Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
StackingFaultTetrahedraGenerator.cpp
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_StackingFaultTetrahedraGenerator_cpp_
9#define model_StackingFaultTetrahedraGenerator_cpp_
10
12#include <numbers>
13#include <chrono>
14#include <random>
15#include <cmath>
16#include <list>
17#include <assert.h>
18#include <Eigen/LU>
19#include <Eigen/Cholesky>
20#include <limits>
21
22//#include <Simplex.h>
23#include <SimplicialMesh.h>
24#include <Polycrystal.h>
26#include <LatticeModule.h>
27//#include <PlaneMeshIntersection.h>
34
36#include <TextFileParser.h>
38#include <MeshBoundarySegment.h>
39#include <GlidePlaneModule.h>
40#include <MeshModule.h>
41#include <Plane.h>
45
46namespace model
47{
48
49// StackingFaultTetrahedraGenerator::StackingFaultTetrahedraGenerator(const std::string& fileName) :
50// /* init */ MicrostructureGeneratorBase(fileName)
51// {
52//
53// }
54
56{
57 if(mg.ddBase.poly.crystalStructure=="FCC")
58 {
59 generateDensityFCC(spec,mg);
60 }
61 else
62 {
63 throw std::runtime_error("StackingFaultTetrahedraGenerator requires FCC crystal structure");
64 }
65}
66
68{
69 if(mg.ddBase.poly.crystalStructure=="FCC")
70 {
71 generateIndividualFCC(spec,mg);
72 }
73 else
74 {
75 throw std::runtime_error("StackingFaultTetrahedraGenerator requires FCC crystal structure");
76 }
77}
78
79
80// void StackingFaultTetrahedraGenerator::generateDensity(MicrostructureGenerator& mg)
81// {
82// if(mg.ddBase.poly.crystalStructure=="FCC")
83// {
84// generateDensityFCC(mg);
85// }
86// else
87// {
88// throw std::runtime_error("StackingFaultTetrahedraGenerator requires FCC crystal structure");
89// }
90// }
91
92// void StackingFaultTetrahedraGenerator::generateIndividual(MicrostructureGenerator& mg)
93// {
94// if(mg.ddBase.poly.crystalStructure=="FCC")
95// {
96// generateIndividualFCC(mg);
97// }
98// else
99// {
100// throw std::runtime_error("StackingFaultTetrahedraGenerator requires FCC crystal structure");
101// }
102// }
103
104bool StackingFaultTetrahedraGenerator::generateSingleSFT(MicrostructureGenerator& mg,const int& planeID,const VectorDimD& basePoint,const bool& inverted,const int& sftSize)
105{
106 if(sftSize>1.0)
107 {
108 std::pair<bool,const Simplex<3,3>*> found=mg.ddBase.mesh.search(basePoint);
109 if(found.first)
110 {
111 const int grainID=found.second->region->regionID;
112 const auto& grain(mg.ddBase.poly.grain(grainID));
113
114
115 if(planeID>=0 && planeID<4)
116 {
117 const auto basePlane(inverted? std::shared_ptr<GlidePlaneBase>(new GlidePlaneBase(grain->planeNormals().at(planeID)->primitiveVectors.second,grain->planeNormals().at(planeID)->primitiveVectors.first,nullptr)) : grain->planeNormals().at(planeID));
118 const auto unitNormal(basePlane->cartesian().normalized());
119 const auto faceBaryShift((basePlane->primitiveVectors.first+basePlane->primitiveVectors.second).cartesian()*sftSize/3.0);
120 const VectorDimD corner(grain->snapToLattice(basePoint-faceBaryShift).cartesian());
121
122 std::vector<VectorDimD> nodePos;
123 nodePos.push_back(corner);
124 nodePos.push_back(corner+basePlane->primitiveVectors.first.cartesian()*sftSize);
125 nodePos.push_back(corner+basePlane->primitiveVectors.second.cartesian()*sftSize);
126 nodePos.push_back((nodePos[0]+nodePos[1]+nodePos[2])/3.0-unitNormal*sftSize*sqrt(2.0/3.0));
127// nodePos.push_back((nodePos[0]+nodePos[1]+nodePos[2])/3.0+unitNormal*sftSize*sqrt(2.0/3.0));
128
129
130 if(mg.allPointsInGrain(nodePos,grainID))
131 {
132 //3 ___________2____________ 3
133 // \ /\ /
134 // \ 230 / \ 132 /
135 // \ / \ /
136 // \ / \ /
137 // \ / 012 \ /
138 // \/__________\/
139 // 0 \ / 1
140 // \ 031 /
141 // \ /
142 // \ /
143 // \ /
144 // \/
145 // 3
146
147 if(true)
148 {// SFT loop 0->1->2 (base Frank loop)
149 std::vector<VectorDimD> facePos012;
150 facePos012.push_back(nodePos[0]);
151 facePos012.push_back(nodePos[1]);
152 facePos012.push_back(nodePos[2]);
153 const auto n012(grain->reciprocalLatticeDirection((nodePos[1]-nodePos[0]).cross(nodePos[2]-nodePos[1])));
154 const VectorDimD b012(n012.interplaneVector());
155 const std::pair<bool,long int> heightPair012=LatticePlane::computeHeight(n012,nodePos[0]);
156 if(!heightPair012.first)
157 {
158 throw std::runtime_error("Cannot determine plane of SFT face 012.");
159 }
160 GlidePlaneKey<3> basePlaneKey012(heightPair012.second, n012);
161 std::shared_ptr<PeriodicGlidePlane<3>> glidePlane012(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(basePlaneKey012));
162 mg.insertJunctionLoop(facePos012, glidePlane012,
163 b012,n012.cartesian().normalized(),
164 nodePos[0],grainID,DislocationLoopIO<3>::SESSILELOOP);
165 }
166
167 if(true)
168 {// SFT loop 2->3->0 (side Shockley loop)
169 std::vector<VectorDimD> facePos230;
170 facePos230.push_back(nodePos[2]);
171 facePos230.push_back(nodePos[3]);
172 facePos230.push_back(nodePos[0]);
173 const auto n230(grain->reciprocalLatticeDirection((nodePos[3]-nodePos[2]).cross(nodePos[0]-nodePos[3])));
174 const VectorDimD b230((0.5*(nodePos[2]+nodePos[0])-nodePos[3]).normalized()*sqrt(3.0)/3.0);
175 const std::pair<bool,long int> heightPair230=LatticePlane::computeHeight(n230,nodePos[2]);
176 if(!heightPair230.first)
177 {
178 throw std::runtime_error("Cannot determine plane of SFT face 230.");
179 }
180 GlidePlaneKey<3> basePlaneKey230(heightPair230.second, n230);
181 std::shared_ptr<PeriodicGlidePlane<3>> glidePlane230(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(basePlaneKey230));
182 mg.insertJunctionLoop(facePos230, glidePlane230,
183 b230,n230.cartesian().normalized(),
184 nodePos[2],grainID,DislocationLoopIO<3>::GLISSILELOOP);
185 }
186
187 if(true)
188 {// SFT loop 0->3->1 (side Shockley loop)
189 std::vector<VectorDimD> facePos031;
190 facePos031.push_back(nodePos[0]);
191 facePos031.push_back(nodePos[3]);
192 facePos031.push_back(nodePos[1]);
193 const auto n031(grain->reciprocalLatticeDirection((nodePos[3]-nodePos[0]).cross(nodePos[1]-nodePos[3])));
194 const VectorDimD b031((0.5*(nodePos[0]+nodePos[1])-nodePos[3]).normalized()*sqrt(3.0)/3.0);
195 const std::pair<bool,long int> heightPair031=LatticePlane::computeHeight(n031,nodePos[0]);
196 if(!heightPair031.first)
197 {
198 throw std::runtime_error("Cannot determine plane of SFT face 031.");
199 }
200 GlidePlaneKey<3> basePlaneKey031(heightPair031.second, n031);
201 std::shared_ptr<PeriodicGlidePlane<3>> glidePlane031(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(basePlaneKey031));
202 mg.insertJunctionLoop(facePos031, glidePlane031,
203 b031,n031.cartesian().normalized(),
204 nodePos[0],grainID,DislocationLoopIO<3>::GLISSILELOOP);
205 }
206
207 if(true)
208 {// SFT loop 1->3->2 (side Shockley loop)
209 std::vector<VectorDimD> facePos132;
210 facePos132.push_back(nodePos[1]);
211 facePos132.push_back(nodePos[3]);
212 facePos132.push_back(nodePos[2]);
213 const auto n132(grain->reciprocalLatticeDirection((nodePos[3]-nodePos[1]).cross(nodePos[2]-nodePos[3])));
214 const VectorDimD b132((0.5*(nodePos[1]+nodePos[2])-nodePos[3]).normalized()*sqrt(3.0)/3.0);
215 const std::pair<bool,long int> heightPair132=LatticePlane::computeHeight(n132,nodePos[1]);
216 if(!heightPair132.first)
217 {
218 throw std::runtime_error("Cannot determine plane of SFT face132.");
219 }
220 GlidePlaneKey<3> basePlaneKey132(heightPair132.second, n132);
221 std::shared_ptr<PeriodicGlidePlane<3>> glidePlane132(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(basePlaneKey132));
222 mg.insertJunctionLoop(facePos132, glidePlane132,
223 b132,n132.cartesian().normalized(),
224 nodePos[1],grainID,DislocationLoopIO<3>::GLISSILELOOP);
225 }
226 return true;
227 }
228 else
229 {
230 std::cout<<"SFT points outside mesh, skipping generation."<<std::endl;
231 return false;
232 }
233 }
234 else
235 {
236 std::cout<<"SFT planeID not a valid index into planeNormals, skipping generation."<<std::endl;
237 return false;
238 }
239 }
240 else
241 {
242 std::cout<<"SFT basePoint outside mesh, skipping generation."<<std::endl;
243 return false;
244 }
245 }
246 else
247 {
248 std::cout<<"SFT size <1b, skipping generation."<<std::endl;
249 return false;
250 }
251
252}
253
254
255void StackingFaultTetrahedraGenerator::generateIndividualFCC(const StackingFaultTetrahedraIndividualSpecification& spec,MicrostructureGenerator& mg)
256{
257 std::cout<<magentaBoldColor<<"Generating individual SFTs"<<defaultColor<<std::endl;
258// const std::vector<int> sftPlaneIDs(this->parser.readArray<int>("sftPlaneIDs",true));
259// const std::vector<int> sftIsInverted(this->parser.readArray<int>("sftIsInverted",true));
260// const std::vector<double> sftSizes(this->parser.readArray<double>("sftSizes",true));
261// const Eigen::Matrix<double,Eigen::Dynamic,3> sftBasePoints(this->parser.readMatrix<double>("sftBasePoints",sftPlaneIDs.size(),dim,true));
262//
263// if(int(sftPlaneIDs.size())!=sftBasePoints.rows())
264// {
265// std::cout<<"sftPlaneIDs.size()="<<sftPlaneIDs.size()<<std::endl;
266// std::cout<<"sftBasePoints.rows()="<<sftBasePoints.rows()<<std::endl;
267// throw std::runtime_error("You must provide one point for each SFT. Each point is a row of the matrix sftBasePoints.");
268// }
269//
270// if(sftPlaneIDs.size()!=sftSizes.size())
271// {
272// std::cout<<"sftPlaneIDs.size()="<<sftPlaneIDs.size()<<std::endl;
273// std::cout<<"sftSizes.size()="<<sftSizes.size()<<std::endl;
274// throw std::runtime_error("You must provide one size for each SFT. Each size is an element of the vector sftSizes.");
275// }
276//
277// if(sftPlaneIDs.size()!=sftIsInverted.size())
278// {
279// std::cout<<"sftPlaneIDs.size()="<<sftPlaneIDs.size()<<std::endl;
280// std::cout<<"sftIsInverted()="<<sftSizes.size()<<std::endl;
281// throw std::runtime_error("You must provide one boolean value of sftIsInverted for each SFT. Each value is an element of the vector sftIsInverted.");
282// }
283
284 size_t ndefects=0;
285 for(size_t k=0;k<spec.planeIDs.size();++k)
286 {
287 const int& planeID(spec.planeIDs[k]);
288 const VectorDimD basePoint(spec.basePoints.row(k));
289 const bool inverted(spec.areInverted[k]);
290 const int sftSize(std::round(spec.sizes[k]/mg.ddBase.poly.b_SI));
291 ndefects+=generateSingleSFT(mg,planeID,basePoint,inverted,sftSize);
292 }
293 std::cout<<"Generated "<<ndefects<<" STFs"<<std::endl;
294
295}
296
297void StackingFaultTetrahedraGenerator::generateDensityFCC(const StackingFaultTetrahedraDensitySpecification& spec,MicrostructureGenerator& mg)
298{
299 std::cout<<magentaBoldColor<<"Generating SFT density"<<defaultColor<<std::endl;
300// const double targetSFTdensity(this->parser.readScalar<double>("targetSFTdensity",true));
301// const double sftSizeMean(this->parser.readScalar<double>("sftSizeMean",true));
302// const double sftSizeStd(this->parser.readScalar<double>("sftSizeStd",true));
303
304
305 if(spec.targetDensity>0.0)
306 {
307 std::mt19937 generator;
308 std::uniform_int_distribution<> planeNormalDistribution(0,3);
309 std::uniform_int_distribution<> invertedThompsonTetrahedronDistribution(0,1);
310 std::normal_distribution<double> sftSizeDistribution(spec.sizeDistributionMean,spec.sizeDistributionStd);
311
312
313 size_t ndefects=0;
314 double defectsDensity=ndefects/mg.ddBase.mesh.volume()/std::pow(mg.ddBase.poly.b_SI,3);
315 while(defectsDensity<spec.targetDensity)
316 {
317 const int sftSize(std::round(sftSizeDistribution(generator)/mg.ddBase.poly.b_SI));
318 ndefects+=generateSingleSFT(mg,planeNormalDistribution(generator),mg.ddBase.poly.randomPoint(),invertedThompsonTetrahedronDistribution(generator),sftSize);
319 defectsDensity=ndefects/mg.ddBase.mesh.volume()/std::pow(mg.ddBase.poly.b_SI,3);
320 std::cout<<"SFT density="<<defectsDensity<<std::endl;
321 }
322 }
323}
324
325}
326#endif
bool insertJunctionLoop(const std::vector< VectorDimD > &loopNodePos, const std::shared_ptr< PeriodicGlidePlane< 3 > > &periodicPlane, const VectorDimD &b, const VectorDimD &unitNormal, const VectorDimD &P0, const size_t &grainID, const DislocationLoopIO< dim >::DislocationLoopType &loopType)
DefectiveCrystalBase< 3 > & ddBase
bool allPointsInGrain(const std::vector< VectorDimD > &points, const int &grainID)
std::pair< bool, const Simplex< _dim, _dim > * > search(const Eigen::Matrix< double, dim, 1 > &P) const
StackingFaultTetrahedraGenerator(const StackingFaultTetrahedraDensitySpecification &, MicrostructureGenerator &mg)
static std::string defaultColor
static std::string magentaBoldColor
LatticePlaneKey< dim > GlidePlaneKey
const Polycrystal< dim > & poly
const SimplicialMesh< dim > & mesh
DislocationDynamicsBase< dim > & dislocationDynamics() const
static std::pair< bool, long int > computeHeight(const ReciprocalLatticeDirection< dim > &r, const VectorDimD &P)
int corner[3]
int k