Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testPolycrystalClosedBoundary.cpp
Go to the documentation of this file.
4#include <filesystem>
5#include <fstream>
6#include <chrono>
7#include <iostream>
8#include <numbers>
9
10void require(bool condition,const char* message)
11{
12 if(!condition)
13 {
14 throw std::runtime_error(message);
15 }
16}
17
18int main(int argc,char** argv)
19{
20 try
21 {
22 require(argc==2,"Expected repository root");
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"})
32 {
33 std::filesystem::copy_file(fixture/name,input/name);
34 }
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");
37 {
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";
40 }
41 model::DefectiveCrystalBase<3> base(folder.string());
43 model::DislocationNetwork<3> network(container);
44 model::DefectiveCrystalConfigIO<3> saved(folder.string());
45 std::ifstream stream(fixture/"evl_34.txt");
46 require(bool(stream),"Missing frame 34 fixture");
47 saved.readTxtStream(stream);
48 network.initializeConfiguration(saved,std::ofstream(),std::ofstream());
49 using V=Eigen::Vector3d;
50 const double dt=101.4090812001895;
51 network.trialNodeMotion=true;
52 for(const auto& entry : network.networkNodes())
53 {
54 const auto node=entry.second.lock();
55 node->trySet_P(node->get_P()+dt*node->get_V());
56 }
57 const auto target=network.loops().at(579).lock();
58 std::vector<V> polygon;
59 for(const auto* link : target->linkSequence())
60 {
61 if(!link->source->isPeriodicSubdivision())
62 {
63 polygon.push_back(link->source->get_P());
64 }
65 }
66 // Independent convex-grain clipping oracle for this central-patch loop.
67 // Only the test uses half-space clipping; production walks port adjacency.
68 for(const auto& entry : target->glidePlane->grain.region.faces())
69 {
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)
74 {
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);
79 if(da>=0)
80 {
81 clipped.push_back(a);
82 }
83 if((da>=0)!=(db>=0))
84 {
85 clipped.push_back(a+da/(da-db)*(b-a));
86 }
87 }
88 polygon=std::move(clipped);
89 }
90 const auto area=[](const std::vector<V>& points)->V
91 {
92 V result=V::Zero();
93 if(!points.empty())
94 {
95 for(size_t i=0; i<points.size(); ++i)
96 {
97 result+=0.5*(points[i]-points.front()).cross(points[(i+1)%points.size()]-points.front());
98 }
99 }
100 return result;
101 };
102 const V expected=area(polygon);
103 require(expected.norm()>1,"Regression target has no resolved slipped area");
104 network.updateBoundaryNodes();
105 network.trialNodeMotion=false;
106 const auto check=[&]()
107 {
108 std::vector<V> actual;
109 for(const auto* link : target->linkSequence())
110 {
111 actual.push_back(link->source->get_P());
112 require(link->sink->next.second->source==link->sink,"Broken loop connectivity");
113 }
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())
117 {
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");
121 }
122 };
123 check();
124 const size_t nodes=network.loopNodes().size();
125 network.updateBoundaryNodes();
126 check();
127 require(network.loopNodes().size()==nodes,"Repeated reconciliation changed contour topology");
129 check();
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";
132 return 0;
133 }
134 catch(const std::exception& error)
135 {
136 std::cerr<<error.what()<<'\n';
137 return 1;
138 }
139}
Eigen::Vector3d V
void updateBoundaryNodes(const std::function< void()> &checkpoint={})
void executeSingleGlideStepDiscreteEvents(const long int &runID)
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 NetworkNodeContainerType & networkNodes() const
const LoopNodeContainerType & loopNodes() const
a
Definition int_R.m:14
b
Definition int_R.m:16
fs::path fixture(const fs::path &root, int rank, int reactions, bool source, const std::string &name="unitCube24.msh")
void check(bool ok, const char *message)
void require(bool condition, const char *message)
void out
void argv
void b int argc
int i
REAL area
result