Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testBicrystalOpenBoundary.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-open-boundary-" + 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
57 model::DefectiveCrystalBase<3> base(folder.string());
59 model::DislocationNetwork<3> network(container);
60 model::DefectiveCrystalConfigIO<3> saved(folder.string());
61 std::ifstream stream(root/"tests/data/bicrystalBoundary621.txt");
62 require(bool(stream),"Missing bicrystal junction regression fixture");
63 saved.readTxtStream(stream);
64 network.initializeConfiguration(saved,std::ofstream(),std::ofstream());
65 using V=Eigen::Vector3d;
66 const double dt=147.3858585805344;
67 network.trialNodeMotion=true;
68 for(const auto& entry : network.networkNodes())
69 {
70 const auto node=entry.second.lock();
71 node->trySet_P(node->get_P()+dt*node->get_V());
72 }
73 const auto target=network.loops().at(162).lock();
74 std::vector<V> polygon;
75 for(const auto* link : target->linkSequence())
76 {
77 if(!link->source->isPeriodicSubdivision())
78 {
79 polygon.push_back(link->source->get_P());
80 }
81 }
82 // Independent area oracle: the host grain is the slab -length<=x<=0;
83 // its y/z faces are same-grain periodic. Clip only for the test oracle,
84 // without choosing any walk continuation by geometric proximity.
85 for(bool left : {true,false})
86 {
87 std::vector<V> clipped;
88 for(size_t i=0; i<polygon.size(); ++i)
89 {
90 const V& a=polygon[i];
91 const V& b=polygon[(i+1)%polygon.size()];
92 const double da=left ? a.x()+length : -a.x();
93 const double db=left ? b.x()+length : -b.x();
94 if(da>=0)
95 {
96 clipped.push_back(a);
97 }
98 if((da>=0)!=(db>=0))
99 {
100 clipped.push_back(a+da/(da-db)*(b-a));
101 }
102 }
103 polygon=std::move(clipped);
104 }
105 const auto area=[](const std::vector<V>& points)->V
106 {
107 V result=V::Zero();
108 if(!points.empty())
109 {
110 for(size_t i=0; i<points.size(); ++i)
111 {
112 result+=0.5*(points[i]-points.front()).cross(points[(i+1)%points.size()]-points.front());
113 }
114 }
115 return result;
116 };
117 const V expected=area(polygon);
118 require(expected.norm()>1,"Regression target has no resolved slipped area");
119 network.updateBoundaryNodes();
120 network.trialNodeMotion=false;
121 const auto check=[&]()
122 {
123 std::vector<V> actual;
124 for(const auto* link : target->linkSequence())
125 {
126 actual.push_back(link->source->get_P());
127 require(link->sink->next.second->source==link->sink,"Broken loop connectivity");
128 }
129 require((area(actual)-expected).norm()<1.e-8*expected.norm(),
130 "Boundary walk lost or changed a lobe of the retained contour");
131 for(const auto& entry : network.loopNodes())
132 {
133 const auto node=entry.second.lock();
134 require((node->get_P()+node->periodicPlanePatch()->shift-node->networkNode->get_P()).norm()<1.e-7,
135 "Loop/network periodic mapping is inconsistent");
136 }
137 };
138 check();
139 const size_t nodes=network.loopNodes().size();
140 network.updateBoundaryNodes();
141 check();
142 require(network.loopNodes().size()==nodes,"Repeated reconciliation changed contour topology");
144 check();
145 std::filesystem::remove_all(folder);
146 std::cout<<"PASS: frame 621 open-boundary walk, area and periodic mapping\n";
147 return 0;
148 }
149 catch(const std::exception& error)
150 {
151 std::cerr<<error.what()<<'\n';
152 return 1;
153 }
154}
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
a
Definition int_R.m:14
b
Definition int_R.m:16
void require(bool condition, const char *message)
void check(bool ok, const char *message)
void argv
left
void b int argc
vertex p[3]
int i
REAL area
result