27 const std::filesystem::path root(
argv[1]);
28 const auto folder = std::filesystem::temp_directory_path() /
29 (
"bicrystal-shared-constraints-" + 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");
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;
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";
51 std::ifstream stream(root/
"tests/data/bicrystalSharedConstraints1915.txt");
52 require(
bool(stream),
"Missing bicrystal junction regression fixture");
55 using Triplets=std::vector<Eigen::Triplet<double>>;
58 Eigen::SparseMatrix<double> sparse(3*network.
networkNodes().size(),3*freeCount);
59 sparse.setFromTriplets(triplets.begin(),triplets.end());
60 const Eigen::MatrixXd Z(sparse);
61 require((Z*Eigen::VectorXd::Ones(Z.cols())-Eigen::VectorXd::Ones(Z.rows())).norm()<1.e-8,
62 "Periodic constraints lost uniform translation or doubled a velocity");
66 const auto node=entry.second.lock();
67 if(node->sID>=975875 && node->sID<=975878)
70 require(node->loopNodes().size()==2,
"Missing shared crossing memberships");
71 for(
const auto* ln : node->loopNodes())
73 require(ln->isPeriodicSubdivision(),
"Fixture no longer exercises periodic interpolation");
74 const auto a=ln->periodicPrev();
75 const auto b=ln->periodicNext();
76 const double da=(ln->get_P()-
a->get_P()).norm();
77 const double db=(ln->get_P()-
b->get_P()).norm();
78 const auto residual=(Z.middleRows(3*node->networkID(),3)
79 -db/(da+db)*Z.middleRows(3*
a->networkNode->networkID(),3)
80 -da/(da+db)*Z.middleRows(3*
b->networkNode->networkID(),3)).eval();
81 require(residual.norm()<1.e-8,
"Shared crossing does not satisfy both loop interpolants");
85 require(shared==4,
"Missing frame 1915 shared crossings");
88 for(
bool reverse : {
false,
true})
91 for(
size_t endpoint : {reverse ? 2UL : 1UL,reverse ? 1UL : 2UL})
98 const auto count=constraints.
append<1>(
t);
99 require(count==2,
"Duplicate periodic relations changed the number of free velocities");
100 Eigen::SparseMatrix<double> transform(5,count);
101 transform.setFromTriplets(
t.begin(),
t.end());
102 const Eigen::MatrixXd
M(transform);
103 require((
M.row(1)-
M.row(2)).norm()<1.e-12,
"Competing endpoint velocities are incompatible");
104 require((
M.row(3)-0.4*
M.row(0)-0.6*
M.row(1)).norm()<1.e-12,
"Incorrect crossing interpolation");
105 require((
M.row(4)-0.8*
M.row(0)-0.2*
M.row(2)).norm()<1.e-12,
"Incorrect second crossing interpolation");
106 require((
M*Eigen::Vector2d::Ones()-Eigen::VectorXd::Ones(5)).norm()<1.e-12,
"Constant velocity changed");
112 directions.
constrain({{2,1/std::sqrt(2.0)},{0,-0.5}});
113 directions.
constrain({{2,1/std::sqrt(2.0)},{1,-0.5}});
115 const auto count=directions.
append<1>(entries);
117 map.setFromTriplets(entries.begin(),entries.end());
118 const Eigen::Vector3d diagonal(1,2,3), force(1,2,4), mode(1,1,1/std::sqrt(2.0));
119 const Eigen::Vector3d expected=mode*(mode.dot(force)/mode.dot(diagonal.cwiseProduct(mode)));
121 require((actual-expected).norm()<1.e-12,
"Direction-aware climb differs from independent reduced balance");
123 "Undriven constrained climb is not stationary");
129 const auto count=constraints.
append<1>(entries);
131 map.setFromTriplets(entries.begin(),entries.end());
133 require((actual-Eigen::Vector3d::Constant(0.5)).norm()<1.e-12,
134 "Force on a dependent zero-mass crossing was lost during reduction");
136 std::filesystem::remove_all(folder);
137 std::cout<<
"PASS: frame 1915 shared periodic constraints, compatibility and uniform translation\n";
140 catch(
const std::exception& error)
142 std::cerr<<error.what()<<
'\n';