Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
PeriodicDipoleGenerator.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_PeriodicDipoleGenerator_cpp_
9#define model_PeriodicDipoleGenerator_cpp_
10
11
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#include <random>
22#include <iomanip>
23
24//#include <Simplex.h>
25#include <SimplicialMesh.h>
26#include <Polycrystal.h>
28#include <LatticeModule.h>
29//#include <PlaneMeshIntersection.h>
36
38#include <TextFileParser.h>
40#include <MeshBoundarySegment.h>
41//#include <ConfinedDislocationObject.h>
42#include <GlidePlaneModule.h>
43#include <MeshModule.h>
44#include <Plane.h>
45#include <Line.h>
49
50namespace model
51{
52
54 {
55 std::cout<<magentaBoldColor<<"Generating individual periodic dipoles"<<defaultColor<<std::endl;
56 if(spec.slipSystemIDs.size())
57 {
58 if(spec.slipSystemIDs.size()!=spec.exitFaceIDs.size())
59 {
60 throw std::runtime_error("slipSystemIDs.size()="+std::to_string(spec.slipSystemIDs.size())+" NOT EQUAL TO exitFaceIDs.size()="+std::to_string(spec.exitFaceIDs.size()));
61 }
62 if(int(spec.slipSystemIDs.size())!=spec.dipoleCenters.rows())
63 {
64 throw std::runtime_error("slipSystemIDs.size()="+std::to_string(spec.slipSystemIDs.size())+" NOT EQUAL TO dipoleCenters.rows()="+std::to_string(spec.dipoleCenters.rows()));
65 }
66 if(spec.slipSystemIDs.size()!=spec.dipoleHeights.size())
67 {
68 throw std::runtime_error("slipSystemIDs.size()="+std::to_string(spec.slipSystemIDs.size())+" NOT EQUAL TO dipoleHeights.size()="+std::to_string(spec.dipoleHeights.size()));
69 }
70 if(spec.slipSystemIDs.size()!=spec.nodesPerLine.size())
71 {
72 throw std::runtime_error("slipSystemIDs.size()="+std::to_string(spec.slipSystemIDs.size())+" NOT EQUAL TO nodesPerLine.size()="+std::to_string(spec.nodesPerLine.size()));
73 }
74 if(spec.slipSystemIDs.size()!=spec.glideSteps.size())
75 {
76 throw std::runtime_error("slipSystemIDs.size()="+std::to_string(spec.slipSystemIDs.size())+" NOT EQUAL TO periodicDipoleGlideSteps.size()="+std::to_string(spec.glideSteps.size()));
77 }
78
79 for(size_t k=0;k<spec.slipSystemIDs.size();++k)
80 {
81 generateSingle(mg,spec.slipSystemIDs[k],spec.dipoleCenters.row(k),spec.exitFaceIDs[k],spec.dipoleHeights[k],spec.nodesPerLine[k],spec.glideSteps[k]);
82 }
83 }
84
85 }
86
88 {
89 std::cout<<magentaBoldColor<<"Generating periodic dipole density"<<defaultColor<<std::endl;
90 // const double targetDensity(this->parser.readScalar<double>("targetDensity",true));
91 if(spec.targetDensity>0.0)
92 {
93 std::mt19937 generator;
94 double density=0.0;
95 while(density<spec.targetDensity)
96 {
97 const std::pair<LatticeVector<3>, int> rp(mg.ddBase.poly.randomLatticePointInMesh());
98 const LatticeVector<3> L0=rp.first;
99 const size_t grainID=rp.second;
100 std::uniform_int_distribution<> ssDist(0,mg.ddBase.poly.grain(grainID)->slipSystems().size()-1);
101 const int rSS(ssDist(generator)); // a random SlipSystem
102 std::uniform_int_distribution<> fDist(0,mg.ddBase.poly.grain(grainID)->region.faces().size()-1);
103 const int rF(fDist(generator)); // a random face
104 auto faceIter(mg.ddBase.poly.grain(grainID)->region.faces().begin());
105 std::advance(faceIter,rF);
106
107 try
108 {
109 generateSingle(mg,rSS,L0.cartesian(),faceIter->first,100,0,20.0);
110 density+=2.0*faceIter->second->periodicFacePair.first.norm()/mg.ddBase.mesh.volume()/std::pow(mg.ddBase.poly.b_SI,2);
111 std::cout<<"periodic dipole density="<<density<<std::endl;
112 }
113 catch(const std::exception& e)
114 {
115
116 }
117 }
118 }
119 }
120
121 bool PeriodicDipoleGenerator::generateSingle(MicrostructureGenerator& mg,const int& rSS,const VectorDimD& dipolePoint,const int& exitFaceID,const int& dipoleHeight,const int& dipoleNodes, double glideStep)
122 {
123
124
125 if(rSS>=0)
126 {
127 std::pair<bool,const Simplex<3,3>*> found(mg.ddBase.mesh.search(dipolePoint));
128 if(!found.first)
129 {
130 std::cout<<"Point "<<dipolePoint.transpose()<<" is outside mesh. EXITING."<<std::endl;
131 exit(EXIT_FAILURE);
132 }
133
134 const int grainID(found.second->region->regionID);
135 assert(mg.ddBase.poly.grains.size()==1 && "Periodic dislocations only supported for single crystals");
136 const auto& grain(mg.ddBase.poly.grain(grainID));
137
138 if(rSS<int(grain->slipSystems().size()))
139 {
140 const auto periodicFaceIter(grain->region.faces().find(exitFaceID));
141 if(periodicFaceIter!=grain->region.faces().end())
142 {
143 const auto periodicFaceA(periodicFaceIter->second);
144 const auto periodicFaceB(periodicFaceA->periodicFacePair.second);
145
146 if(periodicFaceB!=nullptr)
147 {
148
149 const auto& faceAshift(periodicFaceA->periodicFacePair.first);
150 const auto faceAlatticeShift(grain->latticeVector(faceAshift));
151
152 const auto& slipSystem(*grain->slipSystems().at(rSS));
153
154 if(slipSystem.n.dot(faceAlatticeShift)==0)
155 {
156
157 // const std::pair<bool,long int> heightPair=LatticePlane::computeHeight(slipSystem.n,dipolePoint);
158
159 const VectorDimD planePoint(dipolePoint-0.5*dipoleHeight*slipSystem.n.interplaneVector());
160
161 // Construct lower glide plane
162 const long int planeIndex(slipSystem.n.closestPlaneIndexOfPoint(planePoint));
163 GlidePlaneKey<3> glidePlaneKey(planeIndex, slipSystem.n);
164 std::shared_ptr<PeriodicGlidePlane<3>> glidePlane(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(glidePlaneKey));
165
166 // Construct Prismatic Plane
167 const auto prismaticPlaneNormal(grain->reciprocalLatticeDirection(glidePlane->referencePlane->unitNormal.cross(faceAshift)));
168 const long int prismaticPlaneIndex(prismaticPlaneNormal.closestPlaneIndexOfPoint(dipolePoint));
169 GlidePlaneKey<3> prismaticPlaneKey(prismaticPlaneIndex, prismaticPlaneNormal);
170 std::shared_ptr<PeriodicGlidePlane<3>> prismaticGlidePlane(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(prismaticPlaneKey));
171
172 PlanePlaneIntersection<3> ppi(*glidePlane->referencePlane,*prismaticGlidePlane->referencePlane);
173 Line<3> ppLine(ppi.P,ppi.d);
174 //const VectorDimD P0(ppi.P+(planePoint-ppi.P).dot(ppi.d)*ppi.d);
175 const VectorDimD P0(ppLine.snap(planePoint));
176
177
178 PlaneLineIntersection<3> pliA(periodicFaceA->center(),periodicFaceA->outNormal(),P0,faceAshift);
179 PlaneLineIntersection<3> pliB(periodicFaceB->center(),periodicFaceB->outNormal(),P0,faceAshift);
180
182 {
183 const VectorDimD AB(pliB.P-pliA.P);
184 if((AB-faceAshift).norm()<FLT_EPSILON)
185 {
186
187 GlidePlaneKey<3> parallelGlidePlaneKey(planeIndex+dipoleHeight, slipSystem.n);
188 std::shared_ptr<PeriodicGlidePlane<3>> parallelglidePlane(mg.ddBase.dislocationDynamics().periodicGlidePlaneFactory.get(parallelGlidePlaneKey));
189
190
191 if(parallelglidePlane && prismaticGlidePlane)
192 {
193
194
195 std::map<VectorDimD,size_t,CompareVectorsByComponent<double,3,float>> uniqueNetworkNodeMap; // networkNodePosition->networkNodeID
196 // The prismatic loop
197 const int nShift(2);
198 const VectorDimD lShift(nShift*AB);
199 const VectorDimD rShift(lShift+AB);
200 const VectorDimD startPoint(0.5*(pliB.P+pliA.P));
201 std::vector<VectorDimD> prismaticNodePos;
202 prismaticNodePos.push_back(startPoint+lShift); //HERE ADD N*AB
203 prismaticNodePos.push_back(startPoint+rShift);
204 prismaticNodePos.push_back(parallelglidePlane->referencePlane->snapToPlane(startPoint+rShift));
205 prismaticNodePos.push_back(parallelglidePlane->referencePlane->snapToPlane(startPoint+lShift));
206
207 const VectorDimD lineP0 = 0.5*(startPoint+lShift+parallelglidePlane->referencePlane->snapToPlane(startPoint+lShift));
208 const VectorDimD lineP1 = 0.5*(startPoint+rShift+parallelglidePlane->referencePlane->snapToPlane(startPoint+rShift));
209
210 mg.insertJunctionLoop(prismaticNodePos,prismaticGlidePlane,
211 slipSystem.s.cartesian(),prismaticGlidePlane->referencePlane->unitNormal,
213
214 if(std::fabs(glideStep)>FLT_EPSILON)
215 {
216 const int halfNodeNumber(dipoleNodes/2);
217 if(halfNodeNumber < 0)
218 {
219 throw std::runtime_error("dipoleNodes="+std::to_string(halfNodeNumber)+"is smaller than 0");
220 }
221 const double halfDipoleLength(AB.norm()*0.5);
222 const VectorDimD dipoleDir(AB/AB.norm());
223 const VectorDimD shiftNodeLength(halfDipoleLength/(1.0*(halfNodeNumber+1))*dipoleDir);
224
225 // First glide loop
226 // const double glideStep=50.0;
227 std::vector<VectorDimD> firstNodePos;
228 firstNodePos.push_back(startPoint+lShift);
229 firstNodePos.push_back(startPoint+rShift);
230 if((rShift-lShift).cross(glideStep*prismaticGlidePlane->referencePlane->unitNormal).dot(glidePlane->referencePlane->unitNormal)>0.0)
231 {// loop is right-handed to glidePlane->referencePlane->unitNormal
232 glideStep*=-1;
233 }
234 firstNodePos.push_back(startPoint+rShift+glideStep*prismaticGlidePlane->referencePlane->unitNormal);
235 for(int k=1; k<=halfNodeNumber; k++)
236 { // Add nodes on rigth arm
237 firstNodePos.push_back(startPoint+rShift-k*shiftNodeLength+glideStep*prismaticGlidePlane->referencePlane->unitNormal);
238 }
239 for(int k=halfNodeNumber; k>0; k--)
240 { // Add nodes on left arm
241 firstNodePos.push_back(startPoint+lShift+k*shiftNodeLength+glideStep*prismaticGlidePlane->referencePlane->unitNormal);
242 }
243 firstNodePos.push_back(startPoint+lShift+glideStep*prismaticGlidePlane->referencePlane->unitNormal);
244
245 mg.insertJunctionLoop(firstNodePos,glidePlane,
246 -slipSystem.s.cartesian(),glidePlane->referencePlane->unitNormal,
248
249
250 FiniteLineSegment<3> mirrowLine(lineP0,lineP1);
251
252 // Second glide loop
253 std::vector<VectorDimD> secondNodePos;
254 for(const auto& pos : firstNodePos)
255 {
256 VectorDimD c=mirrowLine.snapToInfiniteLine(pos);
257 secondNodePos.push_back(2.0*c-pos);
258 // secondNodePos.push_back(parallelglidePlane->referencePlane->snapToPlane(pos));
259 }
260
261
262 mg.insertJunctionLoop(secondNodePos,parallelglidePlane,
263 slipSystem.s.cartesian(),parallelglidePlane->referencePlane->unitNormal,
264 parallelglidePlane->referencePlane->snapToPlane(P0),grainID,DislocationLoopIO<3>::GLISSILELOOP);
265 return true;
266 }
267
268 }
269 else
270 {
271 std::cout<<"Cannot create glide planes"<<std::endl;
272 }
273 }
274 else
275 {
276 throw std::runtime_error("periodic line intersection with faces is not the face shift vector");
277 }
278 }
279 else
280 {
281 throw std::runtime_error("periodic line direction does not form an incident intersecitn with periodic faces");
282 }
283 }
284 else
285 {
286 throw std::runtime_error("planeNormal of slipSystem "+std::to_string(rSS)+" is not othogonal to facelatticeShift "+std::to_string(exitFaceID));
287 }
288 }
289 else
290 {
291 throw std::runtime_error("Mesh face "+std::to_string(exitFaceID)+" is not a periodic face.");
292 }
293 }
294 else
295 {
296 throw std::runtime_error("Mesh face "+std::to_string(exitFaceID)+" not found.");
297 }
298 }
299 else
300 {
301 throw std::runtime_error("slipSystem "+std::to_string(rSS)+" not found, skipping.");
302 }
303 }
304 else
305 {
306 std::cout<<"Skipping slip system "<<rSS<<std::endl;
307 }
308 return false;
309 }
310
311}
312#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
PeriodicDipoleGenerator(const PeriodicDipoleDensitySpecification &spec, MicrostructureGenerator &mg)
std::pair< bool, const Simplex< _dim, _dim > * > search(const Eigen::Matrix< double, dim, 1 > &P) const
const double & volume() const
c
Definition int_R.m:15
static std::string defaultColor
static std::string magentaBoldColor
LatticePlaneKey< dim > GlidePlaneKey
const Polycrystal< dim > & poly
const SimplicialMesh< dim > & mesh
DislocationDynamicsBase< dim > & dislocationDynamics() const
int k
int e