Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testEnclosedJunctionOwnership.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 ("periodic-fields-" + 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
53 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
54 const double length=200.0/std::sqrt(3.0);
55 for(int activeAxis : {-1,2})
56 {
57 const bool periodic=activeAxis==0;
58 {
59 std::ofstream f(input / "DefectiveCrystal.txt");
60 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\n"
61 << "outputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0;\nEwaldLengthFactor=0;\n";
62 std::ofstream p(input / "polycrystal.txt");
63 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\n"
64 << "C2G1=1 0 0 0 1 0 0 0 1;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
65 << ";\nX0=0 0 0;\nperiodicFaceIDs=";
66 if(activeAxis>=0)
67 {
68 p << seeds[activeAxis];
69 }
70 p << ";\n";
71 }
72 model::DefectiveCrystalBase<3> base(folder.string());
75 using V=Eigen::Vector3d;
76 Network network(container);
77 const auto grain=base.poly.grain(1);
78 const auto plane=base.dislocationDynamics().glidePlaneFactory.getFromKey(model::GlidePlaneKey<3>(V::Zero(),grain->reciprocalLatticeDirection(V::UnitZ())));
79 const V burgers=2.0/std::sqrt(3.0)*V::UnitX();
80 const std::array<V,4> positions{length*V(-.8,-.8,0),length*V(.8,-.8,0),length*V(.8,.8,0),length*V(-.8,.8,0)};
81 std::vector<std::shared_ptr<Network::NetworkNodeType>> owners;
82 for(const auto& p : positions)
83 {
84 owners.push_back(network.networkNodes().create(0.5*p));
85 }
86 std::vector<std::shared_ptr<Network::LoopType>> loops;
87 for(size_t family=0;family<3;++family)
88 {
89 const auto loop=network.loops().create(burgers,plane);
90 loops.push_back(loop);
91 std::vector<std::shared_ptr<Network::LoopNodeType>> nodes;
92 for(size_t k=0;k<positions.size();++k)
93 {
94 const size_t index=family==1 ? positions.size()-1-k : k;
95 const auto net=family==2 ? network.networkNodes().create(0.5*positions[index]) : owners[index];
96 nodes.push_back(network.loopNodes().create(loop,net,positions[index],loop->periodicGlidePlane->getPatch(V::Zero()),
97 std::make_pair(std::shared_ptr<model::PeriodicPlaneEdge<3>>(),std::shared_ptr<model::PeriodicPlaneEdge<3>>())));
98 }
99 network.insertLoop(loop,nodes);
100 }
101 network.updateBoundaryNodes();
102 std::set<size_t> sharedIDs;
103 for(const auto* link : loops[0]->linkSequence())
104 {
105 const auto segment=link->networkLink();
106 require(segment && segment->loopLinks().size()==2,"Enclosure lost shared contour ownership");
107 require(segment->burgers().norm()<1.e-12,"Opposite enclosed loops no longer cancel");
108 sharedIDs.insert(link->source->networkNode->sID);
109 }
110 require(sharedIDs.size()==4,"Incorrect enclosed face contour");
111 for(const auto* link : loops[2]->linkSequence())
112 {
113 require(!sharedIDs.count(link->source->networkNode->sID),"Unrelated enclosing loop acquired junction sharing");
114 require(link->networkLink()->loopLinks().size()==1,"Unrelated loop was merged");
115 }
116 // The reconciliation stage must retain cancelling lobes too, not
117 // only the geometry-only walk exercised in testPeriodicPolygonWalk.
118 const auto balanced=network.loops().create(burgers,plane);
119 std::vector<std::shared_ptr<Network::LoopNodeType>> balancedNodes;
120 const std::array<V,4> balancedPositions{length*V(-.2,-.2,0),length*V(.2,.2,0),length*V(-.2,.2,0),length*V(.2,-.2,0)};
121 for(const V& position : balancedPositions)
122 {
123 balancedNodes.push_back(network.loopNodes().create(balanced,network.networkNodes().create(position),position,
124 balanced->periodicGlidePlane->getPatch(V::Zero()),
125 std::make_pair(std::shared_ptr<model::PeriodicPlaneEdge<3>>(),std::shared_ptr<model::PeriodicPlaneEdge<3>>())));
126 }
127 network.insertLoop(balanced,balancedNodes);
128 network.updateBoundaryNodes();
129 require(balanced->isLoop() && balanced->linkSequence().size()==4,"Cancelling lobes were deleted during reconciliation");
130 const auto nodeCount=network.networkNodes().size();
131 network.updateBoundaryNodes();
132 require(network.networkNodes().size()==nodeCount,"Enclosed boundary update is not idempotent");
133 for(const auto* link : loops[0]->linkSequence())
134 {
135 require(sharedIDs.count(link->source->networkNode->sID),"Repeated update changed enclosed junction identity");
136 }
137 }
138 std::cout<<"PASS: enclosure preserves shared ownership and separates unrelated loops\n";
139 }
140 catch(const std::exception& error)
141 {
142 std::cerr<<error.what()<<std::endl;
143 return 1;
144 }
145 return 0;
146}
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
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
LatticePlaneKey< dim > GlidePlaneKey
int regions
Definition triangle.cpp:696
SharedPtrType create(const Args &...args)
void periodic(const Trial &field, double relative=1.e-10)
model::DislocationNetwork< 3 > Network
void require(bool condition, const char *message)
void argv
int index
int axis
void b int argc
vertex p[3]
int k