Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testBicrystalJunctionCollapse.cpp
Go to the documentation of this file.
5#include <filesystem>
6#include <fstream>
7#include <iomanip>
8#include <chrono>
9#include <iostream>
10#include <map>
11#include <iterator>
12
13void require(bool condition, const char* message)
14{
15 if(!condition)
16 {
17 throw std::runtime_error(message);
18 }
19}
20
21int main(int argc, char** argv)
22{
23 try
24 {
25 require(argc == 2 || argc == 3, "Expected repository root");
26 const std::filesystem::path root(argv[1]);
27 const bool frame283=argc==3 && std::string(argv[2])=="283";
28 const auto folder = std::filesystem::temp_directory_path() /
29 ("bicrystal-junction-collapse-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
30 const auto input = folder / "inputFiles";
31 std::filesystem::create_directories(input);
32 std::filesystem::create_directories(folder / "F");
33 std::filesystem::copy_file(root / "Library/Materials/W.txt", input / "W.txt");
34
35 std::filesystem::copy_file(root / "Library/Meshes/bicrystal_48.msh", input / "mesh.msh");
36 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
37 std::filesystem::create_directories(folder / "config");
38 const double length=3671.9477120460206;
39 {
40 std::ofstream f(input / "DefectiveCrystal.txt");
41 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
42 std::ofstream p(input / "polycrystal.txt");
43 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
44 << "C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
45 << ";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
46 }
47 // Match the tutorial remeshing length, without depending on its inputs.
48 {
49 const auto dd=input/"DD.txt";
50 std::ifstream source(dd);
51 std::string contents((std::istreambuf_iterator<char>(source)),std::istreambuf_iterator<char>());
52 const auto location=contents.find("Lmax=100;");
53 require(location!=std::string::npos,"Expected library remeshing default");
54 contents.replace(location,std::string("Lmax=100;").size(),"Lmax=150;");
55 std::ofstream output(dd);
56 output<<contents;
57 }
58
59 model::DefectiveCrystalBase<3> base(folder.string());
61 model::DislocationNetwork<3> network(container);
62 model::DefectiveCrystalConfigIO<3> saved(folder.string());
63 std::ifstream stream(root/(frame283 ? "tests/data/bicrystalJunction283.txt" : "tests/data/bicrystalJunction596.txt"));
64 require(bool(stream),"Missing bicrystal junction regression fixture");
65 saved.readTxtStream(stream);
66 network.initializeConfiguration(saved,std::ofstream(),std::ofstream());
67 // Saved velocities and the original timestep reproduce the junction
68 // contraction that reduces a triangular loop to two distinct points.
69 network.moveNodes(frame283 ? 272.4170214605611 : 236.5277449432792);
70 network.executeSingleGlideStepDiscreteEvents(frame283 ? 283 : 596);
71 network.updateBoundaryNodes();
72 for(const auto& entry : network.loops())
73 {
74 const auto loop=entry.second.lock();
75 const auto links=loop->linkSequence();
76 size_t anchors=0;
77 for(const auto* link : links)
78 {
79 if(!link->source->isPeriodicSubdivision())
80 {
81 ++anchors;
82 }
83 }
84 require(anchors>=3,"Collapsed periodic contour survived junction reconciliation");
85 require(links.size()>=3,"Collapsed loop survived junction reconciliation");
86 for(const auto* link : links)
87 {
88 require(link->sink->next.second->source==link->sink,"Loop connectivity is broken");
89 }
90 }
91 for(const auto& entry : network.loopNodes())
92 {
93 const auto node=entry.second.lock();
94 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
95 "Junction reconciliation broke the loop/network mapping");
96 }
97 // Reconciliation is idempotent, including the memberships and Burgers
98 // sums of shared network links after removing a collapsed loop.
99 std::map<std::pair<size_t,size_t>,Eigen::Vector3d> burgers;
100 for(const auto& entry : network.networkLinks())
101 {
102 burgers.emplace(entry.first,entry.second.lock()->burgers());
103 }
104 const auto loopCount=network.loops().size();
105 network.updateBoundaryNodes();
106 require(network.loops().size()==loopCount,"Repeated update changed surviving loops");
107 require(network.networkLinks().size()==burgers.size(),"Repeated update changed junction links");
108 for(const auto& entry : network.networkLinks())
109 {
110 require((entry.second.lock()->burgers()-burgers.at(entry.first)).norm()<1.e-12,
111 "Repeated update changed a shared Burgers contribution");
112 }
113 // A near-coincident edge must be treated consistently with the walk's
114 // edge tolerance; a resolvable thin triangle must remain a contour.
115 const auto grain=base.poly.grain(1);
116 const auto plane=base.dislocationDynamics().periodicGlidePlaneFactory.get(model::GlidePlaneKey<3>(Eigen::Vector3d::Zero(),grain->reciprocalLatticeDirection(Eigen::Vector3d::UnitZ())));
117 for(double separation : {1.e-12,1.e-5})
118 {
119 std::vector<std::pair<Eigen::Vector2d,const int* const>> polygon;
120 const Eigen::Vector2d center=plane->referencePlane->localPosition(Eigen::Vector3d(-0.5*length,0,0));
121 polygon.emplace_back(center,nullptr);
122 polygon.emplace_back(center+Eigen::Vector2d(separation,0),nullptr);
123 polygon.emplace_back(center+Eigen::Vector2d(0,10),nullptr);
124 if(separation<1.e-8)
125 {
126 require(plane->polygonPatchIntersection(polygon,false).empty(),
127 "Near-coincident triangle returned a two-point contour");
128 }
129 else
130 {
131 require(plane->polygonPatchIntersection(polygon,false).size()==3,
132 "Resolvable thin triangle was discarded");
133 }
134 }
135 std::filesystem::remove_all(folder);
136 std::cout<<"PASS: junction collapse, shared Burgers contributions and periodic mapping\n";
137 return 0;
138 }
139 catch(const std::exception& error)
140 {
141 std::cerr<<error.what()<<'\n';
142 return 1;
143 }
144}
void updateBoundaryNodes(const std::function< void()> &checkpoint={})
void executeSingleGlideStepDiscreteEvents(const long int &runID)
void moveNodes(const double &dt_in)
void initializeConfiguration(const DefectiveCrystalConfigIO< dim > &configIO, const std::ofstream &f_file, const std::ofstream &F_labels) override
const LoopContainerType & loops() const
Definition LoopNetwork.h:98
const LoopNodeContainerType & loopNodes() const
NetworkLinkContainerType & networkLinks()
function int_R syms a b c u real f
Definition int_R.m:4
LatticePlaneKey< dim > GlidePlaneKey
void require(bool condition, const char *message)
void argv
void b int argc
vertex p[3]