Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
PeriodicGlidePlane_NEW.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_PeriodicGlidePlane_cpp_
9#define model_PeriodicGlidePlane_cpp_
10
11#include <numbers>
12#include <memory>
13#include <math.h>
14
15#include <Polyhedron.h>
16#include <MeshBoundarySegment.h>
17#include <PeriodicGlidePlane.h>
18//#include <PeriodicGlidePlane.hpp>
20
21namespace model
22{
23
24 template<int dim>
26 const std::shared_ptr<PeriodicPlaneNode<dim>>& source_in,
27 const std::shared_ptr<PeriodicPlaneNode<dim>>& sink_in,
28 const std::shared_ptr<const MeshBoundarySegment<dim>> meshIntersection_in,
29 const short int& edgeID_in) :
30 /* init */ patch(patch_in)
31 /* init */,source(source_in)
32 /* init */,sink(sink_in)
33 /* init */,meshIntersection(meshIntersection_in)
34 /* init */,edgeID(edgeID_in)
35 /* init */,deltaShift(meshIntersection->periodicShift())
36 /* init */,isPeriodicEdge(deltaShift.squaredNorm()>FLT_EPSILON && periodicFacesInSameGrain(meshIntersection_in))
37 /* init */,outNormal(patch->glidePlane->localDirection(meshIntersection->regionBoundaryNormal(patch->glidePlane->grain.grainID)).normalized())
38 /* init */,next(nullptr)
39 /* init */,prev(nullptr)
40 /* init */,twin(nullptr)
41 {
42 // std::cout<<"Creating PeriodicPlaneEdge "<<this->tag()<<std::endl;
43 source->addLink(this);
44 sink->addLink(this);
45 if(twin)
46 {
47 patch->patchBoundary->removeUntwinnedEdge(twin);
48 }
49 else
50 {
51 patch->patchBoundary->addUntwinnedEdge(this);
52 }
53 }
54
55 template<int dim>
56
57 bool PeriodicPlaneEdge<dim>::periodicFacesInSameGrain(const std::shared_ptr<const MeshBoundarySegment<dim>> meshIntersection_in)
58 {
59 bool temp(true);
60 for(const auto& face : meshIntersection_in->faces)
61 {
62 if(face->periodicFacePair.second)
63 {// face has periodic face
64 temp = (temp && face->regionIDs==face->periodicFacePair.second->regionIDs);
65 }
66 }
67 return temp;
68 }
69
70
71 template<int dim>
73 {
74 // std::cout<<"Destroying PeriodicPlaneEdge "<<this->tag()<<std::endl;
75
76 source->removeLink(this);
77 sink->removeLink(this);
78 if(next)
79 {
80 next->prev=nullptr;
81 }
82 if(prev)
83 {
84 prev->next=nullptr;
85 }
86 if(twin)
87 {
88 twin->twin=nullptr;
89 patch->patchBoundary->addUntwinnedEdge(twin);
90 }
91 else
92 {
93 patch->patchBoundary->removeUntwinnedEdge(this);
94 }
95 }
96
97 // template<int dim>
98 // typename PeriodicPlaneEdge<dim>::VectorDim PeriodicPlaneEdge<dim>::getDeltaShift(const PeriodicPlanePatch<dim>* const patch,const std::shared_ptr<const MeshBoundarySegment<dim>> meshIntersection)
99 // {
100 //
101 // // VectorDim shift(VectorDim::Zero());
102 // // for(const Polyhedron<dim,dim-1>* const face : meshIntersection->faces)
103 // // {
104 // // const auto parallelFaceID(patch->glidePlane->grain.region.parallelFaces().at(face->sID));
105 // // const auto parallelFace(patch->glidePlane->grain.region.faces().at(parallelFaceID));
106 // // shift+=(parallelFace->center()-face->center()).dot(face->outNormal())*face->outNormal();
107 //
108 // // }
109 // // return shift;
110 // // std::cout<<"Starting to calculate delta shift "<<std::endl;
111 // VectorDim shift(VectorDim::Zero());
112 // for(const Polyhedron<dim,dim-1>* const face : meshIntersection->faces)
113 // {
114 // // std::cout<<"Normal corresponding to this face "<<face->sID<<face->outNormal().transpose()<<std::endl;
115 // const auto parallelFaceID(patch->glidePlane->grain.region.parallelFaces().at(face->sID));
116 // const auto parallelFace(patch->glidePlane->grain.region.faces().at(parallelFaceID));
117 // const double parallelFD(((parallelFace->center()-face->center()).dot(face->outNormal())*face->outNormal()).norm());
118 //
119 // std::vector<VectorDim> vectorofNormals;
120 //
121 //
122 // for (const auto& pface : patch->glidePlane->grain.region.parallelFaces())
123 // {
124 // if (pface.first!= face->sID && pface.second!= face->sID)
125 // {
126 // const auto otherFaceOutNormal(patch->glidePlane->grain.region.faces().at(pface.second)->outNormal());
127 // vectorofNormals.push_back(otherFaceOutNormal);
128 // // const auto shiftDirection((face->outNormal()-(face->outNormal().dot(otherFaceOutNormal)*otherFaceOutNormal)).normalized());
129 // // std::cout<<"Shift direction "<<shiftDirection.transpose()<<std::endl;
130 // // VectorDim faceShift(shiftDirection*parallelFD/face->outNormal().dot(shiftDirection));
131 // // shift+=0.5*faceShift;
132 // }
133 // }
134 // GramSchmidt::orthoNormalize(vectorofNormals);
135 // VectorDim faceShift(face->outNormal());
136 // for (const auto& normal : vectorofNormals)
137 // {
138 // faceShift-=faceShift.dot(normal)*normal;
139 // }
140 // faceShift.normalize();
141 // shift-=faceShift*parallelFD/faceShift.dot(face->outNormal());
142 // }
143 // // std::cout<<"Finished to calculate delta shift "<<shift.transpose()<<std::endl;
144 //
145 // return shift;
146 // }
147
148 template<int dim>
149 std::string PeriodicPlaneEdge<dim>::tag() const
150 {
152 return std::to_string(source->sID) + " " + std::to_string(sink->sID)+" "+std::to_string(patch->sID)+" ("+std::to_string(edgeID)+")";
153 }
154
155 template<int dim>
157 {
159
160 if(next->twin)
161 {
162 return next->twin->nextUntwinned();
163 }
164 else
165 {
166 return next;
167 }
168 }
169
170 template<int dim>
172 {
174
175 if(prev->twin)
176 {
177 return prev->twin->prevUntwinned();
178 }
179 else
180 {
181 return prev;
182 }
183 }
184
185 template<int dim>
187 /* init*/ VectorLowerDim(pos)
188 {
189
190 }
191
192 template<int dim>
193 void PeriodicPlaneNode<dim>::addLink(PeriodicPlaneEdgeType* const link)
194 {
195
196 if(link->sink->sID==this->sID)
197 {// edge ends at this node, so link is an inLink
198
199 // Update _patchConnectivities
200 NodalConnectivityType& patchConnectivity(patchConnectivities()[link->patch->sID]);
201 assert(patchConnectivity.inEdge==nullptr);
202 patchConnectivity.inEdge=link;
203 if(patchConnectivity.outEdge)
204 {// and outEdge of the same patch is connected to this node
205 assert(patchConnectivity.outEdge->prev==nullptr);
206 assert(link->next==nullptr);
207 patchConnectivity.outEdge->prev=link;
208 link->next=patchConnectivity.outEdge;
209 }
210
211 // Update _neighborConnectivities
212 NodalConnectivityType& neighborConnectivity(neighborConnectivities()[link->source->sID]);
213 assert(neighborConnectivity.inEdge==nullptr || neighborConnectivity.inEdge==link);
214 neighborConnectivity.inEdge=link;
215 if(neighborConnectivity.outEdge)
216 {// and outEdge of the same patch is connected to this node
217 assert(neighborConnectivity.outEdge->twin==nullptr || neighborConnectivity.outEdge->twin==link);
218 assert(link->twin==nullptr || link->twin==neighborConnectivity.outEdge);
219 neighborConnectivity.outEdge->twin=link;
220 link->twin=neighborConnectivity.outEdge;
221 }
222
223 }
224 else if(link->source->sID==this->sID)
225 {// edge starts at this node, so link is an outLink
226
227 // Update _patchConnectivities
228 NodalConnectivityType& patchConnectivity(patchConnectivities()[link->patch->sID]);
229 assert(patchConnectivity.outEdge==nullptr);
230 patchConnectivity.outEdge=link;
231 if(patchConnectivity.inEdge)
232 {
233 assert(patchConnectivity.inEdge->next==nullptr);
234 assert(link->prev==nullptr);
235 patchConnectivity.inEdge->next=link;
236 link->prev=patchConnectivity.inEdge;
237 }
238
239 // Update _neighborConnectivities
240 NodalConnectivityType& neighborConnectivity(neighborConnectivities()[link->sink->sID]);
241 assert(neighborConnectivity.outEdge==nullptr || neighborConnectivity.outEdge==link);
242 neighborConnectivity.outEdge=link;
243 if(neighborConnectivity.inEdge)
244 {// and outEdge of the same patch is connected to this node
245 assert(neighborConnectivity.inEdge->twin==nullptr || neighborConnectivity.inEdge->twin==link);
246 assert(link->twin==nullptr || link->twin==neighborConnectivity.inEdge);
247 neighborConnectivity.inEdge->twin=link;
248 link->twin=neighborConnectivity.inEdge;
249 }
250 }
251 else
252 {
253 assert(false && "CONNECTING LINK TO NON-INCIDENT NODE");
254 }
255
256 }
257
258 template<int dim>
259 void PeriodicPlaneNode<dim>::removeLink(PeriodicPlaneEdgeType* const link)
260 {
261
262 if(link->sink->sID==this->sID)
263 {// edge ends at this node, so link is an inLink
264
265 // Update _patchConnectivities
266 auto patchIter(patchConnectivities().find(link->patch->sID));
267 assert(patchIter!=patchConnectivities().end() && "PATCH NOT FOUND IN patchConnectivities");
268 NodalConnectivityType& patchConnectivity(patchIter->second);
269 assert(patchConnectivity.inEdge==link);
270 patchConnectivity.inEdge=nullptr;
271 if(patchConnectivity.inEdge==nullptr && patchConnectivity.outEdge==nullptr)
272 {
273 patchConnectivities().erase(patchIter);
274 }
275
276 // Update _neighborConnectivities
277 auto neighborIter(neighborConnectivities().find(link->source->sID));
278 assert(neighborIter!=neighborConnectivities().end() && "NEIGHBOR NOT FOUND IN neighborConnectivity");
279 NodalConnectivityType& neighborConnectivity(neighborIter->second);
280 assert(neighborConnectivity.inEdge==link);
281 neighborConnectivity.inEdge=nullptr;
282 if(neighborConnectivity.inEdge==nullptr && neighborConnectivity.outEdge==nullptr)
283 {
284 neighborConnectivities().erase(neighborIter);
285 }
286
287 }
288 else if(link->source->sID==this->sID)
289 {// edge starts at this node, so link is an outLink
290
291 // Update _patchConnectivities
292 auto patchIter(patchConnectivities().find(link->patch->sID));
293 assert(patchIter!=patchConnectivities().end() && "PATCH NOT FOUND IN patchConnectivities");
294 NodalConnectivityType& patchConnectivity(patchIter->second);
295 assert(patchConnectivity.outEdge==link);
296 patchConnectivity.outEdge=nullptr;
297 if(patchConnectivity.inEdge==nullptr && patchConnectivity.outEdge==nullptr)
298 {
299 patchConnectivities().erase(patchIter);
300 }
301
302 // Update _neighborConnectivities
303 auto neighborIter(neighborConnectivities().find(link->sink->sID));
304 assert(neighborIter!=neighborConnectivities().end() && "NEIGHBOR NOT FOUND IN neighborConnectivity");
305 NodalConnectivityType& neighborConnectivity(neighborIter->second);
306 assert(neighborConnectivity.outEdge==link);
307 neighborConnectivity.outEdge=nullptr;
308 if(neighborConnectivity.inEdge==nullptr && neighborConnectivity.outEdge==nullptr)
309 {
310 neighborConnectivities().erase(neighborIter);
311 }
312 }
313 else
314 {
315 assert(false && "DISCONNECTING LINK FROM NON-INCIDENT NODE");
316 }
317 }
318
319 template<int dim>
321 {
322 return _patchConnectivities;
323 }
324
325 template<int dim>
327 {
328 return _patchConnectivities;
329 }
330
331 template<int dim>
333 {
334 return _neighborConnectivities;
335 }
336
337 template<int dim>
339 {
340 return _neighborConnectivities;
341 }
342
343 template<int dim>
345 {
346 InOutEdgeContainerType temp;
347 for(const auto& connectivity : neighborConnectivities())
348 {
349 if(connectivity.second.inEdge && !connectivity.second.outEdge)
350 {
351 assert(connectivity.second.inEdge->twin==nullptr);
352 temp.insert(connectivity.second.inEdge);
353 }
354 }
355 return temp;
356 }
357
358 template<int dim>
360 {
361 InOutEdgeContainerType temp;
362 for(const auto& connectivity : neighborConnectivities())
363 {
364 if(connectivity.second.outEdge && !connectivity.second.inEdge)
365 {
366 assert(connectivity.second.outEdge->twin==nullptr);
367 temp.insert(connectivity.second.outEdge);
368 }
369 }
370 return temp;
371 }
372
373 template<int dim>
375 const VectorDim& shift_in) :
376 /* init */ patchBoundary(periodicPatchBoundary_in)
377 /* init */,shift(shift_in)
378 /* init */,glidePlane(patchBoundary->getGlidePlane(shift))
379 {
380 // std::cout<<cyanColor<<"Creating patch "<<this->sID<<" with shift="<<std::setprecision(15)<<std::scientific<<shift.transpose()<<defaultColor<<std::endl;
381
382 if(isRightHandedBoundary(glidePlane->meshIntersections,*patchBoundary->referencePlane))
383 {
384 addMeshIntersections(glidePlane->meshIntersections);
385 }
386 else
387 {
388 BoundingMeshSegments<dim> flippedTemp;
389 for (auto it = glidePlane->meshIntersections.rbegin(); it != glidePlane->meshIntersections.rend(); ++it)
390 {
391 flippedTemp.emplace_back(new MeshBoundarySegment<dim>((*it)->P1,(*it)->P0,(*it)->faces));
392 }
393 addMeshIntersections(flippedTemp);
394 }
395
396 patchBoundary->updateBoundaries();
397
398 }
399
400 template<int dim>
401 PeriodicPlanePatch<dim>::~PeriodicPlanePatch()
402 {
403 // std::cout<<cyanColor<<"Destroying patch "<<this->sID<<" with shift="<<std::setprecision(15)<<std::scientific<<shift.transpose()<<defaultColor<<std::endl;
404 this->clear(); // call before updateBoundaries
405 patchBoundary->updateBoundaries();
406 }
407
408 template<int dim>
409 bool PeriodicPlanePatch<dim>::isRightHandedBoundary(const BoundingMeshSegments<dim>& bnd,const Plane<dim>& plane)
410 {
411 if(bnd.size())
412 {
413 VectorDim nA(VectorDim::Zero());
414 const VectorDim P0(bnd.front()->P0);
415 for(const auto& seg : bnd)
416 {
417 nA+= 0.5*(seg->P0-P0).cross(seg->P1-seg->P0);
418 }
419 return nA.dot(plane.unitNormal)>0.0;
420 }
421 else
422 {
423 return false;
424 }
425 }
426
427 template<int dim>
428 void PeriodicPlanePatch<dim>::addMeshIntersections(const BoundingMeshSegments<dim>& bms)
429 {
430 //
431 // std::vector<std::tuple<std::shared_ptr<PeriodicPlaneNode<dim>>,std::shared_ptr<PeriodicPlaneNode<dim>>,std::shared_ptr<MeshBoundarySegment<dim>>,double>> tempEdges;
432 // for(size_t k=0;k<bms.size();++k)
433 // {// compute 2d points on PeriodicPlane, and coneect them
434 // std::shared_ptr<PeriodicPlaneNode<dim>> source(patchBoundary->getSharedNode(bms[k]->P0,shift));
435 // std::shared_ptr<PeriodicPlaneNode<dim>> sink(patchBoundary->getSharedNode(bms[k]->P1,shift));
436 // tempEdges.emplace_back(source,sink,bms[k],0.0);
437 // }
438 //
439 // VectorLowerDim C(VectorLowerDim::Zero());
440 // for(const auto& tup : tempEdges)
441 // {
442 // C+=*std::get<0>(tup);
443 // }
444 // C/=tempEdges.size(); // position of center of patch
445 //
446 // std::pair<double,size_t> minAngle(std::numbers::pi,tempEdges.size());
447 // for(size_t k=0;k<tempEdges.size();++k)
448 // {
449 // const auto x(*std::get<0>(tempEdges[k])-C);
450 // const double angle(std::fabs(atan2(x(1),x(0))));
451 // if(angle<minAngle.first)
452 // {
453 // minAngle.first=angle;
454 // minAngle.second=k;
455 // }
456 // std::get<3>(tempEdges[k])=angle;
457 // }
458 //
459 // // store edges starting from source of minimum angle
460 // for(size_t s=0;s<tempEdges.size();++s)
461 // {
462 // const short int k((minAngle.second+s)%tempEdges.size());
463 // this->emplace_back(new PeriodicPlaneEdge<dim>(this,std::get<0>(tempEdges[k]),std::get<1>(tempEdges[k]),std::get<2>(tempEdges[k]),s));
464 // }
465
466 //
467 for(size_t k=0;k<bms.size();++k)
468 {// compute 2d points on PeriodicPlane, and coneect them
469 std::shared_ptr<PeriodicPlaneNode<dim>> source(patchBoundary->getSharedNode(bms[k]->P0,shift));
470 std::shared_ptr<PeriodicPlaneNode<dim>> sink(patchBoundary->getSharedNode(bms[k]->P1,shift));
471 //this->emplace_back(new PeriodicPlaneEdge<dim>(this,source,sink,bms[k]));
472 this->emplace_back(new PeriodicPlaneEdge<dim>(this,source,sink,bms[k],k));
473 }
474 }
475
476 template<int dim>
477 const typename PeriodicPlanePatch<dim>::PeriodicPlaneEdgeContainerType& PeriodicPlanePatch<dim>::edges() const
478 {
479 return *this;
480 }
481
482 template<int dim>
483 std::shared_ptr<PeriodicPlaneEdge<dim>> PeriodicPlanePatch<dim>::edgeOnFaces(const std::set<const Polyhedron<dim,dim-1>*>& faces) const
484 {
485 for(const auto& edge : edges())
486 {
487 if(edge->meshIntersection->faces==faces)
488 {
489 return edge;
490 }
491 }
492 return std::shared_ptr<PeriodicPlaneEdge<dim>>(nullptr);
493 }
494
495 template<int dim>
496 int PeriodicPlanePatch<dim>::contains(const VectorLowerDim& test) const
497 {
498 // const auto& outerBoundary(outerBoundaries()[0]);
499 size_t i, j, c = 0;
500 for (i = 0, j = edges().size()-1; i < edges().size(); j = i++)
501 {
502 const VectorLowerDim& Pi(*edges()[i]->source);
503 const VectorLowerDim& Pj(*edges()[j]->source);
504
505 if ( ((Pi(1)>test(1)) != (Pj(1)>test(1))) &&
506 (test(0) < (Pj(0)-Pi(0)) * (test(1)-Pi(1)) / (Pj(1)-Pi(1)) + Pi(0)
507 //+std::numeric_limits<double>::epsilon()
508 ) )
509 {
510 c = !c;
511 }
512 }
513 return c;
514 }
515
516 template<int dim>
517 PeriodicPatchBoundary<dim>::PeriodicPatchBoundary(GlidePlaneFactory<dim>& glidePlaneFactory_in, const std::shared_ptr<GlidePlane<dim>>& referencePlane_in) :
518 /* init */ glidePlaneFactory(glidePlaneFactory_in)
519 /* init */,referencePlane(referencePlane_in)
520 // /* init */,L2G(getL2G(referencePlane->unitNormal))
521 {
522
523 assert(referencePlane->meshIntersections.size()>=3);
524 }
525
526 template<int dim>
528 {
529 return _outerBoundaries;
530 }
531
532 template<int dim>
534 {
535 return _outerBoundaries;
536 }
537
538 template<int dim>
540 {
541 return _innerBoundaries;
542 }
543
544 template<int dim>
546 {
547 return _innerBoundaries;
548 }
549
550 template<int dim>
552 {
553 return *this;
554 }
555
556 template<int dim>
558 {
559 return *this;
560 }
561
562 template<int dim>
564 {
565 untwinnedEdges().insert(link);
566 }
567
568 template<int dim>
570 {
571 const size_t erased(untwinnedEdges().erase(link));
572 if(erased!=1)
573 {
574 throw std::runtime_error("COULD NOT ERASE LINK FROM BOUNDARYLINKS");
575 }
576 // assert(erased==1 && "COULD NOT ERASE LINK FROM BOUNDARYLINKS");
577 }
578
579 template<int dim>
581 {
582 return *this;
583 }
584
585 template<int dim>
587 {
588 return *this;
589 }
590
591 template<int dim>
593 {
594 if(isCompact())
595 {
596 const auto& outerBoundary(outerBoundaries()[0]);
597 size_t i, j, c = 0;
598 for (i = 0, j = outerBoundary.size()-1; i < outerBoundary.size(); j = i++)
599 {
600 const VectorLowerDim& Pi(*outerBoundary[i]->source);
601 const VectorLowerDim& Pj(*outerBoundary[j]->source);
602
603 if ( ((Pi(1)>test(1)) != (Pj(1)>test(1))) &&
604 (test(0) < (Pj(0)-Pi(0)) * (test(1)-Pi(1)) / (Pj(1)-Pi(1)) + Pi(0)) )
605 {
606 c = !c;
607 }
608 }
609 return c;
610 }
611 else
612 {
613 return 0;
614 }
615 }
616
617 template<int dim>
619 {
620 return outerBoundaries().size()==1 && innerBoundaries().size()==0;
621 }
622
623 template<int dim>
625 {// TO DO: THIS SHOULD USE THE 2D POINTS
626 if(bnd.size()>=3)
627 {
628 VectorDim nA(VectorDim::Zero());
629 const VectorDim P0(bnd.front()->meshIntersection->P0-(bnd.front())->patch->shift);
630 for(const auto& seg : bnd)
631 {
632 VectorDim temp_shift=seg->patch->shift;
633 VectorDim P0_temp=seg->meshIntersection->P0-temp_shift;
634 VectorDim P1_temp=seg->meshIntersection->P1-temp_shift;
635 nA+= 0.5*(P0_temp-P0).cross(P1_temp-P0_temp);
636 }
637 return nA;
638 }
639 else
640 {
641 return VectorDim::Zero();
642 }
643 }
644
645 template<int dim>
646 double PeriodicPatchBoundary<dim>::rightHandedArea(const std::vector<const PeriodicPlaneEdge<dim>*>& bnd)
647 {
648 return rightHandedNormal(bnd).dot(referencePlane->unitNormal);
649 }
650
651 template<int dim>
653 {
654 return rightHandedArea(bnd)>=0.0;
655 }
656
657 template<int dim>
658 std::shared_ptr<PeriodicPlaneNode<dim> > PeriodicPatchBoundary<dim>::getSharedNode(const VectorDim& pointDim,const VectorDim& shift)
659 {
660 // const VectorLowerDim point(referencePlane->localPosition(pointDim-shift));
661 return nodes().getFromKey(referencePlane->localPosition(pointDim-shift));
662 }
663
664 template<int dim>
665 void PeriodicPatchBoundary<dim>::createNewBoundary(const PeriodicPlaneEdge<dim>* currentEdge,UntwinnedEdgeContainerType& untwinnedCopy)
666 {
667 BoundaryContainerType temp;
668 temp.reserve(untwinnedCopy.size());
669 while(true)
670 {
671 temp.push_back(currentEdge);
672 const size_t erased(untwinnedCopy.erase(currentEdge));
673 if(erased!=1)
674 {
675
676 std::cout<<"Trying to erase "<<currentEdge->tag()<<std::endl;
677 std::cout<<"untwinnedCopy is"<<std::endl;
678 for(const auto& edgePtr : untwinnedCopy)
679 {
680 std::cout<<" "<<edgePtr->tag()<<std::endl;
681 }
682
683 std::ofstream pointsFile("points.txt");
684 std::cout<<"points"<<std::endl;
685 for(const auto& node : this->nodes())
686 {
687 if(!node.second.expired())
688 {
689 pointsFile<<" "<<node.second.lock()->sID<<" "<<node.first.transpose()<<std::endl;
690 std::cout<<" "<<node.second.lock()->sID<<" "<<node.first.transpose()<<std::endl;
691 }
692 }
693
694
695 // std::ofstream edgesFile("edges.txt");
696 // for(const auto& patch : patches())
697 // {
698 // for(const auto& edge : patch.second->edges())
699 // {
700 // edgesFile<<edge->tag()<<std::endl;
701 // }
702 // }
703
704 throw std::runtime_error("could not find link in untwinnedEdges 2");
705
706 // assert(erased==1 && "could not find link in untwinnedEdges 2");
707 }
708 if(temp.back()->sink->sID==temp.front()->source->sID)
709 {
710 break;
711 }
712 currentEdge=currentEdge->next;
713 while(currentEdge->twin)
714 {
715 currentEdge=currentEdge->twin->next;
716 }
717
718 }
719
720 if(temp.size())
721 {// if temp is not empty a loop was closed.
722 if(this->isRightHandedBoundary(temp))
723 {// assign temp to _outerBoundaries
724 this->_outerBoundaries.push_back(temp);
725 }
726 else
727 {// assign temp to _innerBoundaries
728 this->_innerBoundaries.push_back(temp);
729
730 }
731 }
732 }
733
734 //Other version (for the case where "must start from node with only one edge in and one edge out" is not possible)
735 template<int dim>
737 {
738 // std::cout<<"Updating OuterBoundary"<<std::endl;
739 this->outerBoundaries().clear();
740 this->innerBoundaries().clear();
741 UntwinnedEdgeContainerType untwinnedCopy(this->untwinnedEdges());
742 while(untwinnedCopy.size())
743 {
744 size_t untwinnedSize(untwinnedCopy.size());
745 for(const auto& edge : untwinnedCopy)
746 {
747 if(edge->source->outEdges().size()==1 && edge->source->inEdges().size()==1) //Discuss this with Dr. Po(Yash)
748 {// must start from node with only one edge in and one edge out
749 createNewBoundary(edge,untwinnedCopy);
750 break;
751 }
752 }
753 if (untwinnedCopy.size() && untwinnedCopy.size()==untwinnedSize) //No node exists with only one edge in and one edge out
754 {
755 createNewBoundary(*untwinnedCopy.begin(),untwinnedCopy);
756
757 }
758 }
759 }
760
761 template<int dim>
762 std::shared_ptr<PeriodicPlanePatch<dim>> PeriodicPatchBoundary<dim>::getPatch(const VectorDim& shift)
763 {
764 return patches().getFromKey(shift);
765 }
766
767 template<int dim>
769 {
770 return *this;
771 }
772
773 template<int dim>
775 {
776 return *this;
777 }
778
779 template<int dim>
781 {
782 return GlidePlaneKey<dim>(referencePlane->P+shift,referencePlane->n);
783 }
784
785 template<int dim>
786 std::shared_ptr<GlidePlane<dim>> PeriodicPatchBoundary<dim>::getGlidePlane(const VectorDim& shift)
787 {
788 return glidePlaneFactory.getFromKey(getGlidePlaneKey(shift));
789 }
790
791 template<int dim>
792 PeriodicGlidePlane<dim>::PeriodicGlidePlane(PeriodicGlidePlaneFactoryType* const pgpf,
793 const KeyType& key_in) :
794 /* init */ PeriodicPatchBoundary<dim>(pgpf->glidePlaneFactory,pgpf->glidePlaneFactory.getFromKey(key_in))
795 // /* init */ PeriodicPatchBoundary<dim>(pgpf->glidePlaneFactory.getFromKey(key_in))
796 /* init */,glidePlaneFactory(pgpf->glidePlaneFactory)
797 /* init */,periodicGlidePlaneFactory(*pgpf)
798 /* init */,referencePlane(pgpf->glidePlaneFactory.getFromKey(key_in))
799 {
800
801 }
802
803 template<int dim>
804 std::pair<typename PeriodicGlidePlane<dim>::VectorDim,bool> PeriodicGlidePlane<dim>::findPatch(const typename PeriodicGlidePlane<dim>::VectorLowerDim& P0,const VectorDim& guessShift)
805 {
806
807 PeriodicPatchBoundary<dim> patchBoundary(glidePlaneFactory,referencePlane);
808 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> currentPatches; // keep patches alive during search
809
810
811 // Set up a starting point
812 std::shared_ptr<PeriodicPlanePatch<dim>> lastPatch(patchBoundary.getPatch(guessShift));
813 currentPatches.push_back(lastPatch); // keep patches alive durin current line segment search
814 const std::shared_ptr<GlidePlane<dim>>& centralPlane(lastPatch->glidePlane);
815 VectorLowerDim insideReferencePoint(VectorLowerDim::Zero());
816 for(const auto& seg : centralPlane->meshIntersections) // problem is here for referencePlane not cutting mesh
817 {
818 insideReferencePoint+=referencePlane->localPosition(seg->P0-lastPatch->shift)/centralPlane->meshIntersections.size();
819 }
820 // insideReferencePoint/=centralPlane->meshIntersections.size();
821 if(!lastPatch->contains(insideReferencePoint))
822 {
823 throw std::runtime_error("lastPatch does not cointain insideReferencePoint");
824 }
825 // assert(lastPatch->contains(insideReferencePoint));
826
827 // Find initial point
828 // const VectorLowerDim P0(polyPoints[0]);
829 while(!lastPatch->contains(P0))
830 {
831 std::set<const PeriodicPlaneEdge<dim>*> crossdEdges;
832 for(const auto& bndEdge : patchBoundary.untwinnedEdges())
833 {// loop over outer boundaries and holes
834 SegmentSegmentDistance<dim-1> ssd(P0,insideReferencePoint,*bndEdge->source,*bndEdge->sink);
835 if(ssd.dMin<FLT_EPSILON)
836 {// intersection with current boundary found
837 // std::cout<<ssd.x0.transpose()<<std::endl;
838 crossdEdges.insert(bndEdge);
839 }
840 }
841
842 switch (crossdEdges.size())
843 {
844 case 1:
845 {
846 assert(lastPatch.get()==(*crossdEdges.begin())->patch);
847 if((*crossdEdges.begin())->deltaShift.squaredNorm()<FLT_EPSILON)
848 {
849 return std::make_pair(VectorDim::Zero(),false);
850 }
851 const VectorDim newShift((*crossdEdges.begin())->deltaShift+(*crossdEdges.begin())->patch->shift);
852 lastPatch=patchBoundary.getPatch(newShift);
853 currentPatches.push_back(lastPatch); // keep patches alive durin current line segment search
854 break;
855 }
856
857 case 2:
858 {
859 assert(lastPatch.get()==(*crossdEdges.begin())->patch);
860 assert((*crossdEdges.begin())->patch==(*crossdEdges.rbegin())->patch);
861 if(((*crossdEdges.begin())->deltaShift+(*crossdEdges.rbegin())->deltaShift).squaredNorm()<FLT_EPSILON)
862 {
863 return std::make_pair(VectorDim::Zero(),false);
864 }
865 const VectorDim newShift((*crossdEdges.begin())->deltaShift+(*crossdEdges.rbegin())->deltaShift+(*crossdEdges.begin())->patch->shift);
866 lastPatch=patchBoundary.getPatch(newShift);
867 currentPatches.push_back(lastPatch); // keep patches alive durin current line segment search
868 // const auto shiftIter(usedPatches.find(newShift));
869 // if(shiftIter==usedPatches.end())
870 // {
871 // lastPatch=usedPatches.emplace(newShift,new PeriodicPlanePatch<dim>(*this,newShift)).first->second;
872 // }
873 // else
874 // {
875 // lastPatch=shiftIter->second;
876 // }
877 //
878 //
879 // usedPatches.emplace(new PeriodicPlanePatch<dim>(*this,getShift(**crossdEdges.begin())+getShift(**crossdEdges.rbegin())+(*crossdEdges.begin())->patch->shift));
880 // getPatch(getShift(**crossdEdges.begin())+getShift(**crossdEdges.rbegin())+(*crossdEdges.begin())->patch->shift);
881 break;
882 }
883
884 default:
885 {
886 std::cout<<"untwinnedEdges().size()="<<patchBoundary.untwinnedEdges().size()<<std::endl;
887 std::cout<<"crossdEdges.size()="<<crossdEdges.size()<<std::endl;
888 throw std::runtime_error("1 or 2 edges must be crossed");
889 // assert(false && "1 or 2 edges must be crossed");
890 break;
891 }
892 }
893 }
894 assert(lastPatch->contains(P0));
895 if(!lastPatch->contains(P0))
896 {
897 throw std::runtime_error("lastPatch does not cointain searched point.");
898 }
899 return std::make_pair(lastPatch->shift,true);
900 }
901
902 template<int dim>
904 {
905 std::cout<<"PeriodiPlane nodes:"<<std::endl;
906 for(const auto& node : this->nodes())
907 {
908 if(!node.second.expired())
909 {
910 std::cout<<node.second.lock()->sID<<" "<<node.first.transpose()<<std::endl;
911 }
912 }
913
914 }
915
916 template<int dim>
917 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> PeriodicGlidePlane<dim>::filledPatches(const std::vector<VectorDim>& patchShifts)
918 {/*\returns a vector of patch-shifts (including startShifts) which closes the "holes" on pgp
919 */
920 // Collect patches of the loop. We create a temporary PeriodicPatchBoundary for this, having only the patches of this loop
921 PeriodicPatchBoundary<dim> patchBoundary(glidePlaneFactory,referencePlane);
922 std::set<std::shared_ptr<PeriodicPlanePatch<dim>>> tempPatches;
923 for(const auto& ps : patchShifts)
924 {
925 tempPatches.insert(patchBoundary.getPatch(ps));
926 }
927 // There may be "holes" in the patches. Close them
928 while(patchBoundary.innerBoundaries().size())
929 {
930 const PeriodicPlaneEdge<dim>* const holeEdge(*patchBoundary.innerBoundaries().front().begin());
931 tempPatches.insert(patchBoundary.getPatch(holeEdge->deltaShift+holeEdge->patch->shift));
932 }
933
934 // Now grab corresponding patches from this->patchBoundary
935 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> temp;
936 for(const auto& patch : tempPatches)
937 {
938 temp.push_back(this->getPatch(patch->shift));
939 }
940 return temp;
941 }
942
943 template<int dim>
945 /* init */ glidePlaneID(0)
946 /* init */,patchBoundaryID(0)
947 /* init */,shift(VectorDim::Zero())
948 {
949
950 }
951
952 template<int dim>
954 /* init */ glidePlaneID(patch.glidePlane->sID)
955 /* init */,patchBoundaryID(patch.patchBoundary->sID)
956 /* init */,shift(patch.shift)
957 {
958
959 }
960
961 template<int dim>
963 /* init */ glidePlaneID(0)
964 /* init */,patchBoundaryID(0)
965 /* init */,shift(VectorDim::Zero())
966 {
967 ss>>glidePlaneID;
968 ss>>patchBoundaryID;
969 for(int d=0;d<dim;++d)
970 {
971 ss>>shift(d);
972 }
973 }
974
975 template struct PeriodicPlaneEdge<3>;
976 template struct PeriodicPatchBoundary<3>;
977 template class PeriodicPlaneNode<3>;
978 template struct PeriodicPlanePatch<3>;
979 template class PeriodicGlidePlane<3>;
980 template struct PeriodicPlanePatchIO<3>;
981}
982#endif
Class template representing a straight line at the intersection of PlanarMeshFaces.
std::pair< VectorDim, bool > findPatch(const VectorLowerDim &, const VectorDim &)
Eigen::Matrix< double, dim-1, 1 > VectorLowerDim
std::vector< std::shared_ptr< PeriodicPlanePatch< dim > > > filledPatches(const std::vector< VectorDim > &patchShifts)
PeriodicGlidePlane(PeriodicGlidePlaneFactoryType *const pgpf, const KeyType &key_in)
const NodalConnectivityContainerType & neighborConnectivities() const
const NodalConnectivityContainerType & patchConnectivities() const
void removeLink(PeriodicPlaneEdgeType *const link)
InOutEdgeContainerType outEdges() const
void addLink(PeriodicPlaneEdgeType *const link)
std::map< size_t, NodalConnectivity< dim > > NodalConnectivityContainerType
PeriodicPlaneNode(PeriodicPatchBoundary< dim > *const, const VectorLowerDim &pos)
InOutEdgeContainerType inEdges() const
std::set< PeriodicPlaneEdgeType * > InOutEdgeContainerType
c
Definition int_R.m:15
auto test(const std::shared_ptr< T > &t)
LatticePlaneKey< dim > GlidePlaneKey
Eigen::Matrix< double, 3, 1 > VectorDim
Definition pyMoDELib.cxx:66
static VectorDim rightHandedNormal(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
void createNewBoundary(const PeriodicPlaneEdge< dim > *currentEdge, UntwinnedEdgeContainerType &untwinnedCopy)
KeyConstructableWeakPtrFactory< PeriodicPatchBoundary< dim >, PeriodicPlaneNode< dim >, typename PeriodicPlaneNode< dim >::CompareType > NodeCointainerType
const PatchContainerType & patches() const
BoundariesContainerType & innerBoundaries()
bool isRightHandedBoundary(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
std::set< const PeriodicPlaneEdge< dim > * > UntwinnedEdgeContainerType
void addUntwinnedEdge(const PeriodicPlaneEdge< dim > *link)
std::shared_ptr< GlidePlane< dim > > getGlidePlane(const VectorDim &shift)
double rightHandedArea(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
int isInsideOuterBoundary(const VectorLowerDim &test)
KeyConstructableWeakPtrFactory< PeriodicPatchBoundary< dim >, PeriodicPlanePatch< dim >, typename PeriodicPlanePatch< dim >::CompareType > PatchContainerType
std::vector< BoundaryContainerType > BoundariesContainerType
Eigen::Matrix< double, dim, 1 > VectorDim
const UntwinnedEdgeContainerType & untwinnedEdges() const
std::shared_ptr< PeriodicPlanePatch< dim > > getPatch(const VectorDim &shift)
std::shared_ptr< PeriodicPlaneNode< dim > > getSharedNode(const VectorDim &pointDim, const VectorDim &shift)
BoundariesContainerType & outerBoundaries()
GlidePlaneKey< dim > getGlidePlaneKey(const VectorDim &shift)
void removeUntwinnedEdge(const PeriodicPlaneEdge< dim > *link)
PeriodicPlaneEdge(const PeriodicPlanePatch< dim > *const patch_in, const std::shared_ptr< PeriodicPlaneNode< dim > > &source_in, const std::shared_ptr< PeriodicPlaneNode< dim > > &sink_in, const std::shared_ptr< const MeshBoundarySegment< dim > > meshIntersection_in, const short int &)
PeriodicPlaneEdge< dim > * next
PeriodicPlaneEdge< dim > * nextUntwinned() const
PeriodicPlaneEdge< dim > * prevUntwinned() const
static bool periodicFacesInSameGrain(const std::shared_ptr< const MeshBoundarySegment< dim > > meshIntersection_in)
PeriodicPlaneEdge< dim > * prev
PeriodicPlanePatch(PeriodicPatchBoundary< dim > *const, const VectorDim &)
int end[2]
m edges
int j
newsubseg ss[0]
int k
int i
vertex temp