25 const std::filesystem::path root(
argv[1]);
26 const auto folder = std::filesystem::temp_directory_path() /
27 (
"partial-contraction-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
28 const auto input = folder /
"inputFiles";
29 std::filesystem::create_directories(input);
30 std::filesystem::create_directories(folder /
"F");
31 std::filesystem::copy_file(root /
"Library/Materials/W.txt", input /
"W.txt");
32 const auto meshFile = root /
"Library/Meshes/unitCube24.msh";
33 std::filesystem::copy_file(meshFile, input /
"mesh.msh");
35 std::vector<int> seeds;
40 for(
const auto& face : region.second->faces())
42 const auto& pair = face.second->periodicFacePair;
43 if(pair.second && pair.first[
axis] > 0.9 &&
44 pair.first.normalized().cross(Eigen::Vector3d::Unit(
axis)).norm() < 1.e-8)
46 seeds.push_back(face.first);
51 require(seeds.size() == 3,
"Expected three cube periodic directions");
54 std::filesystem::copy_file(root /
"Library/DislocationDynamics/DD.txt", input /
"DD.txt");
55 const double length=200.0/std::sqrt(3.0);
56 for(
int scenario=0;scenario<3;++scenario)
59 std::ofstream
f(input/
"DefectiveCrystal.txt");
60 f<<
"physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0;\nEwaldLengthFactor=0;\n";
61 std::ofstream
p(input/
"polycrystal.txt");
62 p<<std::setprecision(17)<<
"materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\nF="<<length<<
" 0 0 0 "<<length<<
" 0 0 0 "<<length<<
";\nX0=0 0 0;\nperiodicFaceIDs="<<seeds[0]<<
";\n";
65 require(base.periodicLatticeBasis.cols()==1,
"Incorrect active periodic rank");
68 using V=Eigen::Vector3d;
70 const auto grain=base.poly.grain(1);
71 const auto plane=base.dislocationDynamics().glidePlaneFactory.getFromKey(
model::GlidePlaneKey<3>(V::Zero(),grain->reciprocalLatticeDirection(V::UnitZ())));
72 const V burgers=2.0/std::sqrt(3.0)*V::UnitX();
73 const V start=length*
V(0.4,0,0);
74 const V commonPosition=length*
V(0.1,0,0);
78 std::vector<std::shared_ptr<Network::LoopType>> loops;
79 const auto makeNode=[&](
const auto& loop,
const auto& node)
81 return network.
loopNodes().
create(loop,node,node->get_P(),loop->periodicGlidePlane->getPatch(V::Zero()),
86 const auto loop=network.
loops().
create(burgers,plane);
87 loops.push_back(loop);
88 const auto end=
k==0 ?
a :
b;
90 std::vector<std::shared_ptr<Network::LoopNodeType>> nodes{
91 makeNode(loop,common),makeNode(loop,
end),makeNode(loop,
apex)};
92 if(scenario==1 &&
k>0)
94 std::reverse(nodes.begin(),nodes.end());
99 const V target=length*(scenario==2 ?
V(0.7,0.7,0) :
V(0.7,0,0));
107 std::vector<std::shared_ptr<Network::NetworkNodeType>> physical;
110 const auto node=entry.second.lock();
111 for(
const auto* ln : node->loopNodes())
113 if(ln->isPhysicalBoundaryNode())
115 physical.push_back(node);
120 bool contracted=
false;
121 for(
size_t i=0;
i<physical.size() && !contracted;++
i)
123 for(
size_t j=
i+1;
j<physical.size() && !contracted;++
j)
125 if((physical[
i]->get_P()-physical[
j]->get_P()).norm()<1.e-8 &&
126 physical[
i]->meshFaces()==physical[
j]->meshFaces())
128 const auto count=physical[
i]->loopNodes().size()+physical[
j]->loopNodes().size();
129 require(network.
contract(physical[
i],physical[
j]),
"Physical face contraction failed");
130 require(physical[
i]->loopNodes().size()+physical[
j]->loopNodes().size()==count,
131 "Physical face contraction lost loop representations");
136 require(contracted,
"Fixture lacks coincident physical face nodes");
140 for(
const auto& entry : network.
loopNodes())
142 const auto node=entry.second.lock();
143 if(node->isPhysicalBoundaryNode())
145 require(!node->isPeriodicSubdivision(),
"Physical corner became periodic subdivision");
151 require(
a->loopNodes().size()==1 &&
b->loopNodes().size()==2,
"Fixture lost original junction sharing");
154 require(network.
networkNodes().size()+1<before,
"Periodic subdivision nodes were not contracted");
155 require(
a->loopNodes().size()==3,
"Contracted endpoint lost shared loop representations");
156 size_t sharedCrossings=0;
159 const auto node=entry.second.lock();
160 if(node->isBoundaryNode() && node->loopNodes().size()==3)
165 require(sharedCrossings>=2,
"Periodic seam lost shared junction subdivisions");
168 for(
const auto& loop : loops)
170 require(loop->isLoop(),
"Contraction broke loop closure");
171 for(
const auto* link : loop->linkSequence())
173 const auto node=link->source;
174 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
175 "Contraction broke periodic position mapping");
179 std::filesystem::remove_all(folder);
180 std::cout<<
"PASS: partial periodic junction contraction and physical corners\n";
183 catch(
const std::exception& error)
185 std::cerr<<error.what()<<
'\n';