23 const std::filesystem::path root(
argv[1]);
24 const auto fixture=root/
"tests/data/polycrystal34";
25 const auto folder=std::filesystem::temp_directory_path()/
26 (
"polycrystal-closed-fold-"+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::create_directories(folder/
"config");
31 for(
const auto* name : {
"polycrystal.txt",
"DD.txt"})
33 std::filesystem::copy_file(
fixture/name,input/name);
35 std::filesystem::copy_file(root/
"Library/Materials/W.txt",input/
"W.txt");
36 std::filesystem::copy_file(root/
"Library/Meshes/poly30_periodicXYZ.msh",input/
"poly30_periodicXYZ.msh");
38 std::ofstream
out(input/
"DefectiveCrystal.txt");
39 out<<
"physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
45 std::ifstream stream(
fixture/
"evl_34.txt");
46 require(
bool(stream),
"Missing frame 34 fixture");
49 using V=Eigen::Vector3d;
50 const double dt=101.4090812001895;
54 const auto node=entry.second.lock();
55 node->trySet_P(node->get_P()+dt*node->get_V());
57 const auto target=network.
loops().at(579).lock();
58 std::vector<V> polygon;
59 for(
const auto* link : target->linkSequence())
61 if(!link->source->isPeriodicSubdivision())
63 polygon.push_back(link->source->get_P());
68 for(
const auto& entry : target->glidePlane->grain.region.faces())
70 const auto& face=entry.second;
71 const V normal=face->outNormal(target->glidePlane->grain.grainID);
72 std::vector<V> clipped;
73 for(
size_t i=0;
i<polygon.size();++
i)
75 const V&
a=polygon[
i];
76 const V&
b=polygon[(
i+1)%polygon.size()];
77 const double da=normal.dot(face->center()-
a);
78 const double db=normal.dot(face->center()-
b);
85 clipped.push_back(
a+da/(da-db)*(
b-
a));
88 polygon=std::move(clipped);
90 const auto area=[](
const std::vector<V>& points)->
V
95 for(
size_t i=0;
i<points.size(); ++
i)
97 result+=0.5*(points[
i]-points.front()).cross(points[(
i+1)%points.size()]-points.front());
102 const V expected=
area(polygon);
103 require(expected.norm()>1,
"Regression target has no resolved slipped area");
106 const auto check=[&]()
108 std::vector<V> actual;
109 for(
const auto* link : target->linkSequence())
111 actual.push_back(link->source->get_P());
112 require(link->sink->next.second->source==link->sink,
"Broken loop connectivity");
114 require((
area(actual)-expected).norm()<1.e-8*expected.norm(),
115 "Boundary walk lost or changed a lobe of the retained contour");
116 for(
const auto& entry : network.
loopNodes())
118 const auto node=entry.second.lock();
119 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
120 "Loop/network periodic mapping is inconsistent");
124 const size_t nodes=network.
loopNodes().size();
127 require(network.
loopNodes().size()==nodes,
"Repeated reconciliation changed contour topology");
130 std::filesystem::remove_all(folder);
131 std::cout<<
"PASS: polycrystal frame 34 closed-boundary fold; frame 621 open-boundary walk, area and periodic mapping\n";
134 catch(
const std::exception& error)
136 std::cerr<<error.what()<<
'\n';