Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : // TODO:
11 : // Clean up error checking in (!found_edge)
12 : // Save fragment for uncut element ahead of crack tip to avoid renumbering if only embedded node
13 : // Add common code to compare neighbors & fragments (replace multiple set_intersection calls)
14 :
15 : // Handle cases other than 0 or 2 cut edges/elem (include data structure to link cut edges with
16 : // cracks?)
17 : // Allow for more than one cut on an edge
18 : // Support 2d higher order elements
19 : // 3D propagation
20 : // 3D branching
21 :
22 : #include "ElementFragmentAlgorithm.h"
23 :
24 : #include "EFANode.h"
25 : #include "EFAElement3D.h"
26 : #include "EFAElement2D.h"
27 : #include "EFAFuncs.h"
28 : #include "EFAError.h"
29 :
30 452 : ElementFragmentAlgorithm::ElementFragmentAlgorithm(std::ostream & os) : _ostream(os) {}
31 :
32 450 : ElementFragmentAlgorithm::~ElementFragmentAlgorithm()
33 : {
34 : std::map<unsigned int, EFANode *>::iterator mit;
35 83552 : for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
36 : {
37 83102 : delete mit->second;
38 83102 : mit->second = nullptr;
39 : }
40 6798 : for (mit = _embedded_nodes.begin(); mit != _embedded_nodes.end(); ++mit)
41 : {
42 6348 : delete mit->second;
43 6348 : mit->second = nullptr;
44 : }
45 510 : for (mit = _embedded_permanent_nodes.begin(); mit != _embedded_permanent_nodes.end(); ++mit)
46 : {
47 60 : delete mit->second;
48 60 : mit->second = nullptr;
49 : }
50 450 : for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
51 : {
52 0 : delete mit->second;
53 0 : mit->second = nullptr;
54 : }
55 : std::map<unsigned int, EFAElement *>::iterator eit;
56 47070 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
57 : {
58 46620 : delete eit->second;
59 46620 : eit->second = nullptr;
60 : }
61 450 : }
62 :
63 : unsigned int
64 9 : ElementFragmentAlgorithm::add2DElements(std::vector<std::vector<unsigned int>> & quads)
65 : {
66 : unsigned int first_id = 0;
67 9 : unsigned int num_nodes = quads[0].size();
68 :
69 9 : if (quads.size() == 0)
70 0 : EFAError("add2DElements called with empty vector of quads");
71 :
72 41 : for (unsigned int i = 0; i < quads.size(); ++i)
73 : {
74 32 : unsigned int new_elem_id = Efa::getNewID(_elements);
75 32 : EFAElement2D * newElem = new EFAElement2D(new_elem_id, num_nodes);
76 32 : _elements.insert(std::make_pair(new_elem_id, newElem));
77 :
78 32 : if (i == 0)
79 : first_id = new_elem_id;
80 :
81 160 : for (unsigned int j = 0; j < num_nodes; ++j)
82 : {
83 128 : EFANode * currNode = nullptr;
84 128 : std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quads[i][j]);
85 128 : if (mit == _permanent_nodes.end())
86 : {
87 71 : currNode = new EFANode(quads[i][j], EFANode::N_CATEGORY_PERMANENT);
88 71 : _permanent_nodes.insert(std::make_pair(quads[i][j], currNode));
89 : }
90 : else
91 57 : currNode = mit->second;
92 :
93 128 : newElem->setNode(j, currNode);
94 128 : _inverse_connectivity[currNode].insert(newElem);
95 : }
96 32 : newElem->createEdges();
97 : }
98 9 : return first_id;
99 : }
100 :
101 : EFAElement *
102 385302 : ElementFragmentAlgorithm::add2DElement(const std::vector<unsigned int> & quad, unsigned int id)
103 : {
104 385302 : unsigned int num_nodes = quad.size();
105 :
106 : std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
107 385302 : if (mit != _elements.end())
108 0 : EFAError("In add2DElement element with id: ", id, " already exists");
109 :
110 385302 : EFAElement2D * newElem = new EFAElement2D(id, num_nodes);
111 385302 : _elements.insert(std::make_pair(id, newElem));
112 :
113 1995310 : for (unsigned int j = 0; j < num_nodes; ++j)
114 : {
115 1610008 : EFANode * currNode = nullptr;
116 1610008 : std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quad[j]);
117 1610008 : if (mit == _permanent_nodes.end())
118 : {
119 505594 : currNode = new EFANode(quad[j], EFANode::N_CATEGORY_PERMANENT);
120 505594 : _permanent_nodes.insert(std::make_pair(quad[j], currNode));
121 : }
122 : else
123 1104414 : currNode = mit->second;
124 :
125 1610008 : newElem->setNode(j, currNode);
126 1610008 : _inverse_connectivity[currNode].insert(newElem);
127 : }
128 385302 : newElem->createEdges();
129 385302 : return newElem;
130 : }
131 :
132 : EFAElement *
133 40763 : ElementFragmentAlgorithm::add3DElement(const std::vector<unsigned int> & quad, unsigned int id)
134 : {
135 40763 : unsigned int num_nodes = quad.size();
136 : unsigned int num_faces = 0;
137 40763 : if (num_nodes == 8 || num_nodes == 20 || num_nodes == 27)
138 : num_faces = 6;
139 : else if (num_nodes == 4 || num_nodes == 10 || num_nodes == 14)
140 : num_faces = 4;
141 : else
142 0 : EFAError("In add3DElement element with id: ", id, " has invalid num_nodes");
143 :
144 : std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
145 40763 : if (mit != _elements.end())
146 0 : EFAError("In add3DElement element with id: ", id, " already exists");
147 :
148 40763 : EFAElement3D * newElem = new EFAElement3D(id, num_nodes, num_faces);
149 40763 : _elements.insert(std::make_pair(id, newElem));
150 :
151 458007 : for (unsigned int j = 0; j < num_nodes; ++j)
152 : {
153 417244 : EFANode * currNode = nullptr;
154 417244 : std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quad[j]);
155 417244 : if (mit == _permanent_nodes.end())
156 : {
157 111982 : currNode = new EFANode(quad[j], EFANode::N_CATEGORY_PERMANENT);
158 111982 : _permanent_nodes.insert(std::make_pair(quad[j], currNode));
159 : }
160 : else
161 305262 : currNode = mit->second;
162 :
163 417244 : newElem->setNode(j, currNode);
164 417244 : _inverse_connectivity[currNode].insert(newElem);
165 : }
166 40763 : newElem->createFaces();
167 40763 : return newElem;
168 : }
169 :
170 : void
171 3210 : ElementFragmentAlgorithm::updateEdgeNeighbors()
172 : {
173 : std::map<unsigned int, EFAElement *>::iterator eit;
174 429654 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
175 : {
176 426444 : EFAElement * elem = eit->second;
177 426444 : elem->clearNeighbors();
178 : }
179 :
180 429654 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
181 : {
182 426444 : EFAElement * curr_elem = eit->second;
183 426444 : curr_elem->setupNeighbors(_inverse_connectivity);
184 : } // loop over all elements
185 :
186 429654 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
187 : {
188 426444 : EFAElement * curr_elem = eit->second;
189 426444 : curr_elem->neighborSanityCheck();
190 : }
191 3210 : }
192 :
193 : void
194 3179 : ElementFragmentAlgorithm::initCrackTipTopology()
195 : {
196 : _crack_tip_elements.clear(); // re-build CrackTipElements!
197 429398 : for (auto pair : _elements)
198 426219 : pair.second->initCrackTip(_crack_tip_elements); // CrackTipElements changed here
199 3179 : }
200 :
201 : void
202 47183 : ElementFragmentAlgorithm::addElemEdgeIntersection(unsigned int elemid,
203 : unsigned int edgeid,
204 : double position)
205 : {
206 : // this method is called when we are marking cut edges
207 : auto eit = _elements.find(elemid);
208 47183 : if (eit == _elements.end())
209 0 : EFAError("Could not find element with id: ", elemid, " in addEdgeIntersection");
210 :
211 47183 : EFAElement2D * curr_elem = dynamic_cast<EFAElement2D *>(eit->second);
212 47183 : if (!curr_elem)
213 0 : EFAError("addElemEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
214 47183 : curr_elem->addEdgeCut(edgeid, position, nullptr, _embedded_nodes, true);
215 47183 : }
216 :
217 : void
218 346 : ElementFragmentAlgorithm::addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
219 : {
220 : // this method is called when we are marking cut nodes
221 : auto eit = _elements.find(elemid);
222 346 : if (eit == _elements.end())
223 0 : EFAError("Could not find element with id: ", elemid, " in addElemNodeIntersection");
224 :
225 346 : EFAElement2D * curr_elem = dynamic_cast<EFAElement2D *>(eit->second);
226 346 : if (!curr_elem)
227 0 : EFAError("addElemNodeIntersection: elem ", elemid, " is not of type EFAelement2D");
228 :
229 : // Only add cut node when the curr_elem does not have any fragment
230 346 : if (curr_elem->numFragments() == 0)
231 136 : curr_elem->addNodeCut(nodeid, nullptr, _permanent_nodes, _embedded_permanent_nodes);
232 346 : }
233 :
234 : bool
235 35290 : ElementFragmentAlgorithm::addFragEdgeIntersection(unsigned int elemid,
236 : unsigned int frag_edge_id,
237 : double position)
238 : {
239 : // N.B. this method must be called after addEdgeIntersection
240 : auto eit = _elements.find(elemid);
241 35290 : if (eit == _elements.end())
242 0 : EFAError("Could not find element with id: ", elemid, " in addFragEdgeIntersection");
243 :
244 35290 : EFAElement2D * elem = dynamic_cast<EFAElement2D *>(eit->second);
245 35290 : if (!elem)
246 0 : EFAError("addFragEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
247 35290 : return elem->addFragmentEdgeCut(frag_edge_id, position, _embedded_nodes);
248 : }
249 :
250 : void
251 15947 : ElementFragmentAlgorithm::addElemFaceIntersection(unsigned int elemid,
252 : unsigned int faceid,
253 : const std::vector<unsigned int> & edgeid,
254 : const std::vector<double> & position)
255 : {
256 : // this method is called when we are marking cut edges
257 : auto eit = _elements.find(elemid);
258 15947 : if (eit == _elements.end())
259 0 : EFAError("Could not find element with id: ", elemid, " in addEdgeIntersection");
260 :
261 15947 : EFAElement3D * curr_elem = dynamic_cast<EFAElement3D *>(eit->second);
262 15947 : if (!curr_elem)
263 0 : EFAError("addElemEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
264 :
265 : // add cuts to two face edges at the same time
266 15947 : curr_elem->addFaceEdgeCut(faceid, edgeid[0], position[0], nullptr, _embedded_nodes, true, true);
267 15947 : curr_elem->addFaceEdgeCut(faceid, edgeid[1], position[1], nullptr, _embedded_nodes, true, true);
268 15947 : }
269 :
270 : void
271 0 : ElementFragmentAlgorithm::addFragFaceIntersection(
272 : unsigned int /*ElemID*/,
273 : unsigned int /*FragFaceID*/,
274 : const std::vector<unsigned int> & /*FragFaceEdgeID*/,
275 : const std::vector<double> & /*position*/)
276 : {
277 : // TODO: need to finish this for 3D problems
278 0 : }
279 :
280 : void
281 1675 : ElementFragmentAlgorithm::updatePhysicalLinksAndFragments()
282 : {
283 : // loop over the elements in the mesh
284 : std::map<unsigned int, EFAElement *>::iterator eit;
285 255194 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
286 : {
287 253519 : EFAElement * curr_elem = eit->second;
288 253519 : curr_elem->updateFragments(_crack_tip_elements, _embedded_nodes);
289 : } // loop over all elements
290 1675 : }
291 :
292 : void
293 1676 : ElementFragmentAlgorithm::updateTopology(bool mergeUncutVirtualEdges)
294 : {
295 : // If mergeUncutVirtualEdges=true, this algorithm replicates the
296 : // behavior of classical XFEM. If false, it gives the behavior of
297 : // the Richardson et. al. (2011) paper
298 :
299 1676 : _new_nodes.clear();
300 1676 : _child_elements.clear();
301 1676 : _parent_elements.clear();
302 :
303 1676 : unsigned int first_new_node_id = Efa::getNewID(_permanent_nodes);
304 :
305 1676 : createChildElements();
306 1676 : connectFragments(mergeUncutVirtualEdges);
307 1676 : sanityCheck();
308 1676 : updateCrackTipElements();
309 :
310 385628 : for (const auto & [id, node] : _permanent_nodes)
311 383952 : if (id >= first_new_node_id)
312 14771 : _new_nodes.push_back(node);
313 :
314 1676 : clearPotentialIsolatedNodes(); // _new_nodes and _permanent_nodes may change here
315 1676 : }
316 :
317 : void
318 3144 : ElementFragmentAlgorithm::reset()
319 : {
320 3144 : _new_nodes.clear();
321 3144 : _child_elements.clear();
322 3144 : _parent_elements.clear();
323 : _crack_tip_elements.clear();
324 : _inverse_connectivity.clear();
325 :
326 : std::map<unsigned int, EFANode *>::iterator mit;
327 552053 : for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
328 : {
329 548909 : delete mit->second;
330 548909 : mit->second = nullptr;
331 : }
332 : _permanent_nodes.clear();
333 :
334 3144 : for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
335 : {
336 0 : delete mit->second;
337 0 : mit->second = nullptr;
338 : }
339 : _temp_nodes.clear();
340 : std::map<unsigned int, EFAElement *>::iterator eit;
341 394382 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
342 : {
343 391238 : delete eit->second;
344 391238 : eit->second = nullptr;
345 : }
346 : _elements.clear();
347 3144 : }
348 :
349 : void
350 35 : ElementFragmentAlgorithm::clearAncestry()
351 : {
352 : _inverse_connectivity.clear();
353 158 : for (unsigned int i = 0; i < _parent_elements.size(); ++i)
354 : {
355 123 : if (!Efa::deleteFromMap(_elements, _parent_elements[i]))
356 0 : EFAError("Attempted to delete parent element: ",
357 : _parent_elements[i]->id(),
358 : " from _elements, but couldn't find it");
359 : }
360 35 : _parent_elements.clear();
361 :
362 : std::map<unsigned int, EFAElement *>::iterator eit;
363 382 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
364 : {
365 347 : EFAElement * curr_elem = eit->second;
366 347 : curr_elem->clearParentAndChildren();
367 2767 : for (unsigned int j = 0; j < curr_elem->numNodes(); j++)
368 : {
369 2420 : EFANode * curr_node = curr_elem->getNode(j);
370 2420 : _inverse_connectivity[curr_node].insert(curr_elem);
371 : }
372 : }
373 :
374 : std::map<unsigned int, EFANode *>::iterator mit;
375 1129 : for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
376 1094 : mit->second->removeParent();
377 :
378 35 : for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
379 : {
380 0 : delete mit->second;
381 0 : mit->second = nullptr;
382 : }
383 : _temp_nodes.clear();
384 :
385 35 : _new_nodes.clear();
386 35 : _child_elements.clear();
387 :
388 : // TODO: Sanity check to make sure that there are no nodes that are not connected
389 : // to an element -- there shouldn't be any
390 35 : }
391 :
392 : void
393 42275 : ElementFragmentAlgorithm::restoreFragmentInfo(EFAElement * const elem,
394 : const EFAElement * const from_elem)
395 : {
396 42275 : elem->restoreFragment(from_elem);
397 42275 : }
398 :
399 : void
400 1676 : ElementFragmentAlgorithm::createChildElements()
401 : {
402 : // temporary container for new elements -- will be merged with Elements
403 : std::map<unsigned int, EFAElement *> newChildElements;
404 :
405 : // loop over the original elements in the mesh
406 : std::map<unsigned int, EFAElement *>::iterator eit;
407 : std::map<unsigned int, EFAElement *>::iterator ElementsEnd = _elements.end();
408 255198 : for (eit = _elements.begin(); eit != ElementsEnd; ++eit)
409 : {
410 253522 : EFAElement * curr_elem = eit->second;
411 253522 : curr_elem->createChild(_crack_tip_elements,
412 253522 : _elements,
413 : newChildElements,
414 253522 : _child_elements,
415 253522 : _parent_elements,
416 253522 : _temp_nodes);
417 : } // loop over elements
418 : // Merge newChildElements back in with Elements
419 1676 : _elements.insert(newChildElements.begin(), newChildElements.end());
420 1676 : }
421 :
422 : void
423 1676 : ElementFragmentAlgorithm::connectFragments(bool mergeUncutVirtualEdges)
424 : {
425 : // now perform the comparison on the children
426 13760 : for (unsigned int elem_iter = 0; elem_iter < _child_elements.size(); elem_iter++)
427 : {
428 12084 : EFAElement * childElem = _child_elements[elem_iter];
429 12084 : childElem->connectNeighbors(
430 12084 : _permanent_nodes, _temp_nodes, _inverse_connectivity, mergeUncutVirtualEdges);
431 12084 : childElem->updateFragmentNode();
432 : }
433 :
434 : // remove all deleted children
435 1676 : _child_elements.erase(std::remove(_child_elements.begin(), _child_elements.end(), nullptr),
436 : _child_elements.end());
437 1676 : }
438 :
439 : void
440 1676 : ElementFragmentAlgorithm::sanityCheck()
441 : {
442 : // Make sure there are no remaining TempNodes
443 1676 : if (_temp_nodes.size() > 0)
444 : {
445 0 : _ostream << "_temp_nodes size > 0. size=" << _temp_nodes.size() << std::endl;
446 0 : printMesh();
447 0 : throw std::runtime_error("_temp_nodes size > 0");
448 : }
449 1676 : }
450 :
451 : void
452 1676 : ElementFragmentAlgorithm::updateCrackTipElements()
453 : {
454 : std::set<EFAElement *>::iterator sit;
455 : // Delete all elements that were previously flagged as crack tip elements if they have
456 : // been split (and hence appear in ParentElements).
457 8653 : for (unsigned int i = 0; i < _parent_elements.size(); ++i)
458 : {
459 : sit = _crack_tip_elements.find(_parent_elements[i]);
460 6977 : if (sit != _crack_tip_elements.end())
461 413 : _crack_tip_elements.erase(sit);
462 : }
463 :
464 : // Go through new child elements to find elements that are newly at the crack tip due to
465 : // crack growth.
466 13760 : for (unsigned int elem_iter = 0; elem_iter < _child_elements.size(); elem_iter++)
467 : {
468 12084 : EFAElement * childElem = _child_elements[elem_iter];
469 12084 : if (childElem->isCrackTipElement())
470 856 : _crack_tip_elements.insert(childElem);
471 : } // loop over (new) child elements
472 :
473 : //_ostream << "Crack tip elements: ";
474 : // for (sit=CrackTipElements.begin(); sit!=CrackTipElements.end(); ++sit)
475 : //{
476 : // _ostream << (*sit)->id<<" ";
477 : //}
478 : //_ostream << std::endl;
479 1676 : }
480 :
481 : void
482 18 : ElementFragmentAlgorithm::printMesh()
483 : {
484 18 : _ostream << "============================================================"
485 18 : << "==================================================" << std::endl;
486 18 : _ostream << " CutElemMesh Data" << std::endl;
487 18 : _ostream << "============================================================"
488 18 : << "==================================================" << std::endl;
489 18 : _ostream << "Permanent Nodes:" << std::endl;
490 : std::map<unsigned int, EFANode *>::iterator mit;
491 : unsigned int counter = 0;
492 834 : for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
493 : {
494 816 : _ostream << " " << mit->second->id();
495 816 : counter += 1;
496 816 : if (counter % 10 == 0)
497 75 : _ostream << std::endl;
498 : }
499 18 : _ostream << std::endl;
500 18 : _ostream << "Temp Nodes:" << std::endl;
501 : counter = 0;
502 18 : for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
503 : {
504 0 : _ostream << " " << mit->second->id();
505 0 : counter += 1;
506 0 : if (counter % 10 == 0)
507 0 : _ostream << std::endl;
508 : }
509 18 : _ostream << std::endl;
510 18 : _ostream << "Embedded Nodes:" << std::endl;
511 : counter = 0;
512 294 : for (mit = _embedded_nodes.begin(); mit != _embedded_nodes.end(); ++mit)
513 : {
514 276 : _ostream << " " << mit->second->id();
515 276 : counter += 1;
516 276 : if (counter % 10 == 0)
517 18 : _ostream << std::endl;
518 : }
519 18 : _ostream << std::endl;
520 18 : _ostream << "Embedded Permanent Nodes:" << std::endl;
521 : counter = 0;
522 18 : for (mit = _embedded_permanent_nodes.begin(); mit != _embedded_permanent_nodes.end(); ++mit)
523 : {
524 0 : _ostream << " " << mit->second->id();
525 0 : counter += 1;
526 0 : if (counter % 10 == 0)
527 0 : _ostream << std::endl;
528 : }
529 18 : _ostream << std::endl;
530 18 : _ostream << "Parent Elements:" << std::endl;
531 : counter = 0;
532 96 : for (unsigned int i = 0; i < _parent_elements.size(); ++i)
533 : {
534 78 : _ostream << " " << _parent_elements[i]->id();
535 78 : counter += 1;
536 78 : if (counter % 10 == 0)
537 3 : _ostream << std::endl;
538 : }
539 18 : _ostream << std::endl;
540 18 : _ostream << "Child Elements:" << std::endl;
541 : counter = 0;
542 153 : for (unsigned int i = 0; i < _child_elements.size(); ++i)
543 : {
544 135 : _ostream << " " << _child_elements[i]->id();
545 135 : counter += 1;
546 135 : if (counter % 10 == 0)
547 9 : _ostream << std::endl;
548 : }
549 18 : _ostream << std::endl;
550 18 : _ostream << "Elements:" << std::endl;
551 18 : _ostream << " id "
552 : << "| nodes "
553 : << "| embedded nodes "
554 : << "| edge neighbors "
555 : << "| frag "
556 18 : << "| frag link ... " << std::endl;
557 18 : _ostream << "------------------------------------------------------------"
558 18 : << "--------------------------------------------------" << std::endl;
559 : std::map<unsigned int, EFAElement *>::iterator eit;
560 621 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
561 : {
562 603 : EFAElement * currElem = eit->second;
563 603 : currElem->printElement(_ostream);
564 : }
565 18 : }
566 :
567 : EFAElement *
568 286134 : ElementFragmentAlgorithm::getElemByID(unsigned int id)
569 : {
570 : std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
571 286134 : if (mit == _elements.end())
572 0 : EFAError("in getElemByID() could not find element: ", id);
573 286134 : return mit->second;
574 : }
575 :
576 : unsigned int
577 0 : ElementFragmentAlgorithm::getElemIdByNodes(unsigned int * node_id)
578 : {
579 : unsigned int elem_id = std::numeric_limits<unsigned int>::max();
580 : std::map<unsigned int, EFAElement *>::iterator eit;
581 0 : for (eit = _elements.begin(); eit != _elements.end(); ++eit)
582 : {
583 0 : EFAElement * curr_elem = eit->second;
584 : unsigned int counter = 0;
585 0 : for (unsigned int i = 0; i < curr_elem->numNodes(); ++i)
586 : {
587 0 : if (curr_elem->getNode(i)->id() == node_id[i])
588 0 : counter += 1;
589 : }
590 0 : if (counter == curr_elem->numNodes())
591 : {
592 0 : elem_id = curr_elem->id();
593 : break;
594 : }
595 : }
596 0 : return elem_id;
597 : }
598 :
599 : void
600 1676 : ElementFragmentAlgorithm::clearPotentialIsolatedNodes()
601 : {
602 : // compile a set of all child element nodes
603 : std::set<EFANode *> child_nodes;
604 13760 : for (const auto & child_element : _child_elements)
605 : {
606 12084 : const auto & nodes = child_element->getNodes();
607 12084 : child_nodes.insert(nodes.begin(), nodes.end());
608 : }
609 :
610 : // Collect all parent nodes that will be isolated
611 : std::map<EFANode *, EFANode *> isolate_parent_to_child;
612 16447 : for (unsigned int i = 0; i < _new_nodes.size(); ++i)
613 : {
614 14771 : EFANode * parent_node = _new_nodes[i]->parent();
615 14771 : if (!parent_node)
616 0 : EFAError("a new permanent node must have a parent node!");
617 :
618 : auto it = isolate_parent_to_child.lower_bound(parent_node);
619 14771 : if (it != isolate_parent_to_child.end() && it->first == parent_node)
620 112 : continue;
621 :
622 : if (child_nodes.count(parent_node) == 0)
623 116 : isolate_parent_to_child.emplace_hint(it, parent_node, _new_nodes[i]);
624 : }
625 :
626 : // For each isolated parent node, pick one of its child new node
627 : // Then, switch that child with its parent for all new elems
628 1792 : for (const auto [parent_node, child_node] : isolate_parent_to_child)
629 : {
630 2468 : for (unsigned int i = 0; i < _child_elements.size(); ++i)
631 2352 : if (_child_elements[i]->containsNode(child_node))
632 116 : _child_elements[i]->switchNode(parent_node, child_node, true);
633 :
634 116 : _new_nodes.erase(std::remove(_new_nodes.begin(), _new_nodes.end(), child_node),
635 : _new_nodes.end());
636 116 : Efa::deleteFromMap(_permanent_nodes, child_node);
637 : }
638 1676 : }
|