www.mooseframework.org
ElementFragmentAlgorithm.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
30 ElementFragmentAlgorithm::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 
63 unsigned int
64 ElementFragmentAlgorithm::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 
101 EFAElement *
102 ElementFragmentAlgorithm::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 
132 EFAElement *
133 ElementFragmentAlgorithm::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 
170 void
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 
193 void
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 
201 void
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 
217 void
218 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  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 
234 bool
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 
250 void
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 
270 void
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 
280 void
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 
292 void
293 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  _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 
317 void
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 
349 void
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 
392 void
394  const EFAElement * const from_elem)
395 {
396  elem->restoreFragment(from_elem);
397 }
398 
399 void
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;
411  curr_elem->createChild(_crack_tip_elements,
412  _elements,
413  newChildElements,
416  _temp_nodes);
417  } // loop over elements
418  // Merge newChildElements back in with Elements
419  _elements.insert(newChildElements.begin(), newChildElements.end());
420 }
421 
422 void
423 ElementFragmentAlgorithm::connectFragments(bool mergeUncutVirtualEdges)
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 
439 void
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 
451 void
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  {
459  sit = _crack_tip_elements.find(_parent_elements[i]);
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 
481 void
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 
567 EFAElement *
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 
576 unsigned 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 
599 void
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 clearParentAndChildren()
Definition: EFAElement.C:201
void addEdgeCut(unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode *> &EmbeddedNodes, bool add_to_neighbor)
void addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
virtual void printElement(std::ostream &ostream) const =0
bool addFragmentEdgeCut(unsigned int frag_edge_id, double position, std::map< unsigned int, EFANode *> &EmbeddedNodes)
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
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
unsigned int id() const
Definition: EFAElement.C:28
ElementFragmentAlgorithm(std::ostream &os)
Constructor.
void createFaces()
EFAElement * add3DElement(const std::vector< unsigned int > &quad, unsigned int id)
void connectFragments(bool mergeUncutVirtualEdges)
virtual bool isCrackTipElement() const =0
bool deleteFromMap(std::map< unsigned int, T *> &theMap, T *elemToDelete, bool delete_elem=true)
Definition: EFAFuncs.h:22
std::basic_ostream< charT, traits > * os
std::vector< EFAElement * > _child_elements
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
std::vector< EFAElement * > _parent_elements
void updateTopology(bool mergeUncutVirtualEdges=true)
std::map< unsigned int, EFAElement * > _elements
unsigned int add2DElements(std::vector< std::vector< unsigned int >> &quads)
virtual void neighborSanityCheck() const =0
virtual void updateFragmentNode()=0
void addElemFaceIntersection(unsigned int elemid, unsigned int faceid, const std::vector< unsigned int > &edgeid, const std::vector< double > &position)
virtual void setupNeighbors(std::map< EFANode *, std::set< EFAElement *>> &InverseConnectivityMap)=0
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
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
std::map< unsigned int, EFANode * > _embedded_permanent_nodes
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
virtual void restoreFragment(const EFAElement *const from_elem)=0
std::set< EFAElement * > _crack_tip_elements
virtual void clearNeighbors()=0
void addFragFaceIntersection(unsigned int ElemID, unsigned int FragFaceID, const std::vector< unsigned int > &FragFaceEdgeID, const std::vector< double > &position)
std::vector< EFANode * > _new_nodes
void restoreFragmentInfo(EFAElement *const elem, const EFAElement *const from_elem)
unsigned int getElemIdByNodes(unsigned int *node_id)
std::map< EFANode *, std::set< EFAElement * > > _inverse_connectivity
EFAElement * add2DElement(const std::vector< unsigned int > &quad, unsigned int id)
std::map< unsigned int, EFANode * > _temp_nodes
void addNodeCut(unsigned int node_id, EFANode *embedded_permanent_node, std::map< unsigned int, EFANode *> &PermanentNodes, std::map< unsigned int, EFANode *> &EmbeddedPermanentNodes)
EFAElement * getElemByID(unsigned int id)
virtual void updateFragments(const std::set< EFAElement *> &CrackTipElements, std::map< unsigned int, EFANode *> &EmbeddedNodes)=0
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int numNodes() const
Definition: EFAElement.C:34
std::map< unsigned int, EFANode * > _embedded_nodes
std::map< unsigned int, EFANode * > _permanent_nodes
unsigned int id() const
Definition: EFANode.C:36
void setNode(unsigned int node_id, EFANode *node)
Definition: EFAElement.C:40
void createEdges()
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)