Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testBicrystalBoundaryTopology.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
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 ("bicrystal-boundary-topology-" + 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
33 std::filesystem::copy_file(root / "Library/Meshes/bicrystal_48.msh", input / "mesh.msh");
34 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
35 std::filesystem::create_directories(folder / "config");
36 const double length=3671.9477120460206;
37 {
38 std::ofstream f(input / "DefectiveCrystal.txt");
39 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
40 std::ofstream p(input / "polycrystal.txt");
41 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
42 << "C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
43 << ";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
44 }
45 // Match the tutorial remeshing length, without depending on its inputs.
46 {
47 const auto dd=input/"DD.txt";
48 std::ifstream source(dd);
49 std::string contents((std::istreambuf_iterator<char>(source)),std::istreambuf_iterator<char>());
50 const auto location=contents.find("Lmax=100;");
51 require(location!=std::string::npos,"Expected library remeshing default");
52 contents.replace(location,std::string("Lmax=100;").size(),"Lmax=150;");
53 std::ofstream output(dd);
54 output<<contents;
55 }
56 for(int frame : {430,433})
57 {
58 model::DefectiveCrystalBase<3> base(folder.string());
60 model::DislocationNetwork<3> network(container);
61 model::DefectiveCrystalConfigIO<3> saved(folder.string());
62 std::ifstream stream(root/"tests/data"/("bicrystalBoundary"+std::to_string(frame)+".txt"));
63 require(bool(stream),"Missing bicrystal boundary regression fixture");
64 saved.readTxtStream(stream);
65 network.initializeConfiguration(saved,std::ofstream(),std::ofstream());
66 using V=Eigen::Vector3d;
67 const auto areas=[&]()
68 {
69 std::map<size_t,V> result;
70 for(const auto& entry : network.loops())
71 {
72 V area=V::Zero();
73 for(const auto* link : entry.second.lock()->linkSequence())
74 {
75 area+=0.5*link->source->get_P().cross(link->sink->get_P());
76 }
77 result.emplace(entry.first,area);
78 }
79 return result;
80 };
81 const auto check=[&](const std::map<size_t,V>& before,double tolerance)
82 {
83 const auto after=areas();
84 require(after.size()==7 && after.size()==before.size(),"Boundary update split or lost a loop");
85 for(const auto& entry : before)
86 {
87 require((after.at(entry.first)-entry.second).norm()<tolerance*std::max(1.0,entry.second.norm()),
88 "Boundary walk jumped to another contour branch");
89 }
90 for(const auto& entry : network.loopNodes())
91 {
92 const auto node=entry.second.lock();
93 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
94 "Loop/network periodic mapping is inconsistent");
95 }
96 };
97 const auto initial=areas();
98 network.updateBoundaryNodes();
99 check(initial,1.e-10);
100 network.updateBoundaryNodes();
101 check(initial,1.e-10);
102 // The recorded velocities reproduce the 430 branch jump and the
103 // 433 non-closing walk; no field recomputation or tutorial files.
104 network.trialNodeMotion=true;
105 for(const auto& entry : network.networkNodes())
106 {
107 const auto node=entry.second.lock();
108 node->trySet_P(node->get_P()+16.95870980823875*node->get_V());
109 }
110 const auto trial=areas();
111 network.updateBoundaryNodes();
112 network.trialNodeMotion=false;
113 check(trial,1.e-3);
114 const auto clipped=areas();
115 network.updateBoundaryNodes();
116 check(clipped,1.e-10);
117 const auto plasticArea=[&]()
118 {
119 Eigen::Matrix3d result=Eigen::Matrix3d::Zero();
120 for(const auto& entry : areas())
121 {
122 result+=network.loops().at(entry.first).lock()->burgers()*entry.second.transpose();
123 }
124 return result;
125 };
126 const Eigen::Matrix3d plasticBefore=plasticArea();
128 require((plasticArea()-plasticBefore).norm()<1.e-3*std::max(1.0,plasticBefore.norm()),
129 "Junction formation changed Burgers-weighted slipped area");
130 // GB junctions can legitimately split loops. Check the retained
131 // oriented area and mapping instead of requiring unchanged IDs.
132 V areaBefore=V::Zero();
133 V areaAfter=V::Zero();
134 for(const auto& entry : clipped)
135 {
136 areaBefore+=entry.second;
137 }
138 for(const auto& entry : areas())
139 {
140 areaAfter+=entry.second;
141 }
142 require((areaAfter-areaBefore).norm()<1.e-3*std::max(1.0,areaBefore.norm()),
143 "Junction formation changed retained oriented area");
144 for(const auto& entry : network.loops())
145 {
146 require(entry.second.lock()->isLoop(),"Junction formation broke loop closure");
147 }
148 for(const auto& entry : network.loopNodes())
149 {
150 const auto node=entry.second.lock();
151 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
152 "Junction formation broke periodic mapping");
153 }
154 std::cout<<"PASS: bicrystal frame "<<frame<<" topology, mapping, area and remeshing\n";
155 }
156 std::filesystem::remove_all(folder);
157 return 0;
158 }
159 catch(const std::exception& error)
160 {
161 std::cerr<<error.what()<<'\n';
162 return 1;
163 }
164}
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
function int_R syms a b c u real f
Definition int_R.m:4
void require(bool condition, const char *message)
void check(bool ok, const char *message)
void argv
void b int argc
vertex p[3]
REAL area
result