Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testPartialPeriodicContraction.cpp
Go to the documentation of this file.
5#include <filesystem>
6#include <fstream>
7#include <iomanip>
8#include <chrono>
9#include <iostream>
10#include <set>
11
12void require(bool condition, const char* message)
13{
14 if(!condition)
15 {
16 throw std::runtime_error(message);
17 }
18}
19
20int main(int argc, char** argv)
21{
22 try
23 {
24 require(argc == 2, "Expected repository root");
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");
34 model::SimplicialMesh<3> mesh(meshFile.string(), Eigen::Matrix3d::Identity(), Eigen::Vector3d::Zero(), {-1});
35 std::vector<int> seeds;
36 for(int axis = 0; axis < 3; ++axis)
37 {
38 for(const auto& region : mesh.regions())
39 {
40 for(const auto& face : region.second->faces())
41 {
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)
45 {
46 seeds.push_back(face.first);
47 }
48 }
49 }
50 }
51 require(seeds.size() == 3, "Expected three cube periodic directions");
52 model::StaticID<model::Polyhedron<3,3-1>>::force_count(0);
53
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)
57 {
58 {
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";
63 }
64 model::DefectiveCrystalBase<3> base(folder.string());
65 require(base.periodicLatticeBasis.cols()==1,"Incorrect active periodic rank");
68 using V=Eigen::Vector3d;
69 Network network(container);
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);
75 const auto a=network.networkNodes().create(start);
76 const auto b=network.networkNodes().create(start);
77 const auto common=network.networkNodes().create(commonPosition);
78 std::vector<std::shared_ptr<Network::LoopType>> loops;
79 const auto makeNode=[&](const auto& loop,const auto& node)
80 {
81 return network.loopNodes().create(loop,node,node->get_P(),loop->periodicGlidePlane->getPatch(V::Zero()),
82 std::make_pair(std::shared_ptr<model::PeriodicPlaneEdge<3>>(),std::shared_ptr<model::PeriodicPlaneEdge<3>>()));
83 };
84 for(int k=0;k<3;++k)
85 {
86 const auto loop=network.loops().create(burgers,plane);
87 loops.push_back(loop);
88 const auto end=k==0 ? a : b;
89 const auto apex=network.networkNodes().create(length*V(0,(k+1)*0.1,0));
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)
93 {
94 std::reverse(nodes.begin(),nodes.end());
95 }
96 network.insertLoop(loop,nodes);
97 }
98 network.trialNodeMotion=true;
99 const V target=length*(scenario==2 ? V(0.7,0.7,0) : V(0.7,0,0));
100 a->trySet_P(target);
101 b->trySet_P(target);
102 network.updateBoundaryNodes();
103 network.trialNodeMotion=false;
104 network.updateGeometry();
105 if(scenario==2)
106 {
107 std::vector<std::shared_ptr<Network::NetworkNodeType>> physical;
108 for(const auto& entry : network.networkNodes())
109 {
110 const auto node=entry.second.lock();
111 for(const auto* ln : node->loopNodes())
112 {
113 if(ln->isPhysicalBoundaryNode())
114 {
115 physical.push_back(node);
116 break;
117 }
118 }
119 }
120 bool contracted=false;
121 for(size_t i=0;i<physical.size() && !contracted;++i)
122 {
123 for(size_t j=i+1;j<physical.size() && !contracted;++j)
124 {
125 if((physical[i]->get_P()-physical[j]->get_P()).norm()<1.e-8 &&
126 physical[i]->meshFaces()==physical[j]->meshFaces())
127 {
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");
132 contracted=true;
133 }
134 }
135 }
136 require(contracted,"Fixture lacks coincident physical face nodes");
137 network.updateBoundaryNodes();
138 // Physical clipping must preserve closure and never create a
139 // periodic continuation through the inactive Y faces.
140 for(const auto& entry : network.loopNodes())
141 {
142 const auto node=entry.second.lock();
143 if(node->isPhysicalBoundaryNode())
144 {
145 require(!node->isPeriodicSubdivision(),"Physical corner became periodic subdivision");
146 }
147 }
148 }
149 else
150 {
151 require(a->loopNodes().size()==1 && b->loopNodes().size()==2,"Fixture lost original junction sharing");
152 size_t before=network.networkNodes().size();
153 require(network.contract(a,b),"Endpoint contraction failed");
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;
157 for(const auto& entry : network.networkNodes())
158 {
159 const auto node=entry.second.lock();
160 if(node->isBoundaryNode() && node->loopNodes().size()==3)
161 {
162 ++sharedCrossings;
163 }
164 }
165 require(sharedCrossings>=2,"Periodic seam lost shared junction subdivisions");
166 network.updateBoundaryNodes();
167 }
168 for(const auto& loop : loops)
169 {
170 require(loop->isLoop(),"Contraction broke loop closure");
171 for(const auto* link : loop->linkSequence())
172 {
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");
176 }
177 }
178 }
179 std::filesystem::remove_all(folder);
180 std::cout<<"PASS: partial periodic junction contraction and physical corners\n";
181 return 0;
182 }
183 catch(const std::exception& error)
184 {
185 std::cerr<<error.what()<<'\n';
186 return 1;
187 }
188}
Eigen::Vector3d V
void updateBoundaryNodes(const std::function< void()> &checkpoint={})
bool contract(std::shared_ptr< NetworkNodeType > nA, std::shared_ptr< NetworkNodeType > nB)
const LoopContainerType & loops() const
Definition LoopNetwork.h:98
const NetworkNodeContainerType & networkNodes() const
const LoopNodeContainerType & loopNodes() const
void insertLoop(const std::shared_ptr< LoopType > &loop, const std::vector< std::shared_ptr< LoopNodeType > > nodes)
A class template that implements a counter of the number of instances of Derived type that are create...
Definition StaticID.h:29
function int_R syms a b c u real f
Definition int_R.m:4
a
Definition int_R.m:14
b
Definition int_R.m:16
LatticePlaneKey< dim > GlidePlaneKey
int regions
Definition triangle.cpp:696
SharedPtrType create(const Args &...args)
model::DislocationNetwork< 3 > Network
void require(bool condition, const char *message)
int end[2]
int j
void argv
int axis
void b int argc
vertex p[3]
int k
int i
apex(top, farvertex)