Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testNodeMotion.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 ("node-motion-" + 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<5; ++scenario)
57 {
58 const int activeAxis=(scenario==0 || scenario==3 || scenario==4) ? 0 : 1;
59 {
60 std::ofstream f(input / "DefectiveCrystal.txt");
61 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\n"
62 << "outputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0;\nEwaldLengthFactor=0;\n";
63 std::ofstream p(input / "polycrystal.txt");
64 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\n"
65 << "C2G1=1 0 0 0 1 0 0 0 1;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
66 << ";\nX0=0 0 0;\nperiodicFaceIDs=";
67 if(activeAxis>=0)
68 {
69 p << seeds[activeAxis];
70 }
71 p << ";\n";
72 }
73 model::DefectiveCrystalBase<3> base(folder.string());
76 using V=Eigen::Vector3d;
77 Network network(container);
78 const auto grain=base.poly.grain(1);
79 const auto plane=base.dislocationDynamics().glidePlaneFactory.getFromKey(model::GlidePlaneKey<3>(V::Zero(),grain->reciprocalLatticeDirection(V::UnitZ())));
80 const V burgers=2.0/std::sqrt(3.0)*V::UnitX();
81
82 const auto first=network.loops().create(burgers,plane);
83 const auto secondPlane=scenario==4 ? base.dislocationDynamics().glidePlaneFactory.getFromKey(
84 model::GlidePlaneKey<3>(V::Zero(),grain->reciprocalLatticeDirection(V::UnitY()))) : plane;
85 const auto second=network.loops().create(2.0*burgers,secondPlane);
86 const bool surface=scenario==2 || scenario==3;
87 const V a=length*(scenario==3 ? V(0.4,0.5,0) : scenario==2 ? V(0.5,0,0) : V(0.4,0,0));
88 const V b=length*V(0.1,0,0);
89 const auto na=network.networkNodes().create(a);
90 const auto nb=network.networkNodes().create(b);
91 const auto makeNode=[&](const auto& loop,const auto& net,const V& position)
92 {
93 return network.loopNodes().create(loop,net,position,loop->periodicGlidePlane->getPatch(V::Zero()),
94 std::make_pair(std::shared_ptr<model::PeriodicPlaneEdge<3>>(),std::shared_ptr<model::PeriodicPlaneEdge<3>>()));
95 };
96 network.insertLoop(first,std::vector<std::shared_ptr<Network::LoopNodeType>>{
97 makeNode(first,na,a),makeNode(first,nb,b),
98 makeNode(first,network.networkNodes().create(length*V(0,0.2,0)),length*V(0,0.2,0))});
99 network.insertLoop(second,std::vector<std::shared_ptr<Network::LoopNodeType>>{
100 makeNode(second,nb,b),makeNode(second,na,a),
101 makeNode(second,network.networkNodes().create(length*(scenario==4 ? V(0,0,-0.2) : V(0,-0.2,0))),length*(scenario==4 ? V(0,0,-0.2) : V(0,-0.2,0)))});
102 network.updateBoundaryNodes();
103 const V requested=length*(scenario==2 ? V(-0.2,0.1,0) : scenario==3 ? V(0.1,-0.2,0) : V(0.3,0,0));
104 na->set_V(requested,true);
105 if(surface)
106 {
107 const int normal=scenario==2 ? 0 : 1;
108 require(std::abs(na->get_V()[normal])<1.e-8,"Physical surface velocity was not projected");
109 }
110 network.moveNodes(1.0);
111 require(!network.trialNodeMotion,"Trial mode leaked after motion");
112 require(first->isLoop() && second->isLoop(),"Motion broke loop closure");
113 if(scenario==1)
114 {
115 require(na->loopNodes().empty(),"Exited original node was not trimmed");
116 bool sharedExit=false;
117 for(const auto* link : first->linkSequence())
118 {
119 const auto node=link->source->networkNode;
120 if(std::abs(node->get_P().x()-0.5*length)<1.e-7 && std::abs(node->get_P().y())<1.e-7)
121 {
122 sharedExit=node->loopNodes().size()==2;
123 }
124 }
125 require(sharedExit,"Physical exit lost junction sharing");
126 }
127 else
128 {
129 const V expected=length*(scenario==2 ? V(0.5,0.1,0) : scenario==3 ? V(0.5,0.5,0) : V(-0.3,0,0));
130 require((na->get_P()-expected).norm()<1.e-7,"Incorrect committed position");
131 require(na->loopNodes().size()==2,"Motion lost original junction identity");
132 require((na->get_V()-(surface ? length*(scenario==2 ? V(0,0.1,0) : V(0.1,0,0)) : requested)).norm()<1.e-7,
133 "Motion discarded velocity state");
134 }
135 for(const auto& entry : network.networkNodes())
136 {
137 const auto node=entry.second.lock();
138 require(base.mesh.search(node->get_P()).first,"Committed a network node outside the RVE");
139 }
140 for(const auto* link : first->linkSequence())
141 {
142 require((link->source->get_P()+link->source->periodicPlanePatch()->shift-link->source->networkNode->get_P()).norm()<1.e-7,
143 "Loop and network positions disagree");
144 if(const auto segment=link->networkLink())
145 {
146 if(segment->loopLinks().size()==2)
147 {
148 require(std::abs(segment->burgers().norm()-burgers.norm())<1.e-7,"Motion changed junction Burgers vector");
149 }
150 }
151 }
152 if(scenario==3)
153 {
154 na->set_V(length*V(0.2,-0.1,0),true);
155 require((na->get_V()-length*V(0.2,0,0)).norm()<1.e-7,"Periodic corner pinned surface sliding");
156 network.moveNodes(1.0);
157 require((na->get_P()-length*V(-0.3,0.5,0)).norm()<1.e-7,"Mixed-corner continuation failed");
158 require(na->loopNodes().size()==2,"Mixed corner split junction ownership");
159 }
160 if(scenario==0)
161 {
162 const V oldPosition=na->get_P();
163 network.trialNodeMotion=true;
164 na->trySet_P(oldPosition+length*V(0.05,0,0));
165 require((na->get_P()-oldPosition).norm()<1.e-8,"Trial motion prematurely committed network position");
166 network.updateBoundaryNodes();
167 network.trialNodeMotion=false;
168 require((na->get_P()-oldPosition-length*V(0.05,0,0)).norm()<1.e-7,"Trial position not committed");
169 require(na->trySet_P(na->get_P()+length*V(0.05,0,0)),"Immediate motion failed");
170 require((na->get_P()-oldPosition-length*V(0.1,0,0)).norm()<1.e-7,"Standalone trySet_P did not commit");
171 }
172 // Repeat with zero motion to exercise retained surface anchors and seams.
173 for(const auto& entry : network.networkNodes())
174 {
175 entry.second.lock()->set_V(V::Zero(),true);
176 }
177 network.moveNodes(1.0);
178 require(first->isLoop() && second->isLoop(),"Repeated motion broke topology");
179 }
180 std::filesystem::remove_all(folder);
181 std::cout << "PASS: periodic crossing, physical exit, surface sliding and mixed corner motion\n";
182 return 0;
183 }
184 catch(const std::exception& error)
185 {
186 std::cerr << error.what() << '\n';
187 return 1;
188 }
189}
Eigen::Vector3d V
void updateBoundaryNodes(const std::function< void()> &checkpoint={})
void moveNodes(const double &dt_in)
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)
void argv
int axis
void b int argc
vertex p[3]
vertex first