https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ElementFragmentAlgorithm.C
Go to the documentation of this file.
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
23
24#include "EFANode.h"
25#include "EFAElement3D.h"
26#include "EFAElement2D.h"
27#include "EFAFuncs.h"
28#include "EFAError.h"
29
30ElementFragmentAlgorithm::ElementFragmentAlgorithm(std::ostream & os) : _ostream(os) {}
31
33{
34 std::map<unsigned int, EFANode *>::iterator mit;
35 for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
36 {
37 delete mit->second;
38 mit->second = nullptr;
39 }
40 for (mit = _embedded_nodes.begin(); mit != _embedded_nodes.end(); ++mit)
41 {
42 delete mit->second;
43 mit->second = nullptr;
44 }
45 for (mit = _embedded_permanent_nodes.begin(); mit != _embedded_permanent_nodes.end(); ++mit)
46 {
47 delete mit->second;
48 mit->second = nullptr;
49 }
50 for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
51 {
52 delete mit->second;
53 mit->second = nullptr;
54 }
55 std::map<unsigned int, EFAElement *>::iterator eit;
56 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
57 {
58 delete eit->second;
59 eit->second = nullptr;
60 }
61}
62
63unsigned int
64ElementFragmentAlgorithm::add2DElements(std::vector<std::vector<unsigned int>> & quads)
65{
66 unsigned int first_id = 0;
67 unsigned int num_nodes = quads[0].size();
68
69 if (quads.size() == 0)
70 EFAError("add2DElements called with empty vector of quads");
71
72 for (unsigned int i = 0; i < quads.size(); ++i)
73 {
74 unsigned int new_elem_id = Efa::getNewID(_elements);
75 EFAElement2D * newElem = new EFAElement2D(new_elem_id, num_nodes);
76 _elements.insert(std::make_pair(new_elem_id, newElem));
77
78 if (i == 0)
79 first_id = new_elem_id;
80
81 for (unsigned int j = 0; j < num_nodes; ++j)
82 {
83 EFANode * currNode = nullptr;
84 std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quads[i][j]);
85 if (mit == _permanent_nodes.end())
86 {
87 currNode = new EFANode(quads[i][j], EFANode::N_CATEGORY_PERMANENT);
88 _permanent_nodes.insert(std::make_pair(quads[i][j], currNode));
89 }
90 else
91 currNode = mit->second;
92
93 newElem->setNode(j, currNode);
94 _inverse_connectivity[currNode].insert(newElem);
95 }
96 newElem->createEdges();
97 }
98 return first_id;
99}
100
102ElementFragmentAlgorithm::add2DElement(const std::vector<unsigned int> & quad, unsigned int id)
103{
104 unsigned int num_nodes = quad.size();
105
106 std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
107 if (mit != _elements.end())
108 EFAError("In add2DElement element with id: ", id, " already exists");
109
110 EFAElement2D * newElem = new EFAElement2D(id, num_nodes);
111 _elements.insert(std::make_pair(id, newElem));
112
113 for (unsigned int j = 0; j < num_nodes; ++j)
114 {
115 EFANode * currNode = nullptr;
116 std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quad[j]);
117 if (mit == _permanent_nodes.end())
118 {
119 currNode = new EFANode(quad[j], EFANode::N_CATEGORY_PERMANENT);
120 _permanent_nodes.insert(std::make_pair(quad[j], currNode));
121 }
122 else
123 currNode = mit->second;
124
125 newElem->setNode(j, currNode);
126 _inverse_connectivity[currNode].insert(newElem);
127 }
128 newElem->createEdges();
129 return newElem;
130}
131
133ElementFragmentAlgorithm::add3DElement(const std::vector<unsigned int> & quad, unsigned int id)
134{
135 unsigned int num_nodes = quad.size();
136 unsigned int num_faces = 0;
137 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 EFAError("In add3DElement element with id: ", id, " has invalid num_nodes");
143
144 std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
145 if (mit != _elements.end())
146 EFAError("In add3DElement element with id: ", id, " already exists");
147
148 EFAElement3D * newElem = new EFAElement3D(id, num_nodes, num_faces);
149 _elements.insert(std::make_pair(id, newElem));
150
151 for (unsigned int j = 0; j < num_nodes; ++j)
152 {
153 EFANode * currNode = nullptr;
154 std::map<unsigned int, EFANode *>::iterator mit = _permanent_nodes.find(quad[j]);
155 if (mit == _permanent_nodes.end())
156 {
157 currNode = new EFANode(quad[j], EFANode::N_CATEGORY_PERMANENT);
158 _permanent_nodes.insert(std::make_pair(quad[j], currNode));
159 }
160 else
161 currNode = mit->second;
162
163 newElem->setNode(j, currNode);
164 _inverse_connectivity[currNode].insert(newElem);
165 }
166 newElem->createFaces();
167 return newElem;
168}
169
170void
172{
173 std::map<unsigned int, EFAElement *>::iterator eit;
174 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
175 {
176 EFAElement * elem = eit->second;
177 elem->clearNeighbors();
178 }
179
180 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
181 {
182 EFAElement * curr_elem = eit->second;
184 } // loop over all elements
185
186 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
187 {
188 EFAElement * curr_elem = eit->second;
189 curr_elem->neighborSanityCheck();
190 }
191}
192
193void
195{
196 _crack_tip_elements.clear(); // re-build CrackTipElements!
197 for (auto pair : _elements)
198 pair.second->initCrackTip(_crack_tip_elements); // CrackTipElements changed here
199}
200
201void
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 if (eit == _elements.end())
209 EFAError("Could not find element with id: ", elemid, " in addEdgeIntersection");
210
211 EFAElement2D * curr_elem = dynamic_cast<EFAElement2D *>(eit->second);
212 if (!curr_elem)
213 EFAError("addElemEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
214 curr_elem->addEdgeCut(edgeid, position, nullptr, _embedded_nodes, true);
215}
216
217void
218ElementFragmentAlgorithm::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 if (eit == _elements.end())
223 EFAError("Could not find element with id: ", elemid, " in addElemNodeIntersection");
224
225 EFAElement2D * curr_elem = dynamic_cast<EFAElement2D *>(eit->second);
226 if (!curr_elem)
227 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 if (curr_elem->numFragments() == 0)
231 curr_elem->addNodeCut(nodeid, nullptr, _permanent_nodes, _embedded_permanent_nodes);
232}
233
234bool
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 if (eit == _elements.end())
242 EFAError("Could not find element with id: ", elemid, " in addFragEdgeIntersection");
243
244 EFAElement2D * elem = dynamic_cast<EFAElement2D *>(eit->second);
245 if (!elem)
246 EFAError("addFragEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
247 return elem->addFragmentEdgeCut(frag_edge_id, position, _embedded_nodes);
248}
249
250void
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 if (eit == _elements.end())
259 EFAError("Could not find element with id: ", elemid, " in addEdgeIntersection");
260
261 EFAElement3D * curr_elem = dynamic_cast<EFAElement3D *>(eit->second);
262 if (!curr_elem)
263 EFAError("addElemEdgeIntersection: elem ", elemid, " is not of type EFAelement2D");
264
265 // add cuts to two face edges at the same time
266 curr_elem->addFaceEdgeCut(faceid, edgeid[0], position[0], nullptr, _embedded_nodes, true, true);
267 curr_elem->addFaceEdgeCut(faceid, edgeid[1], position[1], nullptr, _embedded_nodes, true, true);
268}
269
270void
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}
279
280void
282{
283 // loop over the elements in the mesh
284 std::map<unsigned int, EFAElement *>::iterator eit;
285 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
286 {
287 EFAElement * curr_elem = eit->second;
289 } // loop over all elements
290}
291
292void
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 _new_nodes.clear();
300 _child_elements.clear();
301 _parent_elements.clear();
302
303 unsigned int first_new_node_id = Efa::getNewID(_permanent_nodes);
304
306 connectFragments(mergeUncutVirtualEdges);
307 sanityCheck();
309
310 for (const auto & [id, node] : _permanent_nodes)
311 if (id >= first_new_node_id)
312 _new_nodes.push_back(node);
313
314 clearPotentialIsolatedNodes(); // _new_nodes and _permanent_nodes may change here
315}
316
317void
319{
320 _new_nodes.clear();
321 _child_elements.clear();
322 _parent_elements.clear();
323 _crack_tip_elements.clear();
324 _inverse_connectivity.clear();
325
326 std::map<unsigned int, EFANode *>::iterator mit;
327 for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
328 {
329 delete mit->second;
330 mit->second = nullptr;
331 }
332 _permanent_nodes.clear();
333
334 for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
335 {
336 delete mit->second;
337 mit->second = nullptr;
338 }
339 _temp_nodes.clear();
340 std::map<unsigned int, EFAElement *>::iterator eit;
341 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
342 {
343 delete eit->second;
344 eit->second = nullptr;
345 }
346 _elements.clear();
347}
348
349void
351{
352 _inverse_connectivity.clear();
353 for (unsigned int i = 0; i < _parent_elements.size(); ++i)
354 {
356 EFAError("Attempted to delete parent element: ",
357 _parent_elements[i]->id(),
358 " from _elements, but couldn't find it");
359 }
360 _parent_elements.clear();
361
362 std::map<unsigned int, EFAElement *>::iterator eit;
363 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
364 {
365 EFAElement * curr_elem = eit->second;
366 curr_elem->clearParentAndChildren();
367 for (unsigned int j = 0; j < curr_elem->numNodes(); j++)
368 {
369 EFANode * curr_node = curr_elem->getNode(j);
370 _inverse_connectivity[curr_node].insert(curr_elem);
371 }
372 }
373
374 std::map<unsigned int, EFANode *>::iterator mit;
375 for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
376 mit->second->removeParent();
377
378 for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
379 {
380 delete mit->second;
381 mit->second = nullptr;
382 }
383 _temp_nodes.clear();
384
385 _new_nodes.clear();
386 _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}
391
392void
394 const EFAElement * const from_elem)
395{
396 elem->restoreFragment(from_elem);
397}
398
399void
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 for (eit = _elements.begin(); eit != ElementsEnd; ++eit)
409 {
410 EFAElement * curr_elem = eit->second;
412 _elements,
413 newChildElements,
417 } // loop over elements
418 // Merge newChildElements back in with Elements
419 _elements.insert(newChildElements.begin(), newChildElements.end());
420}
421
422void
424{
425 // now perform the comparison on the children
426 for (unsigned int elem_iter = 0; elem_iter < _child_elements.size(); elem_iter++)
427 {
428 EFAElement * childElem = _child_elements[elem_iter];
429 childElem->connectNeighbors(
430 _permanent_nodes, _temp_nodes, _inverse_connectivity, mergeUncutVirtualEdges);
431 childElem->updateFragmentNode();
432 }
433
434 // remove all deleted children
435 _child_elements.erase(std::remove(_child_elements.begin(), _child_elements.end(), nullptr),
436 _child_elements.end());
437}
438
439void
441{
442 // Make sure there are no remaining TempNodes
443 if (_temp_nodes.size() > 0)
444 {
445 _ostream << "_temp_nodes size > 0. size=" << _temp_nodes.size() << std::endl;
446 printMesh();
447 throw std::runtime_error("_temp_nodes size > 0");
448 }
449}
450
451void
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 for (unsigned int i = 0; i < _parent_elements.size(); ++i)
458 {
460 if (sit != _crack_tip_elements.end())
461 _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 for (unsigned int elem_iter = 0; elem_iter < _child_elements.size(); elem_iter++)
467 {
468 EFAElement * childElem = _child_elements[elem_iter];
469 if (childElem->isCrackTipElement())
470 _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}
480
481void
483{
484 _ostream << "============================================================"
485 << "==================================================" << std::endl;
486 _ostream << " CutElemMesh Data" << std::endl;
487 _ostream << "============================================================"
488 << "==================================================" << std::endl;
489 _ostream << "Permanent Nodes:" << std::endl;
490 std::map<unsigned int, EFANode *>::iterator mit;
491 unsigned int counter = 0;
492 for (mit = _permanent_nodes.begin(); mit != _permanent_nodes.end(); ++mit)
493 {
494 _ostream << " " << mit->second->id();
495 counter += 1;
496 if (counter % 10 == 0)
497 _ostream << std::endl;
498 }
499 _ostream << std::endl;
500 _ostream << "Temp Nodes:" << std::endl;
501 counter = 0;
502 for (mit = _temp_nodes.begin(); mit != _temp_nodes.end(); ++mit)
503 {
504 _ostream << " " << mit->second->id();
505 counter += 1;
506 if (counter % 10 == 0)
507 _ostream << std::endl;
508 }
509 _ostream << std::endl;
510 _ostream << "Embedded Nodes:" << std::endl;
511 counter = 0;
512 for (mit = _embedded_nodes.begin(); mit != _embedded_nodes.end(); ++mit)
513 {
514 _ostream << " " << mit->second->id();
515 counter += 1;
516 if (counter % 10 == 0)
517 _ostream << std::endl;
518 }
519 _ostream << std::endl;
520 _ostream << "Embedded Permanent Nodes:" << std::endl;
521 counter = 0;
522 for (mit = _embedded_permanent_nodes.begin(); mit != _embedded_permanent_nodes.end(); ++mit)
523 {
524 _ostream << " " << mit->second->id();
525 counter += 1;
526 if (counter % 10 == 0)
527 _ostream << std::endl;
528 }
529 _ostream << std::endl;
530 _ostream << "Parent Elements:" << std::endl;
531 counter = 0;
532 for (unsigned int i = 0; i < _parent_elements.size(); ++i)
533 {
534 _ostream << " " << _parent_elements[i]->id();
535 counter += 1;
536 if (counter % 10 == 0)
537 _ostream << std::endl;
538 }
539 _ostream << std::endl;
540 _ostream << "Child Elements:" << std::endl;
541 counter = 0;
542 for (unsigned int i = 0; i < _child_elements.size(); ++i)
543 {
544 _ostream << " " << _child_elements[i]->id();
545 counter += 1;
546 if (counter % 10 == 0)
547 _ostream << std::endl;
548 }
549 _ostream << std::endl;
550 _ostream << "Elements:" << std::endl;
551 _ostream << " id "
552 << "| nodes "
553 << "| embedded nodes "
554 << "| edge neighbors "
555 << "| frag "
556 << "| frag link ... " << std::endl;
557 _ostream << "------------------------------------------------------------"
558 << "--------------------------------------------------" << std::endl;
559 std::map<unsigned int, EFAElement *>::iterator eit;
560 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
561 {
562 EFAElement * currElem = eit->second;
563 currElem->printElement(_ostream);
564 }
565}
566
569{
570 std::map<unsigned int, EFAElement *>::iterator mit = _elements.find(id);
571 if (mit == _elements.end())
572 EFAError("in getElemByID() could not find element: ", id);
573 return mit->second;
574}
575
576unsigned int
578{
579 unsigned int elem_id = std::numeric_limits<unsigned int>::max();
580 std::map<unsigned int, EFAElement *>::iterator eit;
581 for (eit = _elements.begin(); eit != _elements.end(); ++eit)
582 {
583 EFAElement * curr_elem = eit->second;
584 unsigned int counter = 0;
585 for (unsigned int i = 0; i < curr_elem->numNodes(); ++i)
586 {
587 if (curr_elem->getNode(i)->id() == node_id[i])
588 counter += 1;
589 }
590 if (counter == curr_elem->numNodes())
591 {
592 elem_id = curr_elem->id();
593 break;
594 }
595 }
596 return elem_id;
597}
598
599void
601{
602 // compile a set of all child element nodes
603 std::set<EFANode *> child_nodes;
604 for (const auto & child_element : _child_elements)
605 {
606 const auto & nodes = child_element->getNodes();
607 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 for (unsigned int i = 0; i < _new_nodes.size(); ++i)
613 {
614 EFANode * parent_node = _new_nodes[i]->parent();
615 if (!parent_node)
616 EFAError("a new permanent node must have a parent node!");
617
618 auto it = isolate_parent_to_child.lower_bound(parent_node);
619 if (it != isolate_parent_to_child.end() && it->first == parent_node)
620 continue;
621
622 if (child_nodes.count(parent_node) == 0)
623 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 for (const auto [parent_node, child_node] : isolate_parent_to_child)
629 {
630 for (unsigned int i = 0; i < _child_elements.size(); ++i)
631 if (_child_elements[i]->containsNode(child_node))
632 _child_elements[i]->switchNode(parent_node, child_node, true);
633
634 _new_nodes.erase(std::remove(_new_nodes.begin(), _new_nodes.end(), child_node),
635 _new_nodes.end());
637 }
638}
void addNodeCut(unsigned int node_id, EFANode *embedded_permanent_node, std::map< unsigned int, EFANode * > &PermanentNodes, std::map< unsigned int, EFANode * > &EmbeddedPermanentNodes)
virtual unsigned int numFragments() const
void addEdgeCut(unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode * > &EmbeddedNodes, bool add_to_neighbor)
bool addFragmentEdgeCut(unsigned int frag_edge_id, double position, std::map< unsigned int, EFANode * > &EmbeddedNodes)
void addFaceEdgeCut(unsigned int face_id, unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode * > &EmbeddedNodes, bool add_to_neighbor, bool add_to_adjacent)
virtual void createChild(const std::set< EFAElement * > &CrackTipElements, std::map< unsigned int, EFAElement * > &Elements, std::map< unsigned int, EFAElement * > &newChildElements, std::vector< EFAElement * > &ChildElements, std::vector< EFAElement * > &ParentElements, std::map< unsigned int, EFANode * > &TempNodes)=0
void clearParentAndChildren()
Definition EFAElement.C:201
unsigned int numNodes() const
Definition EFAElement.C:34
EFANode * getNode(unsigned int node_id) const
Definition EFAElement.C:46
virtual void restoreFragment(const EFAElement *const from_elem)=0
virtual void connectNeighbors(std::map< unsigned int, EFANode * > &PermanentNodes, std::map< unsigned int, EFANode * > &TempNodes, std::map< EFANode *, std::set< EFAElement * > > &InverseConnectivityMap, bool merge_phantom_edges)=0
virtual void updateFragmentNode()=0
virtual void setupNeighbors(std::map< EFANode *, std::set< EFAElement * > > &InverseConnectivityMap)=0
void setNode(unsigned int node_id, EFANode *node)
Definition EFAElement.C:40
virtual void clearNeighbors()=0
virtual void updateFragments(const std::set< EFAElement * > &CrackTipElements, std::map< unsigned int, EFANode * > &EmbeddedNodes)=0
virtual bool isCrackTipElement() const =0
unsigned int id() const
Definition EFAElement.C:28
virtual void neighborSanityCheck() const =0
virtual void printElement(std::ostream &ostream) const =0
EFANode * parent() const
Definition EFANode.C:48
@ N_CATEGORY_PERMANENT
Definition EFANode.h:19
unsigned int id() const
Definition EFANode.C:36
void removeParent()
Definition EFANode.C:54
std::map< unsigned int, EFAElement * > _elements
void addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
ElementFragmentAlgorithm(std::ostream &os)
Constructor.
EFAElement * add3DElement(const std::vector< unsigned int > &quad, unsigned int id)
EFAElement * getElemByID(unsigned int id)
std::vector< EFAElement * > _child_elements
std::vector< EFANode * > _new_nodes
void addFragFaceIntersection(unsigned int ElemID, unsigned int FragFaceID, const std::vector< unsigned int > &FragFaceEdgeID, const std::vector< double > &position)
unsigned int getElemIdByNodes(unsigned int *node_id)
std::map< unsigned int, EFANode * > _embedded_permanent_nodes
std::set< EFAElement * > _crack_tip_elements
std::map< unsigned int, EFANode * > _embedded_nodes
void addElemFaceIntersection(unsigned int elemid, unsigned int faceid, const std::vector< unsigned int > &edgeid, const std::vector< double > &position)
std::map< unsigned int, EFANode * > _permanent_nodes
unsigned int add2DElements(std::vector< std::vector< unsigned int > > &quads)
void restoreFragmentInfo(EFAElement *const elem, const EFAElement *const from_elem)
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
std::map< unsigned int, EFANode * > _temp_nodes
std::map< EFANode *, std::set< EFAElement * > > _inverse_connectivity
EFAElement * add2DElement(const std::vector< unsigned int > &quad, unsigned int id)
void connectFragments(bool mergeUncutVirtualEdges)
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
void updateTopology(bool mergeUncutVirtualEdges=true)
std::vector< EFAElement * > _parent_elements
bool deleteFromMap(std::map< unsigned int, T * > &theMap, T *elemToDelete, bool delete_elem=true)
Definition EFAFuncs.h:22
unsigned int getNewID(std::map< unsigned int, T * > &theMap)
Definition EFAFuncs.h:38