Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
DislocationLoopNode.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_DislocationLoopNode_cpp_
9#define model_DislocationLoopNode_cpp_
10
11#include <DislocationLoopNode.h>
12
13namespace model
14{
15
16 template <int dim>
18 const std::shared_ptr<typename DislocationLoopNode<dim>::LoopType>& loop,
19 const std::shared_ptr<typename DislocationLoopNode<dim>::NetworkNodeType>& networkNode,
20 const VectorDim& P,
21 const std::shared_ptr<PeriodicPlanePatch<dim>>& patch_in,
22 const std::pair<const std::shared_ptr<PeriodicPlaneEdge<dim>>,const std::shared_ptr<PeriodicPlaneEdge<dim>>>& edge_in
23// const std::set<std::shared_ptr<PeriodicPlanePatch<dim>>>& auxPatch_in
24 ) :
25 /* init */ LoopNode<DislocationLoopNode>(net,loop,networkNode)
26 /* init */,SplineNodeType(P)
27 /* init */,_periodicPlanePatch(patch_in)
28 /* init */,periodicPlaneEdge(edge_in)
29 {
30 VerboseDislocationLoopNode(1,"Creating LoopNode "<<this->tag()<<std::endl;);
31 if (periodicPlaneEdge.second!=nullptr)
32 {
33 if (periodicPlaneEdge.first == nullptr)
34 {
35 assert(false && "Inconsisten definition of periodic plane edges for the dislocation loop node");
36 }
37 }
38
39 }
40
41 template <int dim>
42 DislocationLoopNode<dim>::DislocationLoopNode(typename DislocationLoopNode<dim>::LoopNetworkType* const net,
43 const std::shared_ptr<typename DislocationLoopNode<dim>::LoopType>& loop,
44 const std::shared_ptr<typename DislocationLoopNode<dim>::NetworkNodeType>& networkNode,
45 const LoopLinkType* const loopLink) :
46 /* init */ LoopNode<DislocationLoopNode>(net,loop,networkNode)
47 /* init */,SplineNodeType(loopLink->periodicPlanePatch()? networkNode->get_P()-loopLink->periodicPlanePatch()->shift : networkNode->get_P())
48 /* init */,_periodicPlanePatch(loopLink->periodicPlanePatch())
49 /* init */,periodicPlaneEdge(std::make_pair(nullptr,nullptr))
50 {
51 VerboseDislocationLoopNode(1,"Creating LoopNode without PeriodicPlaneEdge "<<this->tag()<<std::endl;);
52
53 }
54
55 template <int dim>
57 {
58 return LoopNode<LoopNodeType>::isContractableTo(other) && _periodicPlanePatch==other->periodicPlanePatch();
59 }
60
61
62 template <int dim>
63 std::shared_ptr<DislocationLoopNode<dim>> DislocationLoopNode<dim>::clone(const std::shared_ptr<typename DislocationLoopNode<dim>::LoopType>& otherLoop,
64 const std::shared_ptr<typename DislocationLoopNode<dim>::NetworkNodeType>& otherNetworkNode) const
65 {
66 auto result=std::shared_ptr<DislocationLoopNode<dim>>(new DislocationLoopNode(this->p_network(),otherLoop,otherNetworkNode,this->get_P(),_periodicPlanePatch,periodicPlaneEdge));
67 result->periodicContourVertex=periodicContourVertex;
68 return result;
69 }
70
71 template <int dim>
72 void DislocationLoopNode<dim>::initFromFile(const std::string& fileName)
73 {
74 verboseDislocationLoopNode=TextFileParser(fileName).readScalar<int>("verboseDislocationLoopNode",false);
75 }
76
77 template <int dim>
79 {
80 if (this->prev.first)
81 {
82 auto currentPrev(this->prev.first);
83 while (currentPrev->isPeriodicSubdivision()) //First is sufficient
84 {
85 if (currentPrev == this)
86 {
87 return nullptr;
88 }
89 currentPrev = currentPrev->prev.first;
90 }
91 return currentPrev;
92 }
93 return nullptr;
94 }
95
96 template <int dim>
98 {
99 if (this->next.first)
100 {
101 auto currentNext(this->next.first);
102 while (currentNext->isPeriodicSubdivision())
103 {
104 if (currentNext == this)
105 {
106 return nullptr;
107 }
108 currentNext = currentNext->next.first;
109 }
110 return currentNext;
111 }
112 return nullptr;
113 }
114
115 template <int dim>
116 std::vector<DislocationLoopNode<dim>*> DislocationLoopNode<dim>::boundaryPrev() const
117 {
118 assert(!this->periodicPlaneEdge.first);
119 std::vector<DislocationLoopNode<dim>*> temp;
120 if (this->prev.first)
121 {
122 auto currentPrev(this->prev.first);
123 while (currentPrev->isPeriodicSubdivision())
124 {
125 temp.push_back(currentPrev);
126 currentPrev = currentPrev->prev.first;
127 }
128 }
129 return temp;
130 }
131
132 template <int dim>
133 std::vector<DislocationLoopNode<dim>*> DislocationLoopNode<dim>::boundaryNext() const
134 {
135 assert(!this->periodicPlaneEdge.first);
136 std::vector<DislocationLoopNode<dim>*> temp;
137 if (this->next.first)
138 {
139 auto currentNext(this->next.first);
140 while (currentNext->isPeriodicSubdivision())
141 {
142 temp.push_back(currentNext);
143 currentNext = currentNext->next.first;
144 }
145 }
146
147 return temp;
148 }
149
150 template <int dim>
152 {
153 VerboseDislocationLoopNode(2,"DislocationLoopNode "<<this->tag()<<" set_P (lowerDim)"<<std::endl;);
154 assert(periodicPlaneEdge.first);
155
156 VectorDim globalPosition(this->loop()->periodicGlidePlane->referencePlane->globalPosition(newP));
157 VectorDim localPosition(VectorDim::Zero());
158
159 if (periodicPlaneEdge.second==nullptr)
160 {
161 localPosition=periodicPlaneEdge.first->meshIntersection->snap(globalPosition + periodicPlaneEdge.first->patch->shift);
162 // if (this->networkNode->meshFaces().size()==2)
163 // {
164 // //This means that the node was created at a mesh face and not at the edge
165 // //Clear the confinement so that it can move away from the edge
166 // this->networkNode->meshFaces().clear();
167 // }
168 }
169 else
170 {
171 SegmentSegmentDistance<3> ssd(periodicPlaneEdge.first->meshIntersection->P0,periodicPlaneEdge.first->meshIntersection->P1,
172 periodicPlaneEdge.second->meshIntersection->P0,periodicPlaneEdge.second->meshIntersection->P1);
173 assert(ssd.dMin<FLT_EPSILON && "The two periodic plane edges must intersect");
174 assert((periodicPlaneEdge.first->patch->shift-periodicPlaneEdge.second->patch->shift).norm()<FLT_EPSILON && "Two patch shifts must match ");
175 localPosition=0.5 * (ssd.x0 + ssd.x1);
176 }
177 globalPosition = localPosition - periodicPlaneEdge.first->patch->shift;
178
179 // This global local is necessary so as to have the precision for the boundary node and eliminate any floating point error
180
181 SplineNodeType::set_P(globalPosition);
182 this->networkNode->set_P(localPosition);
183 // this->networkNode->updateConfinement();
184 }
185
186//Yash's Version temporary
187
188 // template <int dim>
189 // void DislocationLoopNode<dim>::set_P(const typename DislocationLoopNode<dim>::VectorLowerDim& newP)
190 // {
191 // VerboseDislocationLoopNode(2,"DislocationLoopNode "<<this->tag()<<" set_P (lowerDim)"<<std::endl;);
192 // assert(periodicPlaneEdge);
193
194 // //If we can get rid of the boundary junctions we do not need the snap operation
195 // const VectorDim globalRVEPosition(this->networkNode->snapToGlidePlanes(this->loop()->periodicGlidePlane->referencePlane->globalPosition(newP)+periodicPlaneEdge->patch->shift));
196 // SplineNodeType::set_P(globalRVEPosition-periodicPlaneEdge->patch->shift);
197 // // std::cout<<"this->networkNode "<<this->networkNode->sID<<this->networkNode->glidePlanes().size()<<std::endl;
198 // this->networkNode->set_P(globalRVEPosition);
199 // }
200
201
202 template <int dim>
204 {
205 for(const auto& edge : {periodicPlaneEdge.first,periodicPlaneEdge.second})
206 {
207 if(edge)
208 {
209 for(const auto* face : edge->meshIntersection->faces)
210 {
211 if(!face->periodicFacePair.second || face->regionIDs!=face->periodicFacePair.second->regionIDs)
212 {
213 return true;
214 }
215 }
216 }
217 }
218 return false;
219 }
220
221 template <int dim>
226
227 template <int dim>
229 {
230 if(!this->network().trialNodeMotion)
231 {
232 // Public motion moves every loop representation of the junction.
233 const VectorDim mapped=newP+(_periodicPlanePatch ? _periodicPlanePatch->shift : VectorDim::Zero());
234 this->networkNode->trySet_P(mapped);
235 return;
236 }
237 if(!isPeriodicSubdivision())
238 {
239 // The trial point may be outside a physical face. Never assign it
240 // to the network node before the retained contour has been found.
241 SplineNodeType::set_P(this->loop()->glidePlane ? this->loop()->glidePlane->snapToPlane(newP) : newP);
242 }
243 }
244
245 template <int dim>
246 std::shared_ptr<PeriodicPlanePatch<dim>> DislocationLoopNode<dim>::periodicPlanePatch() const
247 {
248 return _periodicPlanePatch;
249 }
250
251 template <int dim>
256
257 template <int dim>
258 bool DislocationLoopNode<dim>::isGeometricallyRemovable(const double &Lmin,const double &Lmax,const double& relAreaTh)
259 {
260 const auto pPrev(periodicPrev());
261 const auto pNext(periodicNext());
262 if((pNext->get_P()-pPrev->get_P()).norm()<0.95*Lmax)
263 {
264 const double deltaArea(0.5 * (this->get_P() - pPrev->get_P()).cross(pNext->get_P() - this->get_P()).norm());
265
266 // VectorDim vectorArea(VectorDim::Zero());
267 // if (this->loop()->loopLinks().size())
268 // {
269 // const VectorDim P0((*this->loop()->loopLinks().begin())->source->get_P());
270 // for (const auto &loopLink : this->loop()->loopLinks())
271 // {
272 // vectorArea += 0.5 * (loopLink->source->get_P() - P0).cross(loopLink->sink->get_P() - loopLink->source->get_P());
273 // }
274 // }
275
276 // const double loopArea(vectorArea.norm());
277 const double loopArea(this->loop()->currentAreaVector().norm());
278 const double loopAreaRate(this->loop()->currentAreaRate());
279 // std::cout<<" For loop node "<<this->tag()<<" with "<<this->loop()->loopLinks().size()<<" loopLinks. loop area is "<<std::setprecision(15)<<loopArea<<std::endl;
280 if (loopArea > std::pow(Lmin, 2))
281 {
282 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " loopArea= " << loopArea << std::endl;);
283 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " deltaArea= " << deltaArea << std::endl;);
284 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " relAreaTh= " << relAreaTh << std::endl;);
285 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " removable? " << (deltaArea / loopArea < relAreaTh) << std::endl;);
286
287 return deltaArea / loopArea < relAreaTh;
288 }
289 else if (loopArea > FLT_EPSILON && loopAreaRate<-FLT_EPSILON)
290 {
291 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " removable (small loop)" << std::endl;);
292 return true;
293 }
294 else
295 {
296 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " NOT removable (zero area loop)" << std::endl;);
297 return false;
298 }
299 }
300 else
301 {
302 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " NOT removable (short segment)" << std::endl;);
303 return false;
304 }
305 }
306
307 //Version which can classiy the boundary nodes as well...
308 template <int dim>
309 std::pair<bool,size_t> DislocationLoopNode<dim>::isRemovable(const double &Lmin,const double &Lmax, const double &relAreaTh)
310 {
311 //The pair will be populated as follows:
312 //If the node is removable and it does not have a twin the pair will contain the same node
313 //Otherwise it will contrain the twin (in the removal then we have to remove both the current node and twin)
314
315 VerboseDislocationLoopNode(2, " Checking if DislocationLoopNode " << this->tag() << " is removable " << std::endl;);
316 if (periodicPlaneEdge.first)
317 { // a boundary node
318 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " onPlaneEdge" << std::endl;);
319 const auto pPrev(periodicPrev());
320 const auto pNext(periodicNext());
321 if (pPrev && pNext)
322 {
323 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " NOT removable (both periodicPrev and periodicNext exist)" << std::endl;);
324 return std::make_pair(false,0);
325 }
326 else
327 {
328 const double loopArea(this->loop()->currentAreaVector().norm());
329 if (loopArea < std::pow(Lmin, 2))
330 {
331 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " removable (on Edge via Geometric condition)" << std::endl;);
332 return std::make_pair(true,this->sID);
333 }
334 else
335 {
336 VerboseDislocationLoopNode(2, " DislocationLoopNode " << this->tag() << " NOT removable (on Edge)" << std::endl;);
337 return std::make_pair(false, 0);
338 }
339
340 }
341
342 }
343 else
344 { // not a boundary node
345 VerboseDislocationLoopNode(2, " Dislocation LoopNode Not on Boundary " << std::endl;);
346
347 const auto pPrev(periodicPrev());
348 const auto pNext(periodicNext());
349 // if ((pPrev->get_P() - pNext->get_P()).norm() < this->network().networkRemesher.Lmax)
350 // {
351 if (pPrev && pNext)
352 {
353 VerboseDislocationLoopNode(2, " Has pPrev and pNext" << std::endl;);
354
355 if (this->networkNode->loopNodes().size() == 1)
356 {
357 VerboseDislocationLoopNode(2, " Has 1 loop nodes" << std::endl;);
358 if ((pPrev->get_P() - pNext->get_P()).norm() < this->network().networkRemesher.Lmax
359// if (((pPrev->get_P() - pNext->get_P()).norm() < this->network().networkRemesher.Lmax || pPrev->periodicPlanePatch()!=pNext->periodicPlanePatch())
360 && isGeometricallyRemovable(Lmin, Lmax,relAreaTh))
361 {
362 return std::make_pair(true,this->sID);
363 }
364 else if (this->networkNode->isOnExternalBoundary())
365 {
366 //This means that an internal node is exactly on the the boundary based on the geometrically removable condition, the node can be removed
367 if (isGeometricallyRemovable(Lmin, Lmax, relAreaTh))
368 {
369 return std::make_pair(true,this->sID);
370 }
371 else
372 {
373 return std::make_pair(false,0);
374 }
375
376 }
377 else
378 {
379 return std::make_pair(false,0);
380 }
381 }
382 else if (this->networkNode->loopNodes().size() >= 2)
383 {
384 VerboseDislocationLoopNode(2, " Has 2 loop nodes" << std::endl;);
385 const auto prevTwin(this->prev.second->twinnedLink());
386 const auto nextTwin(this->next.second->twinnedLink());
387
388 if (prevTwin && nextTwin)
389 {
390 VerboseDislocationLoopNode(2, " Has prevTwin and nextTwin" << std::endl;);
391
392 if (prevTwin->loop == nextTwin->loop && (prevTwin->periodicPlanePatch() == nextTwin->periodicPlanePatch()))
393 {
394 VerboseDislocationLoopNode(2, " Same patches" << std::endl;);
395 //Check based on neighbors of the networkNode
396 //Here the other node will be inserted
397 size_t prevtwinID((prevTwin->source->networkNode==this->networkNode)? prevTwin->source->sID : prevTwin->sink->sID);
398 size_t nexttwinID((nextTwin->source->networkNode==this->networkNode)? nextTwin->source->sID : nextTwin->sink->sID);
399
400
401 if (prevtwinID==nexttwinID)
402 {
403 VerboseDislocationLoopNode(2, " Same IDs" << std::endl;);
404 return std::make_pair(true,prevtwinID);
405 }
406 else
407 {
408 // The other loop may visit this network node at
409 // distinct occurrences. They are not a removable pair.
410 return std::make_pair(false,0);
411 }
412
413 }
414 else
415 {
416 VerboseDislocationLoopNode(2, " Different patches" << std::endl;);
417 return std::make_pair(false, 0);
418 }
419 }
420 else
421 {
422 VerboseDislocationLoopNode(2, " No prevTwin or nextTwin" << std::endl;);
423 return std::make_pair(false,0);
424 }
425 }
426 else
427 {
428 VerboseDislocationLoopNode(2, "this->networkNode->loopNodes().size()="<<this->networkNode->loopNodes().size()<< std::endl;);
429 return std::make_pair(false,0);
430 }
431 }
432 else
433 {
434 VerboseDislocationLoopNode(2, " No pPrev or pNext" << std::endl;);
435 return std::make_pair(false,0);
436 }
437
438
439 }
440 }
441
442 template <int dim>
444 {
445 VerboseDislocationLoopNode(4,"checking if DislocationLoopNode "<<this->sID<< " isMovable:"<<std::endl;);
446
447 bool isMovable=true;
448
449 if(periodicPlaneEdge.first)
450 {
451 isMovable=(isMovable && ((X-this->get_P()).squaredNorm()<FLT_EPSILON));
452 }
453
454 if(isMovable && this->loop()->glidePlane)
455 {
456 isMovable=(isMovable && this->loop()->glidePlane->contains(X));
457 }
458 else
459 {
460 isMovable=false;
461 }
462
463 return isMovable;
464 }
465
466 template <int dim>
468
469 template class DislocationLoopNode<3>;
470}
471#endif
static void initFromFile(const std::string &)
TraitsType::LoopType LoopType
DislocationLoopNode(LoopNetworkType *const, const std::shared_ptr< LoopType > &, const std::shared_ptr< NetworkNodeType > &, const VectorDim &, const std::shared_ptr< PeriodicPlanePatch< dim > > &, const std::pair< const std::shared_ptr< PeriodicPlaneEdge< dim > >, const std::shared_ptr< PeriodicPlaneEdge< dim > > > &)
TraitsType::VectorDim VectorDim
std::pair< bool, size_t > isRemovable(const double &Lmin, const double &Lmax, const double &relAreaTh)
const DislocationLoopNodeType * periodicPrev() const
bool isGeometricallyRemovable(const double &Lmin, const double &Lmax, const double &relAreaTh)
TraitsType::LoopNetworkType LoopNetworkType
std::vector< DislocationLoopNodeType * > boundaryNext() const
std::shared_ptr< PeriodicPlanePatch< dim > > periodicPlanePatch() const
TraitsType::NetworkNodeType NetworkNodeType
bool isMovableTo(const VectorDim &) const
std::shared_ptr< DislocationLoopNode > clone(const std::shared_ptr< LoopType > &, const std::shared_ptr< NetworkNodeType > &) const
TraitsType::VectorLowerDim VectorLowerDim
std::vector< DislocationLoopNodeType * > boundaryPrev() const
const std::pair< const std::shared_ptr< PeriodicPlaneEdge< dim > >, const std::shared_ptr< PeriodicPlaneEdge< dim > > > periodicPlaneEdge
void set_P(const VectorDim &)
const DislocationLoopNodeType * periodicNext() const
TraitsType::LoopNodeType LoopNodeType
bool isContractableTo(const LoopNodeType *const other) const
std::shared_ptr< NetworkNodeType > networkNode
Definition LoopNode.h:61
const std::shared_ptr< LoopType > & loop() const
Definition LoopNode.h:122
std::pair< LoopNodeType *, LoopLinkType * > prev
Definition LoopNode.h:62
bool isContractableTo(const Derived *const other) const
Definition LoopNode.h:128
std::pair< LoopNodeType *, LoopLinkType * > next
Definition LoopNode.h:63
Scalar readScalar(const std::string &key, const bool &verbose=false)
vertex temp
result