93 std::vector<size_t> candidates;
94 for(
const auto& entry : DN.networkNodes())
96 candidates.push_back(entry.first);
98 for(
const size_t id : candidates)
100 const auto node=DN.networkNodes().get(
id);
101 if(!node || node->neighbors().size()!=2 || node->loopNodes().empty())
105 std::vector<std::shared_ptr<LoopNode>> representations;
106 std::set<size_t> loops;
107 std::pair<size_t,size_t> endpoints;
109 for(
const auto* ln : node->loopNodes())
111 const auto* prev=ln->prev.first;
112 const auto* next=ln->next.first;
113 const auto& edge=ln->periodicPlaneEdge.first;
117 if(!prev || !next || !edge || ln->periodicPlaneEdge.second ||
118 !ln->isPhysicalBoundaryNode() || edge->meshIntersection->faces.size()!=1 ||
119 ln->periodicPlanePatch()!=prev->periodicPlanePatch() ||
120 ln->periodicPlanePatch()!=next->periodicPlanePatch() ||
121 (prev->periodicPlaneEdge.first!=edge && prev->periodicPlaneEdge.second!=edge) ||
122 (next->periodicPlaneEdge.first!=edge && next->periodicPlaneEdge.second!=edge) ||
123 ln->loop()->loopLinks().size()<=3 || !loops.insert(ln->loop()->sID).second)
128 const auto pair=std::minmax(prev->networkNode->sID,next->networkNode->sID);
129 const std::pair<size_t,size_t>
current(pair.first,pair.second);
131 (!representations.empty() && endpoints!=
current))
136 const VectorDim chord=next->get_P()-prev->get_P();
137 const double length2=chord.squaredNorm();
143 const VectorDim offset=ln->get_P()-prev->get_P();
144 const double t=offset.dot(chord)/length2;
145 const double tolerance=1.e-10*std::max(1.0,std::sqrt(length2));
152 representations.push_back(DN.loopNodes().get(ln->sID));
155 if(!removable || DN.networkLinks().get(endpoints))
161 for(
const auto& ln : representations)
163 DN.removeLoopNode(ln);
176 const auto t0 = std::chrono::system_clock::now();
177 std::cout <<
" Remeshing network: removing... " << std::flush;
179 DN.danglingBoundaryLoopNodes.clear();
181 std::vector<std::shared_ptr<typename DislocationNetwork<dim>::LoopNodeType>> tempLoopNodes;
182 for (
const auto &loopNode : DN.loopNodes())
184 tempLoopNodes.push_back(loopNode.second.lock());
187 std::set<std::tuple<size_t,size_t,size_t>> bndLoopNodes;
192 std::set<const typename DislocationNetwork<dim>::LoopNodeType*> removedLoopNodes;
195 for (
const auto &loopNode : DN.loopNodes())
199 if (removedLoopNodes.find(loopNode.second.lock().get())==removedLoopNodes.end())
204 if (isRemovableLoopNode.first)
207 if (isRemovableLoopNode.second==loopNode.second.lock()->sID)
210 if (!loopNode.second.lock()->periodicPlaneEdge.first)
212 for (
const auto &bndNode : loopNode.second.lock()->boundaryPrev())
215 bndLoopNodes.emplace(bndNode->sID,bndNode->periodicPrev()->sID,bndNode->periodicNext()->sID);
217 for (
const auto &bndNode : loopNode.second.lock()->boundaryNext())
220 bndLoopNodes.emplace(bndNode->sID,bndNode->periodicPrev()->sID,bndNode->periodicNext()->sID);
226 DN.removeLoopNode(loopNode.second.lock()->sID);
229 removedLoopNodes.insert(loopNode.second.lock().get());
237 for (
const auto& loopN : loopNode.second.lock()->networkNode->loopNodes())
239 if (loopN->sID==loopNode.second.lock()->sID || loopN->sID==isRemovableLoopNode.second)
241 if (!loopN->periodicPlaneEdge.first)
243 for (
const auto &bndNode : loopN->boundaryPrev())
245 bndLoopNodes.emplace(bndNode->sID,bndNode->periodicPrev()->sID,bndNode->periodicNext()->sID);
248 for (
const auto &bndNode : loopN->boundaryNext())
250 bndLoopNodes.emplace(bndNode->sID,bndNode->periodicPrev()->sID,bndNode->periodicNext()->sID);
254 DN.removeLoopNode(loopN->sID);
255 removedLoopNodes.insert(loopN);
264 tempLoopNodes.clear();
265 std::cout <<
" (" << Nremoved <<
" LoopNodes removed) " << std::flush;
267 for (
const auto &nodeID : bndLoopNodes)
269 auto nodeIter(DN.loopNodes().find(std::get<0>(nodeID)));
270 if (nodeIter != DN.loopNodes().end())
272 auto bndNode(nodeIter->second.lock());
274 const auto pPrev(bndNode->periodicPrev());
275 const auto pNext(bndNode->periodicNext());
278 if (pPrev->sID == std::get<1>(nodeID) && pNext->sID== std::get<2>(nodeID))
281 const auto pPrevLocal(bndNode->loop()->periodicGlidePlane->referencePlane->localPosition(pPrev->get_P()));
282 const auto pNextLocal(bndNode->loop()->periodicGlidePlane->referencePlane->localPosition(pNext->get_P()));
285 SegmentSegmentDistance<dim - 1> ssd1(pPrevLocal, pNextLocal, *bndNode->periodicPlaneEdge.first->source, *bndNode->periodicPlaneEdge.first->sink);
286 if (ssd1.dMin < FLT_EPSILON)
289 if (bndNode->periodicPlaneEdge.second)
291 SegmentSegmentDistance<dim - 1> ssd2(pPrevLocal, pNextLocal, *bndNode->periodicPlaneEdge.second->source, *bndNode->periodicPlaneEdge.second->sink);
292 const VectorLowerDim ssd1Pos(0.5 * (ssd1.x0 + ssd1.x1));
293 const VectorLowerDim ssd2Pos(0.5 * (ssd2.x0 + ssd2.x1));
294 assert((ssd1Pos - ssd2Pos).norm() < FLT_EPSILON &&
"The two positions must match ");
296 bndNode->set_P(VectorLowerDim(0.5 * (ssd1.x0 + ssd1.x1)));
300 bndNode->set_P(bndNode->loop()->periodicGlidePlane->referencePlane->localPosition(bndNode->get_P()));
301 DN.danglingBoundaryLoopNodes.insert(bndNode.get());
306 bndNode->set_P(bndNode->loop()->periodicGlidePlane->referencePlane->localPosition(bndNode->get_P()));
307 DN.danglingBoundaryLoopNodes.insert(bndNode.get());
315 DN.removeLoopNode(bndNode->sID);
323 std::cout <<
" (" << Nremoved <<
" bndLoopNodes removed). Updating boundary nodes " << std::flush;
325 if (DN.danglingBoundaryLoopNodes.size())
327 DN.updateBoundaryNodes();
330 std::cout <<
magentaColor << std::setprecision(3) << std::scientific <<
" [" << (std::chrono::duration<double>(std::chrono::system_clock::now() -
t0)).
count() <<
" sec]." <<
defaultColor << std::endl;
337 const auto t0 = std::chrono::system_clock::now();
338 std::cout <<
" Remeshing network: expanding... " << std::flush;
339 std::set<std::pair<size_t, size_t>> toBeExpanded;
340 for (
const auto &linkIter : DN.networkLinks())
342 const auto sharedLink(linkIter.second.lock());
344 if (!sharedLink->hasZeroBurgers() && !sharedLink->isSessile() && !sharedLink->isBoundarySegment() && !sharedLink->isGrainBoundarySegment())
346 const VectorDim chord(sharedLink->chord());
347 const double chordLength(chord.norm());
357 if (chordLength >
Lmax)
359 toBeExpanded.insert(std::make_pair(sharedLink->source->sID, sharedLink->sink->sID));
365 unsigned int Nexpanded(0);
366 const double expand_at(0.5);
367 for (
const auto &expIter : toBeExpanded)
371 const auto source(DN.networkNodes().get(expIter.first));
372 const auto sink(DN.networkNodes().get(expIter.second));
374 const auto Lij(DN.networkLinks().get(expIter));
377 VectorDim expandPoint(Lij->get_r(expand_at));
379 if ((expandPoint - source->get_P()).squaredNorm() > FLT_EPSILON && (expandPoint - sink->get_P()).squaredNorm() > FLT_EPSILON)
382 const auto newNetNode(DN.networkNodes().create(expandPoint, 0.5 * (source->get_V() + sink->get_V()),0.5 * (source->climbVelocityScalar + sink->climbVelocityScalar) ,0.5 * (source->velocityReduction() + sink->velocityReduction())));
385 DN.expandNetworkLink(Lij, newNetNode);
390 std::cout <<
" (" << Nexpanded <<
" expanded)" << std::flush;
391 std::cout <<
magentaColor << std::setprecision(3) << std::scientific <<
" [" << (std::chrono::duration<double>(std::chrono::system_clock::now() -
t0)).
count() <<
" sec]." <<
defaultColor << std::endl;
398 std::cout <<
"Contracting BoundaryNodes... " << std::flush;
399 const auto t0 = std::chrono::system_clock::now();
401 typedef std::pair<std::shared_ptr<typename DislocationNetwork<dim>::NetworkNodeType>, std::shared_ptr<typename DislocationNetwork<dim>::NetworkNodeType>> NetNodePairType;
402 typedef std::set<NetNodePairType> BndSetType;
404 std::map<NetNodePairType, BndSetType> bndNodesContractionMap;
406 for (
const auto &netNode : DN.networkNodes())
408 if (netNode.second.lock()->isBoundaryNode())
412 std::set<std::shared_ptr<typename DislocationNetwork<dim>::NetworkNodeType>> internalNodes;
413 for (
const auto &loopNode : netNode.second.lock()->loopNodes())
415 internalNodes.insert(loopNode->periodicPrev()->networkNode);
416 internalNodes.insert(loopNode->periodicNext()->networkNode);
419 if (internalNodes.size() == 2)
424 const NetNodePairType
key((*internalNodes.begin())->sID < (*internalNodes.rbegin())->sID ? std::make_pair(*internalNodes.begin(), *internalNodes.rbegin()) : std::make_pair(*internalNodes.rbegin(), *internalNodes.begin()));
426 if (bndNodesContractionMap.find(
key) == bndNodesContractionMap.end())
428 std::map<std::set<
const Polyhedron<dim,dim-1> *>, std::set<typename DislocationNetwork<dim>::NetworkNodeType *>> bndNodeMap;
430 for (
const auto &loopNode : (*internalNodes.begin())->loopNodes())
432 if (loopNode->periodicPrev()->networkNode == *internalNodes.rbegin())
434 for (
const auto &bndNode : loopNode->boundaryPrev())
437 bndNodeMap[bndNode->networkNode->meshFaces()].insert(bndNode->networkNode.get());
440 else if (loopNode->periodicNext()->networkNode == *internalNodes.rbegin())
442 for (
const auto &bndNode : loopNode->boundaryNext())
445 bndNodeMap[bndNode->networkNode->meshFaces()].insert(bndNode->networkNode.get());
450 for (
const auto &pair : bndNodeMap)
459 if (pair.second.size() > 1)
461 for (
const auto &tempNode : pair.second)
464 if (tempNode != *pair.second.begin())
466 if ((tempNode->get_P() - (*pair.second.begin())->get_P()).norm() < FLT_EPSILON)
468 const NetNodePairType contractPair(tempNode->sID < (*pair.second.begin())->sID ? std::make_pair(tempNode, *pair.second.begin()) : std::make_pair(*pair.second.begin(), tempNode));
470 bndNodesContractionMap[
key].insert(contractPair);
483 for (
const auto &pair : bndNodesContractionMap)
485 std::cout <<
"Contracting bnd nodes of intenal nodes " << pair.first.first->tag() <<
" " << pair.first.second->tag() << std::endl;
486 for (
const auto &bndPair : pair.second)
488 std::cout <<
"Contracting bnd nodes " << bndPair.first->tag() <<
" " << bndPair.second->tag() << std::endl;
489 DN.contract(bndPair.first, bndPair.second);
492 std::cout <<
magentaColor <<
" [" << (std::chrono::duration<double>(std::chrono::system_clock::now() -
t0)).
count() <<
" sec]" <<
defaultColor << std::endl;
556 std::cout<<
" Contracting zero-chord segments... "<<std::flush;
557 const auto t0=std::chrono::system_clock::now();
558 std::set<std::pair<double,std::pair<size_t,size_t>>> ordered;
559 for(
const auto& entry : DN.networkLinks())
561 const auto link=entry.second.lock();
562 if(zeroChordCandidate(link))
564 ordered.emplace((link->sink->get_P()-link->source->get_P()).norm(),link->key);
567 std::vector<std::pair<size_t,size_t>> candidates;
568 for(
const auto& entry : ordered)
570 candidates.push_back(entry.second);
572 const auto contracted=contractZeroChordCandidates(candidates);
573 std::cout<<
"("<<contracted<<
" contracted)"<<
magentaColor<<
" ["
574 <<std::chrono::duration<double>(std::chrono::system_clock::now()-
t0).count()