Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testBicrystalOneSidedMotion.cpp
Go to the documentation of this file.
5#include <OneSidedMotion.h>
6#include <filesystem>
7#include <fstream>
8#include <iomanip>
9#include <chrono>
10#include <iostream>
11#include <iterator>
12void require(bool b,const char* message)
13{
14 if(!b)
15 {
16 throw std::runtime_error(message);
17 }
18}
19int main(int argc,char** argv)
20{
21 try
22 {
23 require(argc == 2, "Expected repository root");
24 const std::filesystem::path root(argv[1]);
25 const auto folder = std::filesystem::temp_directory_path() /
26 ("bicrystal-boundary-topology-" + 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::copy_file(root / "Library/Materials/W.txt", input / "W.txt");
31
32 std::filesystem::copy_file(root / "Library/Meshes/bicrystal_48.msh", input / "mesh.msh");
33 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
34 std::filesystem::create_directories(folder / "config");
35 const double length=3671.9477120460206;
36 {
37 std::ofstream f(input / "DefectiveCrystal.txt");
38 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
39 std::ofstream p(input / "polycrystal.txt");
40 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
41 << "C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
42 << ";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
43 }
44 // Match the tutorial remeshing length, without depending on its inputs.
45 {
46 const auto dd=input/"DD.txt";
47 std::ifstream source(dd);
48 std::string contents((std::istreambuf_iterator<char>(source)),std::istreambuf_iterator<char>());
49 const auto location=contents.find("Lmax=100;");
50 require(location!=std::string::npos,"Expected library remeshing default");
51 contents.replace(location,std::string("Lmax=100;").size(),"Lmax=150;");
52 std::ofstream output(dd);
53 output<<contents;
54 }
55
56 using V=Eigen::Vector3d;
58 // A corner with nonorthogonal physical faces must satisfy both inequalities.
59 const std::vector<V> outward{V::UnitX(),V(1,1,0).normalized()};
60 const std::vector<V> equality{V::UnitZ()};
61 const V corner=model::oneSidedMotion<3>(V(-1,2,3),equality,outward);
62 require((corner-V(0,2,0)).norm()<1.e-10,"Incorrect corner active set");
63 const V blocked=model::oneSidedMotion<3>(V(-2,-1,0),equality,outward);
64 require(blocked.norm()<1.e-10,"Corner allowed inward motion");
65 // Opposite normals from two host grains permit only common sliding.
66 require((model::oneSidedMotion<3>(V(1,2,0),equality,{V::UnitX(),-V::UnitX()})-V(0,2,0)).norm()<1.e-10,
67 "Opposite host-grain normals were merged");
68 for(int side : {0,1})
69 {
70 for(bool mixedCorner : {false,true})
71 {
72 model::DefectiveCrystalBase<3> base(folder.string());
74 Network network(container);
75 const auto grain=base.poly.grain(1);
76 const auto plane=base.dislocationDynamics().glidePlaneFactory.getFromKey(model::GlidePlaneKey<3>(V::Zero(),grain->reciprocalLatticeDirection(V::UnitZ())));
77 const V burgers=2.0/std::sqrt(3.0)*V::UnitX();
78 const auto first=network.loops().create(burgers,plane);
79 const auto second=network.loops().create(2.0*burgers,plane);
80 const double sign=side==0?1.0:-1.0;
81 const double wall=side==0?0.0:-length;
82 const double top=mixedCorner?0.5*length:0.2*length;
83 const std::vector<V> positions{{wall,-0.2*length,0},{wall,top,0},
84 {wall-sign*0.3*length,top,0},{wall-sign*0.3*length,-0.2*length,0}};
85 {
86 std::vector<std::shared_ptr<Network::LoopNodeType>> a,b;
87 for(const auto& p : positions)
88 {
89 const auto node=network.networkNodes().create(p);
90 const auto edges=std::make_pair(std::shared_ptr<model::PeriodicPlaneEdge<3>>(),std::shared_ptr<model::PeriodicPlaneEdge<3>>());
91 a.push_back(network.loopNodes().create(first,node,p,first->periodicGlidePlane->getPatch(V::Zero()),edges));
92 b.push_back(network.loopNodes().create(second,node,p,second->periodicGlidePlane->getPatch(V::Zero()),edges));
93 }
94 network.insertLoop(first,a);
95 network.insertLoop(second,b);
96 }
97 network.updateBoundaryNodes();
98 network.updateGeometry();
99 size_t boundary=0;
100 std::vector<std::shared_ptr<Network::NetworkNodeType>> exiting;
101 for(const auto& entry : network.networkNodes())
102 {
103 const auto node=entry.second.lock();
104 node->set_V(V::Zero(),true);
105 if(std::abs(node->get_P().x()-wall)<1.e-7)
106 {
107 ++boundary;
108 require(node->isGrainBoundaryNode(),"Missing GB node");
109 const V old=node->get_P();
110 node->set_V(V(-sign,0,0),true);
111 require(node->get_V().norm()<1.e-10,"Inward GB velocity was allowed");
112 node->trySet_P(old+V(-sign,0,0));
113 require((node->get_P()-old).norm()<1.e-8,"Position commit allowed inward detachment");
114 const V requested(length*V(sign*0.1,0.05,0));
115 node->set_V(requested,true);
116 require((node->get_V()-requested).norm()<1.e-8,"Outward trial velocity was reduced");
117 exiting.push_back(node);
118 }
119 }
120 require(boundary>=2,"Missing physical boundary chain");
121 // Trial movement must affect all loop representations, not network P.
122 network.trialNodeMotion=true;
123 for(const auto& node : exiting)
124 {
125 const V old=node->get_P();
126 node->trySet_P(old+node->get_V());
127 require((node->get_P()-old).norm()<1.e-10,"Trial motion committed outside grain");
128 for(const auto* ln : node->loopNodes())
129 {
130 require((ln->get_P()+ln->periodicPlanePatch()->shift-old-node->get_V()).norm()<1.e-7,
131 "Junction representations did not share outward trial motion");
132 }
133 }
134 network.updateBoundaryNodes();
135 network.trialNodeMotion=false;
136 network.updateGeometry();
137 for(const auto& node : exiting)
138 {
139 require(node->loopNodes().empty(),"Outside trial anchor was retained after trimming");
140 }
141 require(first->isLoop() && second->isLoop(),"Trimming broke a loop");
142 size_t gbNodes=0;
143 for(const auto& entry : network.networkNodes())
144 {
145 const auto node=entry.second.lock();
146 if(node->loopNodes().empty())
147 {
148 continue;
149 }
150 require(base.mesh.search(node->get_P()).first,"Network node outside RVE");
151 require(node->get_P().x()<=1.e-7 && node->get_P().x()>=-length-1.e-7,"Network node left host grain");
152 require(node->loopNodes().size()==2,"Retrimming split a shared junction");
153 gbNodes+=node->isGrainBoundaryNode();
154 }
155 require(gbNodes>=2,"Lost GB chain after trimming");
156 for(const auto& entry : network.networkLinks())
157 {
158 const auto link=entry.second.lock();
159 require(link->loopLinks().size()==2,"Replacement segment lost loop sharing");
160 require(std::abs(link->burgers().norm()-3.0*burgers.norm())<1.e-8,"Changed junction Burgers vector");
161 if(link->isGrainBoundarySegment())
162 {
163 require(link->meshLocation()==2,"GB segment lost physical classification");
164 }
165 }
166 std::cout<<"PASS side "<<side<<" mixed corner "<<mixedCorner<<std::endl;
167 }
168 }
169 std::filesystem::remove_all(folder);
170 return 0;
171 }
172 catch(const std::exception& e)
173 {
174 std::cerr<<e.what()<<std::endl;
175 return 1;
176 }
177}
Eigen::Vector3d V
void updateBoundaryNodes(const std::function< void()> &checkpoint={})
const LoopContainerType & loops() const
Definition LoopNetwork.h:98
const NetworkNodeContainerType & networkNodes() const
const LoopNodeContainerType & loopNodes() const
NetworkLinkContainerType & networkLinks()
void insertLoop(const std::shared_ptr< LoopType > &loop, const std::vector< std::shared_ptr< LoopNodeType > > nodes)
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
Eigen::Matrix< double, dim, 1 > oneSidedMotion(const Eigen::Matrix< double, dim, 1 > &requested, const std::vector< Eigen::Matrix< double, dim, 1 > > &equalities, const std::vector< Eigen::Matrix< double, dim, 1 > > &outward)
LatticePlaneKey< dim > GlidePlaneKey
SharedPtrType create(const Args &...args)
void require(bool b, const char *message)
model::DislocationNetwork< 3 > Network
int corner[3]
m edges
void argv
void b int argc
vertex p[3]
int e
vertex first
struct otri top