Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
DislocationNode.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_DislocationNode_cpp_
9#define model_DislocationNode_cpp_
10
11#include <DislocationNode.h>
12#include <PlanesIntersection.h>
13#include <OneSidedMotion.h>
14
15namespace model
16{
17
18 template <int dim>
20 const VectorDim& P,
21 const VectorDim& V,
22 const ClimbVelocityScalarType& cvs,
23 const double& vrc) :
24 /* init */ NetworkNode<DislocationNode>(net)
25 /* init */,SplineNodeType(P)
26 /* init */,p_Simplex(get_includingSimplex(this->get_P(),(const Simplex<dim,dim>*) NULL))
27 /* init */,climbVelocityScalar(cvs)
28 /* init */,velocity(V)
29 /* init */,vOld(velocity)
30 /* init */,velocityReductionCoeff(vrc)
31 {
32 VerboseDislocationNode(1, " Creating Network Node " << this->tag() <<" @ "<<this->get_P().transpose() << std::endl;);
33 }
34
35template <int dim>
37 const VectorDim& P) :
38/* init */ NetworkNode<DislocationNode>(net)
39/* init */,SplineNodeType(P)
40/* init */,p_Simplex(get_includingSimplex(this->get_P(),(const Simplex<dim,dim>*) NULL))
42/* init */,velocity(VectorDim::Zero())
43/* init */,vOld(velocity)
44/* init */,velocityReductionCoeff(1.0)
45{
46 VerboseDislocationNode(1, " Creating Network Node " << this->tag() <<" @ "<<this->get_P().transpose() << std::endl;);
47}
48
49template <int dim>
51{
52 VectorDim temp(VectorDim::Zero());
53 for(const auto& link : this->neighbors())
54 {// weighted average of segments climb directions
55 if(std::get<1>(link.second)->isSessile())
56 {
57 temp+=std::get<1>(link.second)->climbDirection()*std::get<1>(link.second)->chordLength();
58 }
59 }
60 const double tempNorm(temp.norm());
61 return tempNorm>FLT_EPSILON? (temp/tempNorm).eval() : VectorDim::Zero();
62}
63
64 template <int dim>
66 {
67 VerboseDislocationNode(1, " Destroying Network Node " << this->tag() << std::endl;);
68
69 }
70
71 template <int dim>
72 std::shared_ptr<DislocationNode<dim>> DislocationNode<dim>::clone() const
73 {
74 return std::shared_ptr<DislocationNode<dim>>(new DislocationNode(this->p_network(),this->get_P(),get_V(),climbVelocityScalar,velocityReduction()));
75 }
76
77 template <int dim>
79 {
80 std::pair<bool,const Simplex<dim,dim>*> temp(false,NULL);
81 if (guess==NULL)
82 {
83 temp=this->network().ddBase.mesh.search(X);
84 }
85 else
86 {
87 const auto grains(this->grains());
88 if(grains.size()==1)
89 {// node only in one region
90 if((*grains.begin())->grainID!=guess->region->regionID)
91 {
92 temp=this->network().ddBase.mesh.searchRegion((*grains.begin())->grainID,X);
93 }
94 else
95 {
96 temp=this->network().ddBase.mesh.searchRegionWithGuess(X,guess);
97 }
98 }
99 else
100 {
101 temp=this->network().ddBase.mesh.searchWithGuess(X,guess);
102 }
103 }
104 if(!temp.first) // PlanarDislocationNode not found inside mesh
105 {// Detect if the PlanarDislocationNode is sligtly outside the boundary
106 int faceID;
107 const double baryMin(temp.second->pos2bary(X).minCoeff(&faceID));
108 const bool isApproxOnBoundary(std::fabs(baryMin)<1.0e3*FLT_EPSILON && temp.second->child(faceID).isBoundarySimplex());
109 if(!isApproxOnBoundary)
110 {
111 std::cout<<"PlanarDislocationNode "<<this->sID<<" @ "<<X.transpose()<<std::endl;
112 std::cout<<"Simplex "<<temp.second->xID<<std::endl;
113 std::cout<<"bary "<<temp.second->pos2bary(X)<<std::endl;
114 std::cout<<"face of barymin is "<<temp.second->child(faceID).xID<<std::endl;
115 std::cout<<"face of barymin is boundary Simplex? "<<temp.second->child(faceID).isBoundarySimplex()<<std::endl;
116 std::cout<<"face of barymin is region-boundary Simplex? "<<temp.second->child(faceID).isRegionBoundarySimplex()<<std::endl;
117 throw std::runtime_error("DISLOCATION NODE OUTSIDE MESH.");
118// assert(0 && "DISLOCATION NODE OUTSIDE MESH.");
119 }
120 }
121 return temp.second;
122 }
123
124
125 template <int dim>
127 {
128 VectorOfNormalsType normals;
129 for(const auto* ln : this->loopNodes())
130 {
131 if(!ln->periodicPlanePatch())
132 {
133 continue;
134 }
135 const int grain=ln->periodicPlanePatch()->glidePlane->grain.grainID;
136 for(const auto& edge : {ln->periodicPlaneEdge.first,ln->periodicPlaneEdge.second})
137 {
138 if(!edge)
139 {
140 continue;
141 }
142 for(const auto* face : edge->meshIntersection->faces)
143 {
144 if(!face->periodicFacePair.second || face->regionIDs!=face->periodicFacePair.second->regionIDs)
145 {
146 const VectorDim normal=face->outNormal(grain);
147 bool duplicate=false;
148 for(const auto& existing : normals)
149 {
150 duplicate|=(normal-existing).norm()<1.e-12;
151 }
152 if(!duplicate && normal.squaredNorm()>0.0)
153 {
154 normals.push_back(normal);
155 }
156 }
157 }
158 }
159 }
160 return normals;
161 }
162
163 template <int dim>
164 void DislocationNode<dim>::projectVelocity(const bool& isClimbingStep)
165 {
166 VectorOfNormalsType equalities;
167 for(const auto* ln : this->loopNodes())
168 {
169 if(ln->loop()->glidePlane)
170 {
171 equalities.push_back(ln->loop()->glidePlane->unitNormal);
172 }
173 if(!isClimbingStep && ln->loop()->loopType==DislocationLoopIO<dim>::SESSILELOOP)
174 {
175 velocity.setZero();
176 return;
177 }
178 }
179 for(int r=0;r<this->network().nodalVelocityConstraints.rows();++r)
180 {
181 equalities.push_back(this->network().nodalVelocityConstraints.row(r));
182 }
184 }
185
186 template <int dim>
187 void DislocationNode<dim>::set_V(const VectorDim& vNew,const bool& isClimbingStep)
188 {
189
190 double emaStrength=0.0;
191
192 vOld=velocity; // store current value of velocity before updating
193
194 //velocity=vNew;
195 velocity=(1.0-emaStrength)*vNew+emaStrength*velocity;
196 projectVelocity(isClimbingStep);
197
198// if (this->network().capMaxVelocity && !this->network().timeIntegrator.isTimeStepControlling(*this))
199// {
200// //Need to cap the max velocity based on the time step
201// const double vmax=this->network().timeIntegrator.dxMax/this->network().timeIntegrator.dtMax;
202// assert(fabs(vmax)>FLT_EPSILON && "Max velocity should be greater than 0");
203// if (velocity.norm()>=FLT_EPSILON && velocity.norm()>fabs(vmax))
204// {
205// const double velredFac(velocity.norm()/fabs(vmax));
206// assert(velredFac>=1.0 && "Velocity reduction factor must be greater than 1");
207// velocity/=velredFac;
208// totalCappedNodes+=1;
209// }
210// }
211
212// if(this->network().use_velocityFilter)
213// {
214// if(!isBoundaryNode())
215// {
216// const double filterThreshold=0.05*velocity.norm()*vOld.norm()+FLT_EPSILON;
217//
218// if(velocity.dot(vOld)<-filterThreshold)
219// {
220// velocityReductionCoeff*=this->network().velocityReductionFactor;
221// }
222// else if(velocity.dot(vOld)>filterThreshold)
223// {
224// velocityReductionCoeff/=this->network().velocityReductionFactor;
225// }
226// else
227// {
228// // don't change velocityReductionCoeff
229// }
230// if(velocityReductionCoeff>1.0)
231// {
232// velocityReductionCoeff=1.0;
233// }
234// if(velocityReductionCoeff<0.005)
235// {
236// velocityReductionCoeff=0.005;
237// }
238// velocity*=velocityReductionCoeff;
239// }
240// else
241// {
242// // TO DO BOUNDARY NODES NEED TO INTERPOLATE ALSO THE VELOCTY FILTER
243// }
244//
245// }
246 }
247
248 template <int dim>
250 {
251 for(const auto& neighboor : this->neighbors())
252 {
253 std::get<1>(neighboor.second)->updateGeometry();
254 }
255 }
256
257 template <int dim>
259 {
260 auto& network=this->network();
261 VectorDim displacement=snapToGlidePlanesinPeriodic(newP)-this->get_P();
262 VectorOfNormalsType normals;
263 for(const auto* plane : glidePlanes())
264 {
265 normals.push_back(plane->unitNormal);
266 }
267 for(int r=0;r<network.nodalVelocityConstraints.rows();++r)
268 {
269 normals.push_back(network.nodalVelocityConstraints.row(r));
270 }
271 displacement=oneSidedMotion<dim>(displacement,normals,physicalBoundaryNormals());
272 const bool immediate=!network.trialNodeMotion;
273 std::vector<std::pair<std::shared_ptr<LoopNodeType>,typename LoopNodeType::SplineNodeType>> saved;
274 for(const auto* node : this->loopNodes())
275 {
276 saved.emplace_back(network.loopNodes().get(node->sID),static_cast<const typename LoopNodeType::SplineNodeType&>(*node));
277 }
278 network.trialNodeMotion=true;
279 try
280 {
281 for(const auto& entry : saved)
282 {
283 entry.first->set_P(VectorDim(entry.second.get_P()+displacement));
284 }
285 if(immediate)
286 {
287 network.updateBoundaryNodes();
288 network.trialNodeMotion=false;
289 }
290 }
291 catch(...)
292 {
293 for(const auto& entry : saved)
294 {
295 static_cast<typename LoopNodeType::SplineNodeType&>(*entry.first)=entry.second;
296 }
297 network.trialNodeMotion=!immediate;
298 throw;
299 }
300 return true;
301 }
302
303 template <int dim>
305 {
306 VerboseDislocationNode(1, " Setting P for Network Node " << this->tag() << std::endl;);
307
308 if((SplineNodeType::get_P()-newP).norm()>FLT_EPSILON) //Check with the base classs
309 {
310 const auto simplex=get_includingSimplex(newP,p_Simplex);
311 SplineNodeType::set_P(newP);
312 p_Simplex=simplex;
313
314 }
315
316 return (this->get_P()-newP).norm()<FLT_EPSILON;
317 }
318
319
320
321 template <int dim>
323 {
325 return velocity;
326 }
327
328 template <int dim>
329 std::set<typename DislocationNode<dim>::LoopType*> DislocationNode<dim>::sessileLoops() const
330 {
331 std::set<LoopType*> temp;
332 for (const auto& loop : this->loops())
333 {
334 if (loop->loopType == DislocationLoopIO<dim>::SESSILELOOP)
335 {
336 temp.insert(loop);
337 }
338 }
339 return temp;
340 }
341
342
343 template <int dim>
345 {
347 }
348
349 template <int dim>
351 {
352 // A periodic grain interface is both an outer mesh boundary and a GB.
353 // Give its physical GB classification priority in serialized/display data.
355 {
356 return MeshLocation::onRegionBoundary;
357 }
358 if(isBoundaryNode())
359 {
360 return MeshLocation::onMeshBoundary;
361 }
362 return MeshLocation::insideMesh;
363 }
364
365// template <int dim>
366// const std::shared_ptr<typename DislocationNode<dim>::NetworkNodeType>& DislocationNode<dim>::virtualBoundaryNode() const
367// {
368// return virtualNode;
369// }
370
371 template <int dim>
373 {
376 VectorDim temp(this->neighbors().size()? std::get<1>(this->neighbors().begin()->second)->chord().normalized() : VectorDim::Zero());
377 for (const auto& neighborIter : this->neighbors())
378 {
379 if(std::get<1>(neighborIter.second)->chord().normalized().cross(temp).norm()>FLT_EPSILON)
380 {
381 temp.setZero();
382 }
383 }
384 return temp;
385 }
386
387 template <int dim>
389 {
390 for(const auto& loopNode : this->loopNodes())
391 {
392 const VectorDim shift(loopNode->periodicPlanePatch()? loopNode->periodicPlanePatch()->shift : VectorDim::Zero());
393
394 if(!loopNode->isMovableTo(X-shift))
395 {
396 VerboseDislocationNode(2," DislocationNode "<<this->tag()<< " NOT movable "<<std::endl;);
397 return false;
398 }
399 }
400 return true;
401
402 }
403
404 template <int dim>
410
411// template <int dim>
412// bool DislocationNode<dim>::isVirtualBoundaryNode() const
413// {
414// return masterNode && this->meshFaces().size()==0;
416// }
417
418
419
420 template <int dim>
422 {
423 return isOnExternalBoundary();
424 }
425
426 template <int dim>
428 {
429 for(const auto* face : meshFaces())
430 {
431 if(face->regionIDs.first!=face->regionIDs.second)
432 {
433 return true;
434 }
435 const auto* partner=face->periodicFacePair.second;
436 if(partner && face->regionIDs!=partner->regionIDs)
437 {
438 return true;
439 }
440 }
441 return false;
442 }
443
444 template <int dim>
446 {
448 for (const auto &ln : this->loopNodes())
449 {
450 if (ln->periodicPlanePatch())
451 {
452 temp.emplace(ln->periodicPlanePatch()->glidePlane.get());
453 }
454 }
455 return temp;
456 }
457
458 template <int dim>
460 {
462 for (const auto &ln : this->loopNodes())
463 {
464 if (ln->periodicPlaneEdge.first)
465 {
466 const auto& faces=ln->periodicPlaneEdge.first->meshIntersection->faces;
467 temp.insert(faces.begin(),faces.end());
468 }
469 if (ln->periodicPlaneEdge.second)
470 {
471 for (const auto &face : ln->periodicPlaneEdge.second->meshIntersection->faces)
472 {
473 temp.emplace(face);
474 }
475 }
476 }
477 return temp;
478 }
479
480 template <int dim>
482 {
484 bool _isOnExternalBoundary(false);
485 for (const auto &face : meshFaces())
486 {
487 if (face->regionIDs.first == face->regionIDs.second)
488 {
489 _isOnExternalBoundary = true;
490 break;
491 }
492 }
493
494 return _isOnExternalBoundary;
495 }
496
497 template <int dim>
499 {
500 bool _isOnInternalBoundary(false);
501 for (const auto &face : meshFaces())
502 {
503 if (face->regionIDs.first != face->regionIDs.second)
504 {
505 _isOnInternalBoundary = true;
506 break;
507 }
508 }
509 return _isOnInternalBoundary;
510 }
511
512 template <int dim>
517
518 template <int dim>
520 {
521 VectorDim _outNormal(VectorDim::Zero());
522 for (const auto &face : meshFaces())
523 {
524 _outNormal += face->outNormal();
525 }
526 const double _outNormalNorm(_outNormal.norm());
527 if (_outNormalNorm > FLT_EPSILON)
528 {
529 _outNormal /= _outNormalNorm;
530 }
531 else
532 {
533 _outNormal.setZero();
534 }
535 return _outNormal;
536 }
537
538 template <int dim>
540 {
542 if(gps.size())
543 {
544 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> N(Eigen::Matrix<double,dim,Eigen::Dynamic>::Zero(dim,gps.size()));
545 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> P(Eigen::Matrix<double,dim,Eigen::Dynamic>::Zero(dim,gps.size()));
546
547 int k=0;
548 for(const auto& plane : gps)
549 {
550 N.col(k)=plane->unitNormal;
551 P.col(k)=plane->P;
552 ++k;
553 }
554 PlanesIntersection<dim> pInt(N,P,FLT_EPSILON);
555
556 const std::pair<bool,VectorDim> snapped(pInt.snap(x));
557 if(snapped.first)
558 {
559 return snapped.second;
560 }
561 else
562 {
563 std::cout<<"glidePlanes.size()="<<gps.size()<<std::endl;
564 std::cout<<"N="<<N<<std::endl;
565 std::cout<<"P="<<P<<std::endl;
566 throw std::runtime_error("DislocationNode, cannot snap, glidePlanes dont intersect.");
567 return snapped.second;
568 }
569 }
570 else
571 {
572 if(sessileLoops().size()==this->loops().size())
573 {
574 return x;
575 }
576 else
577 {
578 throw std::runtime_error("All loops must be sessile if there are no glide planes.");
579 return x;
580 }
581 }
582 }
583
584 template <int dim>
586 {
588 for (const auto &glidePlane : glidePlanes())
589 {
590 temp.insert(&glidePlane->grain);
591 }
592 return temp;
593 }
594
595 template <int dim>
597
598 template class DislocationNode<3>;
599
600}
601#endif
Eigen::Vector3d V
SplineNode< DislocationLoopNode< dim >, dim, 0, Hermite > SplineNodeType
std::shared_ptr< DislocationNode > clone() const
const Simplex< dim, dim > * get_includingSimplex(const VectorDim &, const Simplex< dim, dim > *const) const
void projectVelocity(const bool &isClimbingStep)
double velocityReductionCoeff
The previous velocity vector of *this PlanarDislocationNode.
GrainContainerType grains() const
std::vector< VectorDim > VectorOfNormalsType
bool trySet_P(const VectorDim &)
std::set< const GlidePlaneType * > GlidePlaneContainerType
bool isMovableTo(const VectorDim &) const
ClimbVelocityScalarType climbVelocityScalar
VectorOfNormalsType physicalBoundaryNormals() const
const Simplex< dim, dim > * includingSimplex() const
VectorDim climbDirection() const
TypeTraits< NetworkNodeType >::MeshLocation MeshLocation
std::set< LoopType * > sessileLoops() const
DislocationNode(LoopNetworkType *const, const VectorDim &, const VectorDim &, const ClimbVelocityScalarType &, const double &)
TraitsType::VectorDim VectorDim
Eigen::Array< double, 1, ClusterDynamicsParameters< dim >::mSize > ClimbVelocityScalarType
std::set< const PlanarMeshFaceType * > PlanarMeshFaceContainerType
SplineNode< DislocationNode< dim >, dim, 0, Hermite > SplineNodeType
std::set< const GrainType * > GrainContainerType
const VectorDim & get_V() const
TraitsType::LoopNetworkType LoopNetworkType
VectorDim invariantDirectionOfMotion() const
void set_V(const VectorDim &vNew, const bool &isClimbingStep)
VectorDim bndNormal() const
MeshLocation meshLocation() const
VectorDim snapToGlidePlanesinPeriodic(const VectorDim &P) const
const double & velocityReduction() const
bool set_P(const VectorDim &)
GlidePlaneContainerType glidePlanes() const
const Simplex< dim, dim > * p_Simplex
PlanarMeshFaceContainerType meshFaces() const
NetworkNode(LoopNetworkType *const loopNetwork_in)
Definition NetworkNode.h:59
const NeighborContainerType & neighbors() const
const LoopNodeContainerType & loopNodes() const
std::set< LoopType * > loops() const
x
Definition int_R.m:12
Eigen::Matrix< double, dim, 1 > oneSidedMotion(const Eigen::Matrix< double, dim, 1 > &requested, const std::vector< Eigen::Matrix< double, dim, 1 > > &equalities, const std::vector< Eigen::Matrix< double, dim, 1 > > &outward)
auto eval(const std::shared_ptr< T > &t)
Eigen::Matrix< double, 3, 1 > VectorDim
Definition pyMoDELib.cxx:66
std::pair< bool, VectorDim > snap(const VectorDim &x) const
int k
vertex temp