Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testBicrystalCollapse4244.cpp
Go to the documentation of this file.
4#include <filesystem>
5#include <fstream>
6#include <iomanip>
7#include <chrono>
8#include <iostream>
9#include <map>
10#include <iterator>
11#include <array>
12#include <set>
13
14void require(bool condition, const char* message)
15{
16 if(!condition)
17 {
18 throw std::runtime_error(message);
19 }
20}
21
22int main(int argc, char** argv)
23{
24 try
25 {
26 require(argc == 2, "Expected repository root");
27 const std::filesystem::path root(argv[1]);
28 const auto folder = std::filesystem::temp_directory_path() /
29 ("bicrystal-collapse-4244-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
30 const auto input = folder / "inputFiles";
31 std::filesystem::create_directories(input);
32 std::filesystem::create_directories(folder / "F");
33 std::filesystem::copy_file(root / "Library/Materials/W.txt", input / "W.txt");
34
35 std::filesystem::copy_file(root / "Library/Meshes/bicrystal_48.msh", input / "mesh.msh");
36 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
37 std::filesystem::create_directories(folder / "config");
38 const double length=3671.9477120460206;
39 {
40 std::ofstream f(input / "DefectiveCrystal.txt");
41 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
42 std::ofstream p(input / "polycrystal.txt");
43 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
44 << "C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
45 << ";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
46 }
47 // Match the tutorial remeshing length, without depending on its inputs.
48 {
49 const auto dd=input/"DD.txt";
50 std::ifstream source(dd);
51 std::string contents((std::istreambuf_iterator<char>(source)),std::istreambuf_iterator<char>());
52 const auto location=contents.find("Lmax=100;");
53 require(location!=std::string::npos,"Expected library remeshing default");
54 contents.replace(location,std::string("Lmax=100;").size(),"Lmax=150;");
55 std::ofstream output(dd);
56 output<<contents;
57 }
58
59 model::DefectiveCrystalBase<3> base(folder.string());
61 model::DislocationNetwork<3> network(container);
62 model::DefectiveCrystalConfigIO<3> saved(folder.string());
63 std::ifstream stream(root/"tests/data/bicrystalCollapse4244.txt");
64 require(bool(stream),"Missing frame 4244 fixture");
65 saved.readTxtStream(stream);
66 network.initializeConfiguration(saved,std::ofstream(),std::ofstream());
67 require(network.loops().size()==6,"Incomplete junction neighborhood");
68 require(network.loops().at(5860).lock()->currentAreaVector().norm()>1.0,"Initial loop has no slipped area");
69 {
70 const auto loop=network.loops().at(5860).lock();
71 const auto plane=loop->periodicGlidePlane;
72 const Eigen::Vector3d originalApex=network.loopNodes().get(6036331)->get_P();
73 const std::array<Eigen::Vector3d,3> trial{
74 Eigen::Vector3d(3672.8571855755372,480.38042416509757,-1119.2670014528765),
75 Eigen::Vector3d(3671.947712046021,458.39269828388035,-1146.0695536572607),
76 Eigen::Vector3d(3671.947712046021,489.69414114074192,-1106.9427500861839)};
77 for(bool outside : {false,true})
78 {
79 for(size_t start=0;start<3;++start)
80 {
81 for(bool reverse : {false,true})
82 {
83 std::vector<std::pair<Eigen::Vector2d,const int* const>> polygon;
84 for(size_t k=0;k<3;++k)
85 {
86 const size_t i=(start+(reverse ? 3-k : k))%3;
87 polygon.emplace_back(plane->referencePlane->localPosition(i==0 && !outside ? originalApex : trial[i]),nullptr);
88 }
89 const auto contour=plane->polygonPatchIntersection(polygon,false);
90 if(outside)
91 {
92 require(contour.empty(),"Clipped line returned a degenerate contour");
93 }
94 else
95 {
96 require(contour.size()>=3,"Valid nearby slipped area was discarded");
97 double area=0;
98 for(size_t k=0;k<contour.size();++k)
99 {
100 const auto a=std::get<0>(contour[k])-std::get<0>(contour.front());
101 const auto b=std::get<0>(contour[(k+1)%contour.size()])-std::get<0>(contour.front());
102 area+=a.x()*b.y()-a.y()*b.x();
103 }
104 require(std::abs(area)>1.0,"Nearby contour lost its nonzero area");
105 }
106 }
107 }
108 }
109 }
110 network.moveNodes(108.4240043273397);
111 require(network.loops().count(5860)==0,"Collapsed retained line survived as a loop");
112 // Three coincident cap loops collapse together. Their base nodes
113 // belong only to those caps and must disappear; the adjoining three
114 // nonzero-area loops must keep their shared network segments.
115 const std::set<size_t> survivingLoops{5852,5892,5893};
116 require(network.loops().size()==survivingLoops.size(),"Unexpected surviving loop count");
117 for(const auto& entry : network.loops())
118 {
119 require(survivingLoops.count(entry.first) && entry.second.lock()->currentAreaVector().norm()>1.0,
120 "Lost a nonzero-area neighbor");
121 }
122 require(!network.networkLinks().empty(),"Neighboring junction vanished");
123 for(const auto& entry : network.networkLinks())
124 {
125 const auto link=entry.second.lock();
126 std::set<size_t> memberships;
127 Eigen::Vector3d sum=Eigen::Vector3d::Zero();
128 for(const auto* ll : link->loopLinks())
129 {
130 memberships.insert(ll->loop->sID);
131 sum+=(ll->source->networkNode==link->source ? 1.0 : -1.0)*ll->flow().cartesian();
132 }
133 require(memberships==survivingLoops,"Clipping damaged the three-loop junction sharing");
134 require((sum-link->burgers()).norm()<1.e-12,"Shared Burgers sum is inconsistent");
135 }
136 const auto loopCount=network.loops().size();
137 const auto nodeCount=network.networkNodes().size();
138 std::map<std::pair<size_t,size_t>,Eigen::Vector3d> burgers;
139 for(const auto& entry : network.networkLinks())
140 {
141 burgers.emplace(entry.first,entry.second.lock()->burgers());
142 }
143 network.updateBoundaryNodes();
144 require(network.loops().size()==loopCount && network.networkNodes().size()==nodeCount &&
145 network.networkLinks().size()==burgers.size(),"Boundary update is not idempotent");
146 for(const auto& entry : network.networkLinks())
147 {
148 require((entry.second.lock()->burgers().array()==burgers.at(entry.first).array()).all(),"Shared Burgers vector changed");
149 }
150 for(const auto& entry : network.loopNodes())
151 {
152 const auto node=entry.second.lock();
153 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
154 "Periodic loop/network mapping changed");
155 }
156 std::filesystem::remove_all(folder);
157 std::cout<<"PASS: frame 4244 collapsed clipping result and shared boundary junctions\n";
158 return 0;
159 }
160 catch(const std::exception& error)
161 {
162 std::cerr<<error.what()<<'\n';
163 return 1;
164 }
165}
void updateBoundaryNodes(const std::function< void()> &checkpoint={})
void moveNodes(const double &dt_in)
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
NetworkLinkContainerType & networkLinks()
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
SharedPtrType get(const KeyType &key) const
void require(bool condition, const char *message)
void argv
void b int argc
vertex p[3]
int k
int i
REAL area