24 const std::filesystem::path root(
argv[1]);
25 const auto folder = std::filesystem::temp_directory_path() /
26 (
"bicrystal-boundary-topology-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
27 const auto input = folder /
"inputFiles";
28 std::filesystem::create_directories(input);
29 std::filesystem::create_directories(folder /
"F");
30 std::filesystem::copy_file(root /
"Library/Materials/W.txt", input /
"W.txt");
32 std::filesystem::copy_file(root /
"Library/Meshes/bicrystal_48.msh", input /
"mesh.msh");
33 std::filesystem::copy_file(root /
"Library/DislocationDynamics/DD.txt", input /
"DD.txt");
34 std::filesystem::create_directories(folder /
"config");
35 const double length=3671.9477120460206;
37 std::ofstream
f(input /
"DefectiveCrystal.txt");
38 f <<
"physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
39 std::ofstream
p(input /
"polycrystal.txt");
40 p << std::setprecision(17) <<
"materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
41 <<
"C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length <<
" 0 0 0 " << length <<
" 0 0 0 " << length
42 <<
";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
46 const auto dd=input/
"DD.txt";
47 std::ifstream source(dd);
48 std::string contents((std::istreambuf_iterator<char>(source)),std::istreambuf_iterator<char>());
49 const auto location=contents.find(
"Lmax=100;");
50 require(location!=std::string::npos,
"Expected library remeshing default");
51 contents.replace(location,std::string(
"Lmax=100;").size(),
"Lmax=150;");
52 std::ofstream output(dd);
56 using V=Eigen::Vector3d;
59 const std::vector<V> outward{V::UnitX(),
V(1,1,0).normalized()};
60 const std::vector<V> equality{V::UnitZ()};
62 require((
corner-
V(0,2,0)).norm()<1.e-10,
"Incorrect corner active set");
64 require(blocked.norm()<1.e-10,
"Corner allowed inward motion");
67 "Opposite host-grain normals were merged");
70 for(
bool mixedCorner : {
false,
true})
75 const auto grain=base.poly.grain(1);
76 const auto plane=base.dislocationDynamics().glidePlaneFactory.getFromKey(
model::GlidePlaneKey<3>(V::Zero(),grain->reciprocalLatticeDirection(V::UnitZ())));
77 const V burgers=2.0/std::sqrt(3.0)*V::UnitX();
79 const auto second=network.
loops().
create(2.0*burgers,plane);
80 const double sign=side==0?1.0:-1.0;
81 const double wall=side==0?0.0:-length;
82 const double top=mixedCorner?0.5*length:0.2*length;
83 const std::vector<V> positions{{wall,-0.2*length,0},{wall,
top,0},
84 {wall-sign*0.3*length,
top,0},{wall-sign*0.3*length,-0.2*length,0}};
86 std::vector<std::shared_ptr<Network::LoopNodeType>>
a,
b;
87 for(
const auto&
p : positions)
92 b.push_back(network.
loopNodes().
create(second,node,
p,second->periodicGlidePlane->getPatch(V::Zero()),
edges));
100 std::vector<std::shared_ptr<Network::NetworkNodeType>> exiting;
103 const auto node=entry.second.lock();
104 node->set_V(V::Zero(),
true);
105 if(std::abs(node->get_P().x()-wall)<1.e-7)
108 require(node->isGrainBoundaryNode(),
"Missing GB node");
109 const V old=node->get_P();
110 node->set_V(
V(-sign,0,0),
true);
111 require(node->get_V().norm()<1.e-10,
"Inward GB velocity was allowed");
112 node->trySet_P(old+
V(-sign,0,0));
113 require((node->get_P()-old).norm()<1.e-8,
"Position commit allowed inward detachment");
114 const V requested(length*
V(sign*0.1,0.05,0));
115 node->set_V(requested,
true);
116 require((node->get_V()-requested).norm()<1.e-8,
"Outward trial velocity was reduced");
117 exiting.push_back(node);
120 require(boundary>=2,
"Missing physical boundary chain");
123 for(
const auto& node : exiting)
125 const V old=node->get_P();
126 node->trySet_P(old+node->get_V());
127 require((node->get_P()-old).norm()<1.e-10,
"Trial motion committed outside grain");
128 for(
const auto* ln : node->loopNodes())
130 require((ln->get_P()+ln->periodicPlanePatch()->shift-old-node->get_V()).norm()<1.e-7,
131 "Junction representations did not share outward trial motion");
137 for(
const auto& node : exiting)
139 require(node->loopNodes().empty(),
"Outside trial anchor was retained after trimming");
141 require(
first->isLoop() && second->isLoop(),
"Trimming broke a loop");
145 const auto node=entry.second.lock();
146 if(node->loopNodes().empty())
150 require(base.mesh.search(node->get_P()).first,
"Network node outside RVE");
151 require(node->get_P().x()<=1.e-7 && node->get_P().x()>=-length-1.e-7,
"Network node left host grain");
152 require(node->loopNodes().size()==2,
"Retrimming split a shared junction");
153 gbNodes+=node->isGrainBoundaryNode();
155 require(gbNodes>=2,
"Lost GB chain after trimming");
158 const auto link=entry.second.lock();
159 require(link->loopLinks().size()==2,
"Replacement segment lost loop sharing");
160 require(std::abs(link->burgers().norm()-3.0*burgers.norm())<1.e-8,
"Changed junction Burgers vector");
161 if(link->isGrainBoundarySegment())
163 require(link->meshLocation()==2,
"GB segment lost physical classification");
166 std::cout<<
"PASS side "<<side<<
" mixed corner "<<mixedCorner<<std::endl;
169 std::filesystem::remove_all(folder);
172 catch(
const std::exception&
e)
174 std::cerr<<
e.what()<<std::endl;