27 const std::filesystem::path root(
argv[1]);
28 const auto folder = std::filesystem::temp_directory_path() /
29 (
"boundary-junction-" + 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");
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");
39 std::array<int,3> seeds{-1,-1,-1};
42 for(
const auto& face : region.second->faces())
44 const auto& pair=face.second->periodicFacePair;
49 if(pair.first.normalized().cross(Eigen::Vector3d::Unit(
axis)).norm()<1.e-8)
51 seeds[
axis]=face.first;
57 require(seeds[0]>=0 && seeds[1]>=0,
"Missing periodic seeds");
59 const double length=3671.9477120460206;
60 for(
int scenario=0;scenario<6;++scenario)
62 const bool full=scenario==1 || scenario==2;
64 std::ofstream
f(input/
"DefectiveCrystal.txt");
65 f<<
"physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize="<<(full ?
"0 0 0" :
"0")<<
";\nEwaldLengthFactor=0;\n";
66 std::ofstream
p(input/
"polycrystal.txt");
67 p<<std::setprecision(17)<<
"materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\nC2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF="<<length<<
" 0 0 0 "<<length<<
" 0 0 0 "<<length<<
";\nX0=0 0 0;\nperiodicFaceIDs="<<(full ? -1 : seeds[scenario==0 || scenario==5 ? 1 : 0])<<
";\n";
70 require(base.periodicLatticeBasis.cols()==(full ? 3 : 1),
"Incorrect active periodic rank");
73 using V=Eigen::Vector3d;
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();
78 const bool yFace=scenario>=4;
79 const double xFace=scenario>=2 ? -1.0 : 0.0;
80 const V p0=length*(yFace ?
V(-0.7,0.5,0) :
V(xFace,-0.2,0));
81 const V p1=length*(yFace ?
V(-0.3,0.5,0) :
V(xFace,0.2,0));
82 std::vector<std::shared_ptr<Network::LoopType>> loops;
85 const auto loop=network.
loops().
create(burgers,plane);
86 loops.push_back(loop);
87 const V apex=length*(yFace ?
V(-0.5,0.1+0.1*
k,0) :
V(-0.4-0.1*
k,0,0));
88 std::vector<std::shared_ptr<Network::LoopNodeType>> ring;
89 for(
const auto& pos : {p0,
p1,
apex})
92 ring.push_back(network.
loopNodes().
create(loop,node,pos,loop->periodicGlidePlane->getPatch(V::Zero()),
99 const auto sharedLength=[&]()
104 const auto link=entry.second.lock();
105 if(link->loopLinks().size()==2)
107 result+=link->chord().norm();
108 require(std::abs(link->burgers().norm()-2*burgers.norm())<1.e-8,
"Junction Burgers sum changed");
113 require(sharedLength()==0,
"Fixture already contains shared segments");
118 const double joined=sharedLength();
121 require(joined<1.e-8,
"Same-grain periodic seam received physical-boundary junction rule");
125 require(std::abs(joined-(
p1-p0).norm())<1.e-7,
"Physical/GB overlap did not become a shared junction");
127 for(
const auto& loop : loops)
129 require(loop->isLoop(),
"Junction formation broke loop closure");
130 for(
const auto* link : loop->linkSequence())
132 const auto node=link->source;
133 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
134 "Junction formation broke periodic mapping");
138 std::filesystem::remove_all(folder);
139 std::cout<<
"PASS: internal, periodic GB, physical-face and same-grain seam junctions\n";
142 catch(
const std::exception& error)
144 std::cerr<<error.what()<<
'\n';