Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
FrankLoopsGenerator.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_FrankLoopsGenerator_cpp_
9#define model_FrankLoopsGenerator_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>
43#include <FrankLoopsGenerator.h>
45
46namespace model
47{
48
49//FrankLoopsGenerator::FrankLoopsGenerator(const std::string& fileName) :
50// /* init */ MicrostructureGeneratorBase(fileName)
51// {
52//
53// }
54
56 {
57 std::cout<<magentaBoldColor<<"Generating Frank loop density"<<defaultColor<<std::endl;
58// const double targetDensity(this->parser.readScalar<double>("targetDensity",true));
59 if(spec.targetDensity>0.0)
60 {
61// const int numberOfSides(this->parser.readScalar<int>("numberOfSides",true));
62// const double radiusDistributionMean(this->parser.readScalar<double>("radiusDistributionMean",true));
63// const double radiusDistributionStd(this->parser.readScalar<double>("radiusDistributionStd",true));
64// const int areVacancyLoops(this->parser.readScalar<int>("areVacancyLoops",true));
65
66 std::normal_distribution<double> radiusDistribution(spec.radiusDistributionMean/mg.ddBase.poly.b_SI,spec.radiusDistributionStd/mg.ddBase.poly.b_SI);
67 std::mt19937 generator;
68
69 std::uniform_int_distribution<> allowedPlaneDist(0,spec.allowedPlaneIDs.size()-1);
70
71 std::set<int> allowedGrainIDsSet;
72 for(const auto& gID : spec.allowedGrainIDs)
73 {
74 allowedGrainIDsSet.insert(gID);
75 }
76 const double allowAllGrains(allowedGrainIDsSet.size() ? (*allowedGrainIDsSet.begin())<0 : true);
77
78
79 double density=0.0;
80 while(density<spec.targetDensity)
81 {
82 const std::pair<LatticeVector<3>, int> rp(mg.ddBase.poly.randomLatticePointInMesh());
83 const LatticeVector<3> L0=rp.first;
84 const size_t grainID=rp.second;
85 if(allowAllGrains || allowedGrainIDsSet.find(grainID)!=allowedGrainIDsSet.end())
86 {
87 std::uniform_int_distribution<> ssDist(0,mg.ddBase.poly.grain(grainID)->planeNormals().size()-1);
88 const int allowedIndex(allowedPlaneDist(generator));
89 const int allowedPlaneID(spec.allowedPlaneIDs[allowedIndex]);
90
91 const int pID(allowedPlaneID<0? ssDist(generator) : allowedPlaneID); // a random SlipSystem
92 const double radius(radiusDistribution(generator));
93 try
94 {
95 const bool isVL(spec.areVacancyLoops>0);
96 generateSingle(mg,pID,L0.cartesian(),radius,spec.numberOfSides,isVL);
97 density+=2.0*std::numbers::pi*radius/mg.ddBase.mesh.volume()/std::pow(mg.ddBase.poly.b_SI,2);
98 std::cout<<"Frank loop density="<<density<<std::endl;
99 }
100 catch(const std::exception& e)
101 {
102
103 }
104 }
105 }
106 }
107 }
108
110 {
111// const std::vector<int> planeIDs(this->parser.readArray<int>("planeIDs",true));
112 std::cout<<magentaBoldColor<<"Generating individual Frank loops"<<defaultColor<<std::endl;
113 if(spec.planeIDs.size())
114 {
115// const std::vector<double> loopRadii(this->parser.readArray<double>("loopRadii_SI",true));
116// const Eigen::Matrix<double,Eigen::Dynamic,3> loopCenters(this->parser.readMatrix<double>("loopCenters",spec.planeIDs.size(),dim,true));
117// const std::vector<int> numberOfSides(this->parser.readArray<int>("numberOfSides",true));
118// const std::vector<int> isVacancyLoop(this->parser.readArray<int>("isVacancyLoop",true));
119
120 if(spec.planeIDs.size()!=spec.loopRadii.size())
121 {
122 throw std::runtime_error("spec.planeIDs.size()="+std::to_string(spec.planeIDs.size())+" NOT EQUAL TO spec.spec.spec.loopRadii.size()="+std::to_string(spec.loopRadii.size()));
123 }
124 if(int(spec.planeIDs.size())!=spec.loopCenters.rows())
125 {
126 throw std::runtime_error("spec.planeIDs.size()="+std::to_string(spec.planeIDs.size())+" NOT EQUAL TO spec.loopCenters.rows()="+std::to_string(spec.loopCenters.rows()));
127 }
128 if(spec.planeIDs.size()!=spec.loopSides.size())
129 {
130 throw std::runtime_error("spec.planeIDs.size()="+std::to_string(spec.planeIDs.size())+" NOT EQUAL TO spec.loopSides.size()="+std::to_string(spec.loopSides.size()));
131 }
132 if(spec.planeIDs.size()!=spec.isVacancyLoop.size())
133 {
134 throw std::runtime_error("spec.planeIDs.size()="+std::to_string(spec.planeIDs.size())+" NOT EQUAL TO spec.isVacancyLoop.size()="+std::to_string(spec.isVacancyLoop.size()));
135 }
136 for(size_t k=0;k<spec.planeIDs.size();++k)
137 {
138
139 const bool isVL(spec.isVacancyLoop[k]>0);
140 generateSingle(mg,spec.planeIDs[k],spec.loopCenters.row(k),spec.loopRadii[k]/mg.ddBase.poly.b_SI,spec.loopSides[k],isVL);
141 }
142 }
143
144 }
145
146 void FrankLoopsGenerator::generateSingle(MicrostructureGenerator& mg,const int& pID,const VectorDimD& center,const double& radius,const size_t& sides,const bool& isVacancyLoop)
147 {
148 std::pair<bool,const Simplex<3,3>*> found(mg.ddBase.mesh.search(center));
149 if(!found.first)
150 {
151 std::cout<<"Point "<<center.transpose()<<" is outside mesh. EXITING."<<std::endl;
152 exit(EXIT_FAILURE);
153 }
154
155 const int grainID(found.second->region->regionID);
156 assert(mg.ddBase.poly.grains.size()==1 && "Periodic dislocations only supported for single crystals");
157 const auto& grain(mg.ddBase.poly.grain(grainID));
158
159 if(pID>=0 && pID<int(grain->planeNormals().size()))
160 {
161 const auto& planeBase(*grain->planeNormals().at(pID));
162
163
164 const long int planeIndex(planeBase.closestPlaneIndexOfPoint(center));
165 GlidePlaneKey<3> glidePlaneKey(planeIndex, planeBase);
166 std::shared_ptr<PeriodicGlidePlane<3>> glidePlane(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(glidePlaneKey));
167 const VectorDimD P0(glidePlane->referencePlane->snapToPlane(center));
168
169 std::vector<VectorDimD> loopNodePos;
170 for(size_t k=0;k< sides;++k)
171 {
172 loopNodePos.push_back(P0+Eigen::AngleAxisd(k*2.0*std::numbers::pi/sides,planeBase.G2L.row(2).transpose())*planeBase.G2L.row(0).transpose()*radius);
173 }
174
175
176// std::map<VectorDimD,size_t,CompareVectorsByComponent<double,dim,float>> uniqueNetworkNodeMap; // networkNodePosition->networkNodeID
177 ReciprocalLatticeDirection<3> rp(planeBase);
178 const VectorDimD b(isVacancyLoop? (rp.cartesian().normalized()*rp.planeSpacing()).eval() : (-1.0*rp.cartesian().normalized()*rp.planeSpacing()).eval());
179 mg.insertJunctionLoop(loopNodePos,glidePlane,
180 b,glidePlane->referencePlane->unitNormal,
182 }
183 else
184 {
185 if(pID<0)
186 {
187 std::cout<<"Skipping planeID "<<pID<<std::endl;
188 }
189 else
190 {
191 throw std::runtime_error("planeID "+std::to_string(pID)+" not found, skipping.");
192 }
193 }
194 }
195}
196#endif
FrankLoopsGenerator(const FrankLoopsDensitySpecification &, MicrostructureGenerator &)
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
std::pair< bool, const Simplex< _dim, _dim > * > search(const Eigen::Matrix< double, dim, 1 > &P) const
const double & volume() const
b
Definition int_R.m:16
static std::string defaultColor
static std::string magentaBoldColor
LatticePlaneKey< dim > GlidePlaneKey
const Polycrystal< dim > & poly
const SimplicialMesh< dim > & mesh
DislocationDynamicsBase< dim > & dislocationDynamics() const
int sides
int k
int e