Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testCrossSlipOptimizations.cpp
Go to the documentation of this file.
3#include <CrossSlipModels.h>
4#include <filesystem>
5#include <fstream>
6#include <iomanip>
7#include <chrono>
8#include <iostream>
9#ifdef _OPENMP
10#include <omp.h>
11#endif
13void require(bool condition,const char* message)
14{
15 if(!condition)
16 {
17 throw std::runtime_error(message);
18 }
19}
20// Reference algorithms from before the cross-slip allocation optimizations.
21std::pair<bool,int> legacyBase(const Network::NetworkLinkType& link,
23 const bool enforceRemeshLength=true)
24{
25 if( !link.isBoundarySegment()
26 && !link.isGrainBoundarySegment()
27 && link.loopLinks().size()==1
28 && link.unitDirection().cross(link.burgers().normalized()).norm()<=model.sinCrossSlip
29 && link.chordLength()>FLT_EPSILON
30 && (!enforceRemeshLength || link.chordLength()>2.0*link.network().networkRemesher.Lmin)
31 && link.grains().size()==1
32 )
33 {
34 if((*link.loopLinks().begin())->loop->slipSystem())
35 {
36 const auto& grain(**link.grains().begin());
37 return std::make_pair(true,grain.grainID);
38 }
39 }
40 return std::make_pair(false,-1);
41 }
42std::pair<bool,std::pair<int,int>> legacySelection(const Network::NetworkLinkType& link,
44{
45
46 const auto isBaseCSLink(legacyBase(link,model));
47
48 if(isBaseCSLink.first)
49 {
50 // Find slip system on which screw segment has highest glide force
51 const auto loop((*link.loopLinks().begin())->loop);
52 const auto slipSystem(loop->slipSystem());
53 if(slipSystem)
54 {
55 const auto& grain(**link.grains().begin());
56 const auto pki=link.pkIntegral();
57 const double pkGlide=std::fabs((pki-pki.dot(slipSystem->unitNormal)*slipSystem->unitNormal).norm());
58
59 std::map<double,int> ssMap;
60 for(size_t s=0;s<grain.slipSystems().size();++s)
61 {
62 const auto& crossSlipSystem(grain.slipSystems().at(s));
63 if((loop->flow()-crossSlipSystem->s).squaredNorm()==0)
64 {
65 const double pkCross=std::fabs((pki-pki.dot(crossSlipSystem->unitNormal)*crossSlipSystem->unitNormal).norm());
66 ssMap.emplace(pkCross,s);
67 }
68 }
69
70 if(ssMap.size())
71 {
72 const auto& crossSlipSystem(grain.slipSystems().at(ssMap.rbegin()->second));
73 if(slipSystem->unitNormal.cross(crossSlipSystem->unitNormal).squaredNorm()>FLT_EPSILON
74 && ssMap.rbegin()->first>1.1*pkGlide)
75 {// highest glide PK-force is not on current slip system
76 return std::make_pair(true,std::make_pair(grain.grainID,ssMap.rbegin()->second));
77 }
78 }
79 }
80 }
81 return std::make_pair(false,std::make_pair(-1,-1));
82 }
83void verify(Network& network)
84{
85 network.updateGeometry();
87 for(const auto& entry : network.loops())
88 {
89 const auto loop=entry.second.lock();
90 std::map<size_t,const Network::LoopLinkType*> ordered;
91 for(const auto* link : loop->loopLinks())
92 {
93 ordered.emplace(link->source->sID,link);
94 }
95 const auto sequence=loop->linkSequence();
96 require(sequence.size()==loop->loopLinks().size(),"Loop traversal count changed");
97 if(!ordered.empty())
98 {
99 const auto* current=ordered.begin()->second;
100 for(const auto* link : sequence)
101 {
102 require(link==current,"Loop traversal or cyclic start changed");
103 current=current->next;
104 }
105 }
106 }
107 size_t eligible=0,selected=0;
108 for(const auto& entry : network.networkLinks())
109 {
110 const auto link=entry.second.lock();
111 link->createQuadraturePoints(false);
112 link->updateQuadraturePoints(false);
113 for(bool enforceLength : {false,true})
114 {
115 require(model.isBaseCrossSlipLink(*link,enforceLength)==legacyBase(*link,model,enforceLength),
116 "Cross-slip eligibility changed");
117 }
118 const auto legacy=legacySelection(*link,model);
119 require(model.isCrossSlipLink(*link)==legacy,"Cross-slip target or tie-breaking changed");
120 eligible+=legacyBase(*link,model).first;
121 selected+=legacy.first;
122 // Zero force exercises exact ties between every compatible plane.
123 std::vector<Eigen::Vector3d> forces;
124 for(auto& point : link->quadraturePoints())
125 {
126 forces.push_back(point.pkForce);
127 point.pkForce.setZero();
128 }
129 require(model.isCrossSlipLink(*link)==legacySelection(*link,model),"Equal-force selection changed");
130 size_t k=0;
131 for(auto& point : link->quadraturePoints())
132 {
133 point.pkForce=forces[k++];
134 }
135 }
136 std::cout<<"Cross-slip reference: "<<eligible<<" eligible, "<<selected<<" selected links; exact agreement\n";
137}
138int main(int argc, char** argv)
139{
140 try
141 {
142 require(argc == 2 || argc == 3, "Expected repository root");
143 const std::filesystem::path root(argv[1]);
144 if(argc==3 && std::filesystem::is_directory(argv[2]))
145 {
146#ifdef _OPENMP
147 omp_set_num_threads(12);
148#endif
150 model::DefectiveCrystalConfigIO<3> saved(base.simulationParameters.traitsIO.configFolder);
151 saved.read(base.simulationParameters.runID);
152 model::DefectiveCrystal<3> crystal(base);
153 crystal.initializeConfiguration(saved);
154 const auto network=crystal.getUniqueTypedMicrostructure<Network>();
155 require(bool(network) && !network->computeDDinteractions,"Benchmark requires DD with interactions disabled");
156 verify(*network);
157 return 0;
158 }
159 const auto folder = std::filesystem::temp_directory_path() /
160 ("cross-slip-optimization-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
161 const auto input = folder / "inputFiles";
162 std::filesystem::create_directories(input);
163 std::filesystem::create_directories(folder / "F");
164 std::filesystem::copy_file(root / "Library/Materials/W.txt", input / "W.txt");
165
166 std::filesystem::copy_file(root / "Library/Meshes/bicrystal_48.msh", input / "mesh.msh");
167 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
168 std::filesystem::create_directories(folder / "config");
169 const double length=3671.9477120460206;
170 {
171 std::ofstream f(input / "DefectiveCrystal.txt");
172 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
173 std::ofstream p(input / "polycrystal.txt");
174 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
175 << "C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
176 << ";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
177 }
178 model::DefectiveCrystalBase<3> base(folder.string());
179 model::MicrostructureContainer<3> container(base);
180 model::DislocationNetwork<3> network(container);
181 model::DefectiveCrystalConfigIO<3> saved(folder.string());
182 std::ifstream stream(argc==3 ? std::filesystem::path(argv[2]) : root/"tests/data/bicrystalSharedConstraints1915.txt");
183 require(bool(stream),"Missing bicrystal junction regression fixture");
184 saved.readTxtStream(stream);
185 network.initializeConfiguration(saved,std::ofstream(),std::ofstream());
186 network.computeDDinteractions=false;
187#ifdef _OPENMP
188 omp_set_num_threads(argc==3 ? 12 : 2);
189#endif
190 verify(network);
191 if(argc==2)
192 {
193 std::shared_ptr<Network::NetworkLinkType> shared;
194 for(const auto& entry : network.networkLinks())
195 {
196 const auto link=entry.second.lock();
197 if(link->loopLinks().size()>1 && link->chordLength()>1 && !link->isBoundarySegment())
198 {
199 shared=link;
200 break;
201 }
202 }
203 require(bool(shared),"Missing shared junction for topology-change test");
204 const auto memberships=shared->loopLinks().size();
205 auto inserted=network.networkNodes().create(shared->get_r(0.5));
206 network.expandNetworkLink(shared,inserted);
207 shared.reset();
208 require(inserted->loopNodes().size()==memberships,"Expansion lost junction sharing");
209 verify(network);
210 network.removeNetworkNode(inserted->sID);
211 inserted.reset();
212 verify(network);
213 }
214 std::filesystem::remove_all(folder);
215 std::cout<<"PASS: exact cross-slip traversal and selection equivalence before and after shared junction topology changes\n";
216 return 0;
217 }
218 catch(const std::exception& error)
219 {
220 std::cerr<<error.what()<<'\n';
221 return 1;
222 }
223}
void initializeConfiguration(const DefectiveCrystalConfigIO< dim > &configIO)
DefectiveCrystalBase< dim > & ddBase
TraitsType::NetworkLinkType NetworkLinkType
void initializeConfiguration(const DefectiveCrystalConfigIO< dim > &configIO, const std::ofstream &f_file, const std::ofstream &F_labels) override
const VectorDim & burgers() const
GrainContainerType grains() const
const LoopContainerType & loops() const
Definition LoopNetwork.h:98
const NetworkNodeContainerType & networkNodes() const
NetworkLinkContainerType & networkLinks()
SharedNetworkNodePtrType expandNetworkLink(const std::shared_ptr< NetworkLinkType > &Lij, const SharedNetworkNodePtrType &networkNode)
void removeNetworkNode(const size_t &nodeID)
const LoopNetworkType & network() const
Definition NetworkBase.h:57
const VectorDim & unitDirection() const
const double & chordLength() const
function int_R syms a b c u real f
Definition int_R.m:4
DefectiveCrystalParameters simulationParameters
const DefectiveCrystalTraitsIO traitsIO
std::shared_ptr< MicrostructureType > getUniqueTypedMicrostructure() const
SharedPtrType create(const Args &...args)
void verify(Network &network)
std::pair< bool, std::pair< int, int > > legacySelection(const Network::NetworkLinkType &link, const model::AthermalCrossSlipModel< model::TypeTraits< Network >::dim > &model)
std::pair< bool, int > legacyBase(const Network::NetworkLinkType &link, const model::AthermalCrossSlipModel< model::TypeTraits< Network >::dim > &model, const bool enforceRemeshLength=true)
model::DislocationNetwork< 3 > Network
void require(bool condition, const char *message)
void argv
void b int argc
vertex p[3]
int k
int current