26 const std::filesystem::path root(
argv[1]);
27 const auto folder = std::filesystem::temp_directory_path() /
28 (
"prismatic-atomic-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
29 const auto input = folder /
"inputFiles";
30 std::filesystem::create_directories(input);
31 std::filesystem::create_directories(folder /
"F");
32 std::filesystem::copy_file(root /
"Library/Materials/W.txt", input /
"W.txt");
34 std::filesystem::copy_file(root /
"Library/Meshes/bicrystal_48.msh", input /
"mesh.msh");
35 std::filesystem::copy_file(root /
"Library/DislocationDynamics/DD.txt", input /
"DD.txt");
36 std::filesystem::create_directories(folder /
"config");
37 const double length=3671.9477120460206;
39 std::ofstream
f(input /
"DefectiveCrystal.txt");
40 f <<
"physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
41 std::ofstream
p(input /
"polycrystal.txt");
42 p << std::setprecision(17) <<
"materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
43 <<
"C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length <<
" 0 0 0 " << length <<
" 0 0 0 " << length
44 <<
";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
47 using V=Eigen::Vector3d;
49 const auto snapshot=[&]()
51 std::ostringstream
out;
52 out<<std::setprecision(17);
53 for(
const auto&
x : generator.config().nodes())
57 for(
const auto&
x : generator.config().loops())
61 for(
const auto&
x : generator.config().loopNodes())
65 for(
const auto&
x : generator.config().loopLinks())
69 for(
const auto&
x : generator.uniqueNetworkNodeMap)
71 out<<
x.first.transpose()<<
' '<<
x.second<<
'\n';
75 const auto insert=[&](
const V& center,
const double steps)
78 spec.slipSystemIDs={0};
79 spec.loopRadii={1.e-7};
80 spec.glideSteps={steps};
81 spec.loopCenters.resize(1,3);
82 spec.loopCenters.row(0)=center;
83 generator.addPrismaticLoopIndividual(spec);
85 const auto reject=[&](
const V& center,
const double steps)
87 const auto before=snapshot();
93 catch(
const std::runtime_error&)
97 require(rejected,
"Prism crossing into another grain was accepted");
98 require(snapshot()==before,
"Failed prism changed loops, nodes, links or the node map");
101 reject(
V(-0.02*length,0,0),50);
102 require(generator.config().loops().empty() && generator.config().nodes().empty() &&
103 generator.config().loopNodes().empty() && generator.config().loopLinks().empty() &&
104 generator.uniqueNetworkNodeMap.empty(),
"Failed first prism left residual topology");
105 insert(
V(-0.5*length,0,0),50);
106 require(generator.config().loops().size()==7,
"Contained prism is incomplete");
108 reject(
V(-0.02*length,0,0),50);
109 reject(
V(-0.98*length,0,0),50);
111 reject(
V(-0.5*length,0,0),10000);
112 reject(
V(-0.5*length,0,0),-10000);
113 const size_t oldLoops=generator.config().loops().size();
115 insert(
V(-0.5*length,0.49*length,0.49*length),50);
116 require(generator.config().loops().size()==oldLoops+7,
"Same-grain periodic prism is incomplete");
118 std::map<std::pair<size_t,size_t>,
V> burgers;
119 std::set<std::pair<size_t,size_t>> baseEdges;
120 for(
const auto& node : generator.config().loopNodes())
122 shifted+=node.periodicShift.norm()>1.e-8;
124 require(shifted>0,
"Periodic acceptance test never crossed a seam");
125 for(
const auto& link : generator.config().loopLinks())
127 if(link.hasNetworkLink)
129 const auto& source=generator.config().loopNodes().at(link.sourceID);
130 const auto& sink=generator.config().loopNodes().at(link.sinkID);
131 const auto& loop=generator.config().loops().at(link.loopID);
132 const auto key=std::make_pair(std::min(source.networkNodeID,sink.networkNodeID),
133 std::max(source.networkNodeID,sink.networkNodeID));
134 auto entry=burgers.emplace(
key,V::Zero()).first;
135 entry->second+=(source.networkNodeID<sink.networkNodeID? 1.0 : -1.0)*loop.B;
138 baseEdges.insert(
key);
142 require(!baseEdges.empty(),
"No sessile base edges tested");
143 for(
const auto&
key : baseEdges)
145 require(burgers.at(
key).norm()<1.e-10,
"Prism base edge lacks Burgers cancellation");
147 reject(
V(-0.02*length,0,0),50);
148 std::filesystem::remove_all(folder);
149 std::cout<<
"PASS: atomic prism rejection, same-grain periodic crossings and base cancellation\n";
152 catch(
const std::exception& error)
154 std::cerr<<error.what()<<
'\n';