www.mooseframework.org
Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
EFAElement2D Class Reference

#include <EFAElement2D.h>

Inheritance diagram for EFAElement2D:
[legend]

Public Member Functions

 EFAElement2D (unsigned int eid, unsigned int n_nodes)
 
 EFAElement2D (const EFAElement2D *from_elem, bool convert_to_local)
 
 EFAElement2D (const EFAFace *from_face)
 
 ~EFAElement2D ()
 
virtual unsigned int numFragments () const
 
virtual bool isPartial () const
 
virtual void getNonPhysicalNodes (std::set< EFANode *> &non_physical_nodes) const
 
virtual void switchNode (EFANode *new_node, EFANode *old_node, bool descend_to_parent)
 
virtual void switchEmbeddedNode (EFANode *new_node, EFANode *old_node)
 
virtual void updateFragmentNode ()
 
virtual void getMasterInfo (EFANode *node, std::vector< EFANode *> &master_nodes, std::vector< double > &master_weights) const
 
virtual unsigned int numInteriorNodes () const
 
bool overlaysElement (const EFAElement2D *other_elem) const
 
virtual unsigned int getNeighborIndex (const EFAElement *neighbor_elem) const
 
virtual void clearNeighbors ()
 
virtual void setupNeighbors (std::map< EFANode *, std::set< EFAElement *>> &InverseConnectivityMap)
 
virtual void neighborSanityCheck () const
 
virtual void initCrackTip (std::set< EFAElement *> &CrackTipElements)
 
virtual bool shouldDuplicateForCrackTip (const std::set< EFAElement *> &CrackTipElements)
 
virtual bool shouldDuplicateCrackTipSplitElement (const std::set< EFAElement *> &CrackTipElements)
 
virtual bool shouldDuplicateForPhantomCorner ()
 
virtual bool willCrackTipExtend (std::vector< unsigned int > &split_neighbors) const
 
virtual bool isCrackTipElement () const
 
virtual unsigned int getNumCuts () const
 
virtual bool isFinalCut () const
 
virtual void updateFragments (const std::set< EFAElement *> &CrackTipElements, std::map< unsigned int, EFANode *> &EmbeddedNodes)
 
virtual void fragmentSanityCheck (unsigned int n_old_frag_edges, unsigned int n_old_frag_cuts) const
 
virtual void restoreFragment (const EFAElement *const from_elem)
 
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)
 
virtual void removePhantomEmbeddedNode ()
 
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)
 
virtual void printElement (std::ostream &ostream) const
 
EFAFragment2DgetFragment (unsigned int frag_id) const
 
std::set< EFANode * > getEdgeNodes (unsigned int edge_id) const
 
bool getEdgeNodeParametricCoordinate (EFANode *node, std::vector< double > &para_coor) const
 
EFAFaceNodegetInteriorNode (unsigned int interior_node_id) const
 
void deleteInteriorNodes ()
 
unsigned int numEdges () const
 
void setEdge (unsigned int edge_id, EFAEdge *edge)
 
void createEdges ()
 
EFAEdgegetEdge (unsigned int edge_id) const
 
EFAEdgegetFragmentEdge (unsigned int frag_id, unsigned int edge_id) const
 
std::set< EFANode * > getPhantomNodeOnEdge (unsigned int edge_id) const
 
bool getFragmentEdgeID (unsigned int elem_edge_id, unsigned int &frag_edge_id) const
 
bool isEdgePhantom (unsigned int edge_id) const
 
unsigned int numEdgeNeighbors (unsigned int edge_id) const
 
EFAElement2DgetEdgeNeighbor (unsigned int edge_id, unsigned int neighbor_id) const
 
unsigned int getCrackTipSplitElementID () const
 
bool fragmentHasTipEdges () const
 
unsigned int getTipEdgeID () const
 
EFANodegetTipEmbeddedNode () const
 
bool edgeContainsTip (unsigned int edge_id) const
 
bool fragmentEdgeAlreadyCut (unsigned int ElemEdgeID) const
 
void addEdgeCut (unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode *> &EmbeddedNodes, bool add_to_neighbor)
 
void addNodeCut (unsigned int node_id, EFANode *embedded_permanent_node, std::map< unsigned int, EFANode *> &PermanentNodes, std::map< unsigned int, EFANode *> &EmbeddedPermanentNodes)
 
bool addFragmentEdgeCut (unsigned int frag_edge_id, double position, std::map< unsigned int, EFANode *> &EmbeddedNodes)
 
std::vector< EFAFragment2D * > branchingSplit (std::map< unsigned int, EFANode *> &EmbeddedNodes)
 
std::vector< EFANode * > getCommonNodes (const EFAElement2D *other_elem) const
 
unsigned int id () const
 
unsigned int numNodes () const
 
void setNode (unsigned int node_id, EFANode *node)
 
EFANodegetNode (unsigned int node_id) const
 
const std::vector< EFANode * > & getNodes () const
 
bool containsNode (EFANode *node) const
 
void printNodes (std::ostream &ostream) const
 
EFANodecreateLocalNodeFromGlobalNode (const EFANode *global_node) const
 
EFANodegetGlobalNodeFromLocalNode (const EFANode *local_node) const
 
unsigned int getLocalNodeIndex (EFANode *node) const
 
void setCrackTipSplit ()
 
bool isCrackTipSplit () const
 
unsigned int numCrackTipNeighbors () const
 
unsigned int getCrackTipNeighbor (unsigned int index) const
 
void addCrackTipNeighbor (EFAElement *neighbor_elem)
 
EFAElementgetParent () const
 
EFAElementgetChild (unsigned int child_id) const
 
void setParent (EFAElement *parent)
 
unsigned int numChildren () const
 
void addChild (EFAElement *child)
 
void clearParentAndChildren ()
 
void findGeneralNeighbors (const std::map< EFANode *, std::set< EFAElement *>> &InverseConnectivity)
 
EFAElementgetGeneralNeighbor (unsigned int index) const
 
unsigned int numGeneralNeighbors () const
 

Protected Member Functions

void mergeNodes (EFANode *&childNode, EFANode *&childOfNeighborNode, EFAElement *childOfNeighborElem, std::map< unsigned int, EFANode *> &PermanentNodes, std::map< unsigned int, EFANode *> &TempNodes)
 

Protected Attributes

unsigned int _id
 
unsigned int _num_nodes
 
std::vector< EFANode * > _nodes
 
std::vector< EFANode * > _local_nodes
 
EFAElement_parent
 
std::vector< EFAElement * > _children
 
bool _crack_tip_split_element
 
std::vector< unsigned int_crack_tip_neighbors
 
std::vector< EFAElement * > _general_neighbors
 

Private Member Functions

void mapParametricCoordFrom1Dto2D (unsigned int edge_id, double xi_1d, std::vector< double > &para_coor) const
 
void setLocalCoordinates ()
 

Private Attributes

unsigned int _num_edges
 
std::vector< EFAEdge * > _edges
 
std::vector< EFAFaceNode * > _interior_nodes
 
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
 
std::vector< EFAFragment2D * > _fragments
 
std::vector< EFAPoint_local_node_coor
 

Detailed Description

Definition at line 20 of file EFAElement2D.h.

Constructor & Destructor Documentation

◆ EFAElement2D() [1/3]

EFAElement2D::EFAElement2D ( unsigned int  eid,
unsigned int  n_nodes 
)

Definition at line 23 of file EFAElement2D.C.

Referenced by createChild().

23  : EFAElement(eid, n_nodes)
24 {
25  if (n_nodes == 4 || n_nodes == 8 || n_nodes == 9)
26  _num_edges = 4;
27  else if (n_nodes == 3 || n_nodes == 6 || n_nodes == 7)
28  _num_edges = 3;
29  else
30  EFAError(
31  "In EFAelement2D the supported element types are QUAD4, QUAD8, QUAD9, TRI3, TRI6 and TRI7");
33  _edges = std::vector<EFAEdge *>(_num_edges, nullptr);
34  _edge_neighbors = std::vector<std::vector<EFAElement2D *>>(_num_edges, {nullptr});
35 }
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
EFAElement(unsigned int eid, unsigned int n_nodes)
Definition: EFAElement.C:16
void setLocalCoordinates()
Definition: EFAElement2D.C:141
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ EFAElement2D() [2/3]

EFAElement2D::EFAElement2D ( const EFAElement2D from_elem,
bool  convert_to_local 
)

Definition at line 37 of file EFAElement2D.C.

38  : EFAElement(from_elem->_id, from_elem->_num_nodes),
39  _num_edges(from_elem->_num_edges),
40  _edges(_num_edges, nullptr),
41  _edge_neighbors(_num_edges, {nullptr})
42 {
43  if (convert_to_local)
44  {
45  // build local nodes from global nodes
46  for (unsigned int i = 0; i < _num_nodes; ++i)
47  {
48  if (from_elem->_nodes[i]->category() == EFANode::N_CATEGORY_PERMANENT ||
49  from_elem->_nodes[i]->category() == EFANode::N_CATEGORY_TEMP ||
50  from_elem->_nodes[i]->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT)
51  {
52  _nodes[i] = from_elem->createLocalNodeFromGlobalNode(from_elem->_nodes[i]);
53  _local_nodes.push_back(_nodes[i]); // convenient to delete local nodes
54  }
55  else
56  EFAError("In EFAelement2D ",
57  from_elem->id(),
58  " the copy constructor must have from_elem w/ global nodes. node: ",
59  i,
60  " category: ",
61  from_elem->_nodes[i]->category());
62  }
63 
64  // copy edges, fragments and interior nodes from from_elem
65  for (unsigned int i = 0; i < _num_edges; ++i)
66  _edges[i] = new EFAEdge(*from_elem->_edges[i]);
67  for (unsigned int i = 0; i < from_elem->_fragments.size(); ++i)
68  _fragments.push_back(new EFAFragment2D(this, true, from_elem, i));
69  for (unsigned int i = 0; i < from_elem->_interior_nodes.size(); ++i)
70  _interior_nodes.push_back(new EFAFaceNode(*from_elem->_interior_nodes[i]));
71 
72  // replace all global nodes with local nodes
73  for (unsigned int i = 0; i < _num_nodes; ++i)
74  {
75  if (_nodes[i]->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
76  switchNode(
77  _nodes[i],
78  from_elem->_nodes[i],
79  false); // when save to _cut_elem_map, the EFAelement is not a child of any parent
80  else
81  EFAError("In EFAelement2D copy constructor this elem's nodes must be local");
82  }
83 
85  }
86  else
87  EFAError("this EFAelement2D constructor only converts global nodes to local nodes");
88 }
unsigned int id() const
Definition: EFAElement.C:28
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
unsigned int _id
Definition: EFAElement.h:27
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
EFAElement(unsigned int eid, unsigned int n_nodes)
Definition: EFAElement.C:16
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement2D.C:267
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28
std::vector< EFAPoint > _local_node_coor
Definition: EFAElement2D.h:35
EFANode * createLocalNodeFromGlobalNode(const EFANode *global_node) const
Definition: EFAElement.C:70
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34
std::vector< EFANode * > _local_nodes
Definition: EFAElement.h:30

◆ EFAElement2D() [3/3]

EFAElement2D::EFAElement2D ( const EFAFace from_face)

Definition at line 90 of file EFAElement2D.C.

91  : EFAElement(0, from_face->numNodes()),
92  _num_edges(from_face->numEdges()),
93  _edges(_num_edges, nullptr),
94  _edge_neighbors(_num_edges, {nullptr})
95 {
96  for (unsigned int i = 0; i < _num_nodes; ++i)
97  _nodes[i] = from_face->getNode(i);
98  for (unsigned int i = 0; i < _num_edges; ++i)
99  _edges[i] = new EFAEdge(*from_face->getEdge(i));
100  for (unsigned int i = 0; i < from_face->numInteriorNodes(); ++i)
101  _interior_nodes.push_back(new EFAFaceNode(*from_face->getInteriorNode(i)));
102 }
unsigned int numEdges() const
Definition: EFAFace.h:49
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
EFAElement(unsigned int eid, unsigned int n_nodes)
Definition: EFAElement.C:16
EFANode * getNode(unsigned int node_id) const
Definition: EFAFace.C:99
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int numNodes() const
Definition: EFAFace.C:87
unsigned int _num_nodes
Definition: EFAElement.h:28
EFAEdge * getEdge(unsigned int edge_id) const
Definition: EFAFace.h:50
EFAFaceNode * getInteriorNode(unsigned int index) const
Definition: EFAFace.C:641
unsigned int numInteriorNodes() const
Definition: EFAFace.C:236
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ ~EFAElement2D()

EFAElement2D::~EFAElement2D ( )

Definition at line 104 of file EFAElement2D.C.

105 {
106  for (unsigned int i = 0; i < _fragments.size(); ++i)
107  {
108  if (_fragments[i])
109  {
110  delete _fragments[i];
111  _fragments[i] = nullptr;
112  }
113  }
114  for (unsigned int i = 0; i < _edges.size(); ++i)
115  {
116  if (_edges[i])
117  {
118  delete _edges[i];
119  _edges[i] = nullptr;
120  }
121  }
122  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
123  {
124  if (_interior_nodes[i])
125  {
126  delete _interior_nodes[i];
127  _interior_nodes[i] = nullptr;
128  }
129  }
130  for (unsigned int i = 0; i < _local_nodes.size(); ++i)
131  {
132  if (_local_nodes[i])
133  {
134  delete _local_nodes[i];
135  _local_nodes[i] = nullptr;
136  }
137  }
138 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34
std::vector< EFANode * > _local_nodes
Definition: EFAElement.h:30

Member Function Documentation

◆ addChild()

void EFAElement::addChild ( EFAElement child)
inherited

Definition at line 195 of file EFAElement.C.

196 {
197  _children.push_back(child);
198 }
std::vector< EFAElement * > _children
Definition: EFAElement.h:32

◆ addCrackTipNeighbor()

void EFAElement::addCrackTipNeighbor ( EFAElement neighbor_elem)
inherited

Definition at line 149 of file EFAElement.C.

150 {
151  // Find out what side the specified element is on, and add it as a crack tip neighbor
152  // element for that side.
153  unsigned int neighbor_index = getNeighborIndex(neighbor_elem);
154  bool crack_tip_neighbor_exist = false;
155  for (unsigned int i = 0; i < _crack_tip_neighbors.size(); ++i)
156  {
157  if (_crack_tip_neighbors[i] == neighbor_index)
158  {
159  crack_tip_neighbor_exist = true;
160  break;
161  }
162  }
163  if (!crack_tip_neighbor_exist)
164  _crack_tip_neighbors.push_back(neighbor_index);
165 }
virtual unsigned int getNeighborIndex(const EFAElement *neighbor_elem) const =0
std::vector< unsigned int > _crack_tip_neighbors
Definition: EFAElement.h:34

◆ addEdgeCut()

void EFAElement2D::addEdgeCut ( unsigned int  edge_id,
double  position,
EFANode embedded_node,
std::map< unsigned int, EFANode *> &  EmbeddedNodes,
bool  add_to_neighbor 
)

Definition at line 1715 of file EFAElement2D.C.

Referenced by addEdgeCut(), and ElementFragmentAlgorithm::addElemEdgeIntersection().

1720 {
1721  EFANode * local_embedded = nullptr;
1722  EFANode * edge_node1 = _edges[edge_id]->getNode(0);
1723  if (embedded_node) // use the existing embedded node if it was passed in
1724  local_embedded = embedded_node;
1725 
1726  if (_edges[edge_id]->hasIntersectionAtPosition(position, edge_node1) && position > Xfem::tol &&
1727  position < 1.0 - Xfem::tol)
1728  {
1729  unsigned int emb_id = _edges[edge_id]->getEmbeddedNodeIndex(position, edge_node1);
1730  EFANode * old_emb = _edges[edge_id]->getEmbeddedNode(emb_id);
1731  if (embedded_node && embedded_node != old_emb)
1732  {
1733  EFAError("Attempting to add edge intersection when one already exists with different node.",
1734  " elem: ",
1735  _id,
1736  " edge: ",
1737  edge_id,
1738  " position: ",
1739  position);
1740  }
1741  local_embedded = old_emb;
1742  }
1743  else // if no cut exists at the input position
1744  {
1745  bool add2elem = true;
1746 
1747  // check if it is necessary to add cuts to fragment
1748  // id of partially overlapping fragment edge
1749  unsigned int frag_edge_id = std::numeric_limits<unsigned int>::max();
1750  EFAEdge * frag_edge = nullptr;
1751  EFANode * frag_edge_node1 = nullptr;
1752  double frag_pos = -1.0;
1753  bool add2frag = false;
1754 
1755  if (getFragmentEdgeID(edge_id, frag_edge_id)) // elem edge contains a frag edge
1756  {
1757  frag_edge = getFragmentEdge(0, frag_edge_id);
1758  if (!fragmentEdgeAlreadyCut(edge_id))
1759  {
1760  double xi[2] = {-1.0, -1.0}; // relative coords of two frag edge nodes
1761  xi[0] = _edges[edge_id]->distanceFromNode1(frag_edge->getNode(0));
1762  xi[1] = _edges[edge_id]->distanceFromNode1(frag_edge->getNode(1));
1763  if ((position - xi[0]) * (position - xi[1]) <
1764  0.0) // the cut to be added is within the real part of the edge
1765  {
1766  frag_edge_node1 = frag_edge->getNode(0);
1767  frag_pos = (position - xi[0]) / (xi[1] - xi[0]);
1768  add2frag = true;
1769  }
1770  else // the emb node to be added is in the phantom part of the elem edge
1771  add2elem = false; // DO NOT ADD INTERSECT IN THIS CASE
1772  }
1773  else
1774  {
1775  EFAWarning("attempting to add new cut to a cut fragment edge");
1776  add2elem = false; // DO NOT ADD INTERSECT IN THIS CASE
1777  }
1778  }
1779 
1780  // If elem edge has 2 cuts but they have not been restored yet, it's OK because
1781  // getFragmentEdgeID = false so we won't add anything to the restored fragment.
1782  // add to elem edge (IMPORTANT to do it AFTER the above fragment check)
1783  if (add2elem)
1784  {
1785  if (!local_embedded) // need to create new embedded node
1786  {
1787  unsigned int new_node_id = Efa::getNewID(EmbeddedNodes);
1788  local_embedded = new EFANode(new_node_id, EFANode::N_CATEGORY_EMBEDDED);
1789  EmbeddedNodes.insert(std::make_pair(new_node_id, local_embedded));
1790  }
1791  _edges[edge_id]->addIntersection(position, local_embedded, edge_node1);
1792  if (_edges[edge_id]->numEmbeddedNodes() > 2)
1793  EFAError("element edge can't have >2 embedded nodes");
1794  }
1795 
1796  // add to frag edge
1797  if (add2frag)
1798  {
1799  frag_edge->addIntersection(frag_pos, local_embedded, frag_edge_node1);
1800  if (frag_edge->numEmbeddedNodes() > 1)
1801  EFAError("fragment edge can't have >1 embedded nodes");
1802  }
1803  } // IF the input embedded node already exists on this elem edge
1804 
1805  if (add_to_neighbor)
1806  {
1807  for (unsigned int en_iter = 0; en_iter < numEdgeNeighbors(edge_id); ++en_iter)
1808  {
1809  EFAElement2D * edge_neighbor = getEdgeNeighbor(edge_id, en_iter);
1810  unsigned int neighbor_edge_id = edge_neighbor->getNeighborIndex(this);
1811  if (edge_neighbor->getEdge(neighbor_edge_id)->getNode(0) == edge_node1) // same direction
1812  EFAError("neighbor edge has the same direction as this edge");
1813  double neigh_pos = 1.0 - position; // get emb node's postion on neighbor edge
1814  edge_neighbor->addEdgeCut(neighbor_edge_id, neigh_pos, local_embedded, EmbeddedNodes, false);
1815  }
1816  } // If add_to_neighbor required
1817 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
void addEdgeCut(unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode *> &EmbeddedNodes, bool add_to_neighbor)
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
unsigned int _id
Definition: EFAElement.h:27
virtual unsigned int getNeighborIndex(const EFAElement *neighbor_elem) const
Definition: EFAElement2D.C:452
EFAEdge * getEdge(unsigned int edge_id) const
bool fragmentEdgeAlreadyCut(unsigned int ElemEdgeID) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool getFragmentEdgeID(unsigned int elem_edge_id, unsigned int &frag_edge_id) const
static const double tol
Definition: XFEMFuncs.h:21
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
unsigned int numEmbeddedNodes() const
Definition: EFAEdge.C:341
void addIntersection(double position, EFANode *embedded_node_tmp, EFANode *from_node)
Definition: EFAEdge.C:132
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const

◆ addFragmentEdgeCut()

bool EFAElement2D::addFragmentEdgeCut ( unsigned int  frag_edge_id,
double  position,
std::map< unsigned int, EFANode *> &  EmbeddedNodes 
)

Definition at line 1843 of file EFAElement2D.C.

Referenced by ElementFragmentAlgorithm::addFragEdgeIntersection().

1846 {
1847  if (_fragments.size() != 1)
1848  EFAError("Element: ", _id, " should have only 1 fragment in addFragEdgeIntersection");
1849  EFANode * local_embedded = nullptr;
1850 
1851  // check if this intersection coincide with any embedded node on this edge
1852  bool isValidIntersection = true;
1853  EFAEdge * frag_edge = getFragmentEdge(0, frag_edge_id); // we're considering this edge
1854  EFANode * edge_node1 = frag_edge->getNode(0);
1855  EFANode * edge_node2 = frag_edge->getNode(1);
1856  if ((std::abs(position) < Xfem::tol && edge_node1->category() == EFANode::N_CATEGORY_EMBEDDED) ||
1857  (std::abs(1.0 - position) < Xfem::tol &&
1858  edge_node2->category() == EFANode::N_CATEGORY_EMBEDDED))
1859  isValidIntersection = false;
1860 
1861  // TODO: do not allow to cut fragment's node
1862  if (std::abs(position) < Xfem::tol || std::abs(1.0 - position) < Xfem::tol)
1863  isValidIntersection = false;
1864 
1865  // add valid intersection point to an edge
1866  if (isValidIntersection)
1867  {
1868  if (frag_edge->hasIntersection())
1869  {
1870  if (!frag_edge->hasIntersectionAtPosition(position, edge_node1))
1871  EFAError("Attempting to add fragment edge intersection when one already exists with "
1872  "different position.",
1873  " elem: ",
1874  _id,
1875  " edge: ",
1876  frag_edge_id,
1877  " position: ",
1878  position,
1879  " old position: ",
1880  frag_edge->getIntersection(0, edge_node1));
1881  }
1882  else // blank edge - in fact, it can only be a blank element interior edge
1883  {
1884  if (!_fragments[0]->isEdgeInterior(frag_edge_id) ||
1885  _fragments[0]->isSecondaryInteriorEdge(frag_edge_id))
1886  EFAError("Attemping to add intersection to an invalid fragment edge. Element: ",
1887  _id,
1888  " fragment_edge: ",
1889  frag_edge_id);
1890 
1891  // create the embedded node and add it to the fragment's boundary edge
1892  unsigned int new_node_id = Efa::getNewID(EmbeddedNodes);
1893  local_embedded = new EFANode(new_node_id, EFANode::N_CATEGORY_EMBEDDED);
1894  EmbeddedNodes.insert(std::make_pair(new_node_id, local_embedded));
1895  frag_edge->addIntersection(position, local_embedded, edge_node1);
1896 
1897  // save this interior embedded node to FaceNodes
1898  // TODO: for unstructured elements, the following calution gives you inaccurate position of
1899  // face nodes
1900  // must solve this issue for 3D!
1901  std::vector<double> node1_para_coor(2, 0.0);
1902  std::vector<double> node2_para_coor(2, 0.0);
1903  if (getEdgeNodeParametricCoordinate(edge_node1, node1_para_coor) &&
1904  getEdgeNodeParametricCoordinate(edge_node2, node2_para_coor))
1905  {
1906  double xi = (1.0 - position) * node1_para_coor[0] + position * node2_para_coor[0];
1907  double eta = (1.0 - position) * node1_para_coor[1] + position * node2_para_coor[1];
1908  _interior_nodes.push_back(new EFAFaceNode(local_embedded, xi, eta));
1909  }
1910  else
1911  EFAError("elem: ", _id, " cannot get the parametric coords of two end embedded nodes");
1912  }
1913  // no need to add intersection for neighbor fragment - if this fragment has a
1914  // neighbor fragment, the neighbor has already been treated in addEdgeIntersection;
1915  // for an interior edge, there is no neighbor fragment
1916  }
1917 
1918  return isValidIntersection;
1919 }
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
bool getEdgeNodeParametricCoordinate(EFANode *node, std::vector< double > &para_coor) const
double getIntersection(unsigned int emb_id, EFANode *from_node) const
Definition: EFAEdge.C:239
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
unsigned int _id
Definition: EFAElement.h:27
bool hasIntersection() const
Definition: EFAEdge.C:200
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
static const double tol
Definition: XFEMFuncs.h:21
bool hasIntersectionAtPosition(double position, EFANode *from_node) const
Definition: EFAEdge.C:213
void addIntersection(double position, EFANode *embedded_node_tmp, EFANode *from_node)
Definition: EFAEdge.C:132
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34
N_CATEGORY category() const
Definition: EFANode.C:42

◆ addNodeCut()

void EFAElement2D::addNodeCut ( unsigned int  node_id,
EFANode embedded_permanent_node,
std::map< unsigned int, EFANode *> &  PermanentNodes,
std::map< unsigned int, EFANode *> &  EmbeddedPermanentNodes 
)

Definition at line 1820 of file EFAElement2D.C.

Referenced by ElementFragmentAlgorithm::addElemNodeIntersection().

1824 {
1825  EFANode * local_embedded_permanent = nullptr;
1826  EFANode * node = _nodes[node_id];
1827  if (embedded_permanent_node) // use the existing embedded node if it was passed in
1828  local_embedded_permanent = embedded_permanent_node;
1829 
1830  if (node->category() == EFANode::N_CATEGORY_PERMANENT)
1831  {
1833  local_embedded_permanent = node;
1834  EmbeddedPermanentNodes.insert(std::make_pair(node->id(), local_embedded_permanent));
1835  if (!Efa::deleteFromMap(PermanentNodes, local_embedded_permanent, false))
1836  EFAError("Attempted to delete node: ",
1837  local_embedded_permanent->id(),
1838  " from PermanentNodes, but couldn't find it");
1839  }
1840 }
bool deleteFromMap(std::map< unsigned int, T *> &theMap, T *elemToDelete, bool delete_elem=true)
Definition: EFAFuncs.h:22
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
void setCategory(EFANode::N_CATEGORY category)
Definition: EFANode.C:60
unsigned int id() const
Definition: EFANode.C:36
N_CATEGORY category() const
Definition: EFANode.C:42

◆ branchingSplit()

std::vector< EFAFragment2D * > EFAElement2D::branchingSplit ( std::map< unsigned int, EFANode *> &  EmbeddedNodes)

Definition at line 1922 of file EFAElement2D.C.

Referenced by updateFragments().

1923 {
1924  if (isPartial())
1925  EFAError("branching is only allowed for an uncut element");
1926 
1927  // collect all emb nodes counterclockwise
1928  std::vector<EFANode *> three_nodes;
1929  for (unsigned int i = 0; i < _edges.size(); ++i)
1930  {
1931  EFANode * node1 = _edges[i]->getNode(0);
1932  if (_edges[i]->numEmbeddedNodes() == 1)
1933  three_nodes.push_back(_edges[i]->getEmbeddedNode(0));
1934  else if (_edges[i]->numEmbeddedNodes() == 2)
1935  {
1936  unsigned int id0(
1937  _edges[i]->getIntersection(0, node1) < _edges[i]->getIntersection(1, node1) ? 0 : 1);
1938  unsigned int id1 = 1 - id0;
1939  three_nodes.push_back(_edges[i]->getEmbeddedNode(id0));
1940  three_nodes.push_back(_edges[i]->getEmbeddedNode(id1));
1941  }
1942  }
1943  if (three_nodes.size() != 3)
1944  EFAError("three_nodes.size() != 3");
1945 
1946  // get the parent coords of the braycenter of the three nodes
1947  // TODO: may need a better way to compute this "branching point"
1948  std::vector<double> center_xi(2, 0.0);
1949  for (unsigned int i = 0; i < 3; ++i)
1950  {
1951  std::vector<double> xi_2d(2, 0.0);
1952  getEdgeNodeParametricCoordinate(three_nodes[i], xi_2d);
1953  center_xi[0] += xi_2d[0];
1954  center_xi[1] += xi_2d[1];
1955  }
1956  center_xi[0] /= 3.0;
1957  center_xi[1] /= 3.0;
1958 
1959  // create a new interior node for current element
1960  unsigned int new_node_id = Efa::getNewID(EmbeddedNodes);
1961  EFANode * new_emb = new EFANode(new_node_id, EFANode::N_CATEGORY_EMBEDDED);
1962  EmbeddedNodes.insert(std::make_pair(new_node_id, new_emb));
1963  _interior_nodes.push_back(new EFAFaceNode(new_emb, center_xi[0], center_xi[1]));
1964 
1965  // generate the three fragments
1966  std::vector<EFAFragment2D *> new_fragments;
1967  for (unsigned int i = 0; i < 3; ++i) // loop over 3 sectors
1968  {
1969  EFAFragment2D * new_frag = new EFAFragment2D(this, false, nullptr);
1970  unsigned int iplus1(i < 2 ? i + 1 : 0);
1971  new_frag->addEdge(new EFAEdge(three_nodes[iplus1], new_emb));
1972  new_frag->addEdge(new EFAEdge(new_emb, three_nodes[i]));
1973 
1974  unsigned int iedge = 0;
1975  bool add_more_edges = true;
1976  for (unsigned int j = 0; j < _edges.size(); ++j)
1977  {
1978  if (_edges[j]->containsNode(three_nodes[i]))
1979  {
1980  if (_edges[j]->containsNode(three_nodes[iplus1]))
1981  {
1982  new_frag->addEdge(new EFAEdge(three_nodes[i], three_nodes[iplus1]));
1983  add_more_edges = false;
1984  }
1985  else
1986  {
1987  new_frag->addEdge(new EFAEdge(three_nodes[i], _edges[j]->getNode(1)));
1988  }
1989  iedge = j;
1990  break;
1991  }
1992  } // j
1993  while (add_more_edges)
1994  {
1995  iedge += 1;
1996  if (iedge == _edges.size())
1997  iedge = 0;
1998  if (_edges[iedge]->containsNode(three_nodes[iplus1]))
1999  {
2000  new_frag->addEdge(new EFAEdge(_edges[iedge]->getNode(0), three_nodes[iplus1]));
2001  add_more_edges = false;
2002  }
2003  else
2004  new_frag->addEdge(new EFAEdge(_edges[iedge]->getNode(0), _edges[iedge]->getNode(1)));
2005  }
2006  new_fragments.push_back(new_frag);
2007  } // i
2008  return new_fragments;
2009 }
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
bool getEdgeNodeParametricCoordinate(EFANode *node, std::vector< double > &para_coor) const
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
void addEdge(EFAEdge *new_edge)
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
virtual bool isPartial() const
Definition: EFAElement2D.C:213
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")

◆ clearNeighbors()

void EFAElement2D::clearNeighbors ( )
virtual

Implements EFAElement.

Definition at line 464 of file EFAElement2D.C.

465 {
466  _general_neighbors.clear();
467  for (unsigned int edge_iter = 0; edge_iter < _num_edges; ++edge_iter)
468  _edge_neighbors[edge_iter] = {nullptr};
469 }
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36

◆ clearParentAndChildren()

void EFAElement::clearParentAndChildren ( )
inherited

Definition at line 201 of file EFAElement.C.

Referenced by ElementFragmentAlgorithm::clearAncestry().

202 {
203  _parent = nullptr;
204  _children.clear();
205 }
EFAElement * _parent
Definition: EFAElement.h:31
std::vector< EFAElement * > _children
Definition: EFAElement.h:32

◆ connectNeighbors()

void EFAElement2D::connectNeighbors ( std::map< unsigned int, EFANode *> &  PermanentNodes,
std::map< unsigned int, EFANode *> &  TempNodes,
std::map< EFANode *, std::set< EFAElement *>> &  InverseConnectivityMap,
bool  merge_phantom_edges 
)
virtual

Implements EFAElement.

Definition at line 1176 of file EFAElement2D.C.

1180 {
1181  // N.B. "this" must point to a child element that was just created
1182  if (!_parent)
1183  EFAError("no parent element for child element ", _id, " in connect_neighbors");
1184  EFAElement2D * parent2d = dynamic_cast<EFAElement2D *>(_parent);
1185  if (!parent2d)
1186  EFAError("cannot dynamic cast to parent2d in connect_neighbors");
1187 
1188  // First loop through edges and merge nodes with neighbors as appropriate
1189  for (unsigned int j = 0; j < _num_edges; ++j)
1190  {
1191  for (unsigned int k = 0; k < parent2d->numEdgeNeighbors(j); ++k)
1192  {
1193  EFAElement2D * NeighborElem = parent2d->getEdgeNeighbor(j, k);
1194  unsigned int neighbor_edge_id = NeighborElem->getNeighborIndex(parent2d);
1195 
1196  if (_edges[j]->hasIntersection())
1197  {
1198  for (unsigned int l = 0; l < NeighborElem->numChildren(); ++l)
1199  {
1200  EFAElement2D * childOfNeighborElem =
1201  dynamic_cast<EFAElement2D *>(NeighborElem->getChild(l));
1202  if (!childOfNeighborElem)
1203  EFAError("dynamic cast childOfNeighborElem fails");
1204 
1205  // Check to see if the nodes are already merged. There's nothing else to do in that case.
1206  EFAEdge * neighborChildEdge = childOfNeighborElem->getEdge(neighbor_edge_id);
1207  if (_edges[j]->equivalent(*neighborChildEdge))
1208  continue;
1209 
1210  if (_fragments[0]->isConnected(childOfNeighborElem->getFragment(0)))
1211  {
1212  unsigned int num_edge_nodes = 2;
1213  for (unsigned int i = 0; i < num_edge_nodes; ++i)
1214  {
1215  unsigned int childNodeIndex = i;
1216  unsigned int neighborChildNodeIndex = num_edge_nodes - 1 - childNodeIndex;
1217 
1218  EFANode * childNode = _edges[j]->getNode(childNodeIndex);
1219  EFANode * childOfNeighborNode = neighborChildEdge->getNode(neighborChildNodeIndex);
1220 
1221  mergeNodes(
1222  childNode, childOfNeighborNode, childOfNeighborElem, PermanentNodes, TempNodes);
1223  }
1224 
1225  EFANode * childNode = _edges[j]->getInteriorNode();
1226  EFANode * childOfNeighborNode = neighborChildEdge->getInteriorNode();
1227 
1228  mergeNodes(
1229  childNode, childOfNeighborNode, childOfNeighborElem, PermanentNodes, TempNodes);
1230  }
1231  } // l, loop over NeighborElem's children
1232  }
1233  else // No edge intersection -- optionally merge non-material nodes if they share a common
1234  // parent
1235  {
1236  if (merge_phantom_edges)
1237  {
1238  for (unsigned int l = 0; l < NeighborElem->numChildren(); ++l)
1239  {
1240  EFAElement2D * childOfNeighborElem =
1241  dynamic_cast<EFAElement2D *>(NeighborElem->getChild(l));
1242  if (!childOfNeighborElem)
1243  EFAError("dynamic cast childOfNeighborElem fails");
1244 
1245  EFAEdge * neighborChildEdge = childOfNeighborElem->getEdge(neighbor_edge_id);
1246  if (!neighborChildEdge->hasIntersection()) // neighbor edge must NOT have
1247  // intersection either
1248  {
1249  // Check to see if the nodes are already merged. There's nothing else to do in that
1250  // case.
1251  unsigned int num_edge_nodes = 2;
1252  for (unsigned int i = 0; i < num_edge_nodes; ++i)
1253  {
1254  unsigned int childNodeIndex = i;
1255  unsigned int neighborChildNodeIndex = num_edge_nodes - 1 - childNodeIndex;
1256 
1257  EFANode * childNode = _edges[j]->getNode(childNodeIndex);
1258  EFANode * childOfNeighborNode = neighborChildEdge->getNode(neighborChildNodeIndex);
1259 
1260  if (childNode->parent() != nullptr &&
1261  childNode->parent() ==
1262  childOfNeighborNode
1263  ->parent()) // non-material node and both come from same parent
1264  mergeNodes(childNode,
1265  childOfNeighborNode,
1266  childOfNeighborElem,
1267  PermanentNodes,
1268  TempNodes);
1269  } // i
1270  }
1271  } // loop over NeighborElem's children
1272  } // if (merge_phantom_edges)
1273  } // IF edge-j has_intersection()
1274  } // k, loop over neighbors on edge j
1275  } // j, loop over all edges
1276 
1277  // Now do a second loop through edges and convert remaining nodes to permanent nodes.
1278  // Important: temp nodes are not shared by any neighbor, so no need to switch nodes on neighbors
1279  for (unsigned int j = 0; j < _num_nodes; ++j)
1280  {
1281  EFANode * childNode = _nodes[j];
1282  if (childNode->category() == EFANode::N_CATEGORY_TEMP)
1283  {
1284  // if current child element does not have siblings, and if current temp node is a lone one
1285  // this temp node should be merged back to its parent permanent node. Otherwise we would have
1286  // permanent nodes that are not connected to any element
1287  std::set<EFAElement *> patch_elems = InverseConnectivityMap[childNode->parent()];
1288  if (parent2d->numFragments() == 1 && patch_elems.size() == 1)
1289  switchNode(childNode->parent(), childNode, false);
1290  else
1291  {
1292  unsigned int new_node_id = Efa::getNewID(PermanentNodes);
1293  EFANode * newNode =
1294  new EFANode(new_node_id, EFANode::N_CATEGORY_PERMANENT, childNode->parent());
1295  PermanentNodes.insert(std::make_pair(new_node_id, newNode));
1296  switchNode(newNode, childNode, false);
1297  }
1298  if (!Efa::deleteFromMap(TempNodes, childNode))
1299  EFAError(
1300  "Attempted to delete node: ", childNode->id(), " from TempNodes, but couldn't find it");
1301  }
1302  }
1303 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
unsigned int numChildren() const
Definition: EFAElement.C:189
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
unsigned int _id
Definition: EFAElement.h:27
virtual unsigned int getNeighborIndex(const EFAElement *neighbor_elem) const
Definition: EFAElement2D.C:452
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool hasIntersection() const
Definition: EFAEdge.C:200
bool deleteFromMap(std::map< unsigned int, T *> &theMap, T *elemToDelete, bool delete_elem=true)
Definition: EFAFuncs.h:22
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
EFAElement * getChild(unsigned int child_id) const
Definition: EFAElement.C:174
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement2D.C:267
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
EFAFragment2D * getFragment(unsigned int frag_id) const
unsigned int _num_nodes
Definition: EFAElement.h:28
EFAElement * _parent
Definition: EFAElement.h:31
EFANode * getInteriorNode() const
Definition: EFAEdge.h:51
void mergeNodes(EFANode *&childNode, EFANode *&childOfNeighborNode, EFAElement *childOfNeighborElem, std::map< unsigned int, EFANode *> &PermanentNodes, std::map< unsigned int, EFANode *> &TempNodes)
Definition: EFAElement.C:242
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
EFANode * parent() const
Definition: EFANode.C:48
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
static const std::string k
Definition: NS.h:124
unsigned int id() const
Definition: EFANode.C:36
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34
N_CATEGORY category() const
Definition: EFANode.C:42

◆ containsNode()

bool EFAElement::containsNode ( EFANode node) const
inherited

◆ createChild()

void EFAElement2D::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 
)
virtual

Implements EFAElement.

Definition at line 990 of file EFAElement2D.C.

996 {
997  if (_children.size() != 0)
998  EFAError("Element cannot have existing children in createChildElements");
999 
1000  bool shouldDuplicateForCutNodeElement = false;
1001  for (unsigned int j = 0; j < _num_nodes; ++j)
1002  {
1003  if (_nodes[j]->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT)
1004  shouldDuplicateForCutNodeElement = true;
1005  }
1006 
1007  if (_fragments.size() > 1 || shouldDuplicateForCrackTip(CrackTipElements) ||
1008  shouldDuplicateForCutNodeElement)
1009  {
1010  if (_fragments.size() > 3)
1011  EFAError("More than 3 fragments not yet supported");
1012 
1013  // set up the children
1014  ParentElements.push_back(this);
1015  for (unsigned int ichild = 0; ichild < _fragments.size(); ++ichild)
1016  {
1017  unsigned int new_elem_id;
1018  if (newChildElements.size() == 0)
1019  new_elem_id = Efa::getNewID(Elements);
1020  else
1021  new_elem_id = Efa::getNewID(newChildElements);
1022 
1023  EFAElement2D * childElem = new EFAElement2D(new_elem_id, this->numNodes());
1024  newChildElements.insert(std::make_pair(new_elem_id, childElem));
1025 
1026  ChildElements.push_back(childElem);
1027  childElem->setParent(this);
1028  _children.push_back(childElem);
1029 
1030  std::vector<EFAPoint> local_embedded_node_coor;
1031 
1032  for (unsigned int i = 0; i < this->getFragment(ichild)->numEdges(); ++i)
1033  {
1034  if (this->getFragment(ichild)->isEdgeInterior(i))
1035  {
1036  std::vector<EFANode *> master_nodes;
1037  std::vector<double> master_weights;
1038 
1039  for (unsigned int j = 0; j < 2; ++j)
1040  {
1041  this->getMasterInfo(
1042  this->getFragmentEdge(ichild, i)->getNode(j), master_nodes, master_weights);
1043  EFAPoint coor(0.0, 0.0, 0.0);
1044  for (unsigned int k = 0; k < master_nodes.size(); ++k)
1045  {
1046  EFANode * local = this->createLocalNodeFromGlobalNode(master_nodes[k]);
1047  coor += _local_node_coor[local->id()] * master_weights[k];
1048  delete local;
1049  }
1050  local_embedded_node_coor.push_back(coor);
1051  }
1052  }
1053  }
1054 
1055  EFAPoint normal(0.0, 0.0, 0.0);
1056  EFAPoint origin(0.0, 0.0, 0.0);
1057  EFAPoint normal2(0.0, 0.0, 0.0);
1058  EFAPoint origin2(0.0, 0.0, 0.0);
1059 
1060  if (local_embedded_node_coor.size())
1061  {
1062  EFAPoint cut_line = local_embedded_node_coor[1] - local_embedded_node_coor[0];
1063  normal = EFAPoint(cut_line(1), -cut_line(0), 0.0);
1064  Xfem::normalizePoint(normal);
1065  origin = (local_embedded_node_coor[0] + local_embedded_node_coor[1]) * 0.5;
1066  }
1067 
1068  if (local_embedded_node_coor.size() == 4)
1069  {
1070  EFAPoint cut_line = local_embedded_node_coor[3] - local_embedded_node_coor[2];
1071  normal2 = EFAPoint(cut_line(1), -cut_line(0), 0.0);
1072  Xfem::normalizePoint(normal2);
1073  origin2 = (local_embedded_node_coor[2] + local_embedded_node_coor[3]) * 0.5;
1074  }
1075 
1076  // get child element's nodes
1077  for (unsigned int j = 0; j < _num_nodes; ++j)
1078  {
1079  EFAPoint p(0.0, 0.0, 0.0);
1080  p = _local_node_coor[j];
1081 
1082  EFAPoint origin_to_point = p - origin;
1083  EFAPoint origin2_to_point = p - origin2;
1084 
1085  if (_fragments.size() == 1 &&
1086  _nodes[j]->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT) // create temp node for
1087  // embedded permanent
1088  // node
1089  {
1090  unsigned int new_node_id = Efa::getNewID(TempNodes);
1091  EFANode * newNode = new EFANode(new_node_id, EFANode::N_CATEGORY_TEMP, _nodes[j]);
1092  TempNodes.insert(std::make_pair(new_node_id, newNode));
1093  childElem->setNode(j, newNode); // be a temp node
1094  }
1095  else if (_fragments.size() == 1 && !shouldDuplicateForCrackTip(CrackTipElements))
1096  {
1097  childElem->setNode(j, _nodes[j]); // inherit parent's node
1098  }
1099  else if (std::abs(origin_to_point * normal) < Xfem::tol &&
1100  _fragments.size() > 1) // cut through node case
1101  {
1102  unsigned int new_node_id = Efa::getNewID(TempNodes);
1103  EFANode * newNode = new EFANode(new_node_id, EFANode::N_CATEGORY_TEMP, _nodes[j]);
1104  TempNodes.insert(std::make_pair(new_node_id, newNode));
1105  childElem->setNode(j, newNode); // be a temp node
1106  }
1107  else if (origin_to_point * normal < Xfem::tol && origin2_to_point * normal2 < Xfem::tol &&
1108  (_fragments.size() > 1 || shouldDuplicateForCrackTip(CrackTipElements)))
1109  {
1110  childElem->setNode(j, _nodes[j]); // inherit parent's node
1111  }
1112  else if (normal.norm() < Xfem::tol && normal2.norm() < Xfem::tol &&
1113  _fragments.size() == 1) // cut along edge case
1114  {
1115  childElem->setNode(j, _nodes[j]); // inherit parent's node
1116  }
1117  else if ((_fragments.size() > 1 ||
1119  CrackTipElements))) // parent element's node is not in fragment
1120  {
1121  unsigned int new_node_id = Efa::getNewID(TempNodes);
1122  EFANode * newNode = new EFANode(new_node_id, EFANode::N_CATEGORY_TEMP, _nodes[j]);
1123  TempNodes.insert(std::make_pair(new_node_id, newNode));
1124  childElem->setNode(j, newNode); // be a temp node
1125  }
1126  }
1127 
1128  // get child element's fragments
1129  EFAFragment2D * new_frag = new EFAFragment2D(childElem, true, this, ichild);
1130  childElem->_fragments.push_back(new_frag);
1131 
1132  // get child element's edges
1133  for (unsigned int j = 0; j < _num_edges; ++j)
1134  {
1135  unsigned int jplus1(j < (_num_edges - 1) ? j + 1 : 0);
1136  EFAEdge * new_edge = new EFAEdge(childElem->getNode(j), childElem->getNode(jplus1));
1137  if (_edges[j]->hasIntersection())
1138  new_edge->copyIntersection(*_edges[j], 0);
1139  if ((_num_edges == 4 && _num_nodes > 4) || (_num_edges == 3 && _num_nodes > 3))
1140  new_edge->setInteriorNode(childElem->getNode(_num_edges + j));
1141  childElem->setEdge(j, new_edge);
1142  }
1143  childElem->removePhantomEmbeddedNode(); // IMPORTANT
1144 
1145  // inherit old interior nodes
1146  for (unsigned int j = 0; j < _interior_nodes.size(); ++j)
1147  childElem->_interior_nodes.push_back(new EFAFaceNode(*_interior_nodes[j]));
1148  }
1149  }
1150  else // num_links == 1 || num_links == 0
1151  // child is itself - but don't insert into the list of ChildElements!!!
1152  _children.push_back(this);
1153 }
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
unsigned int numEdges() const
virtual bool shouldDuplicateForCrackTip(const std::set< EFAElement *> &CrackTipElements)
Definition: EFAElement2D.C:620
void setEdge(unsigned int edge_id, EFAEdge *edge)
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool isEdgeInterior(unsigned int edge_id) const
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
EFAFragment2D * getFragment(unsigned int frag_id) const
void setParent(EFAElement *parent)
Definition: EFAElement.C:183
unsigned int _num_nodes
Definition: EFAElement.h:28
virtual void removePhantomEmbeddedNode()
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
void setInteriorNode(EFANode *node)
Definition: EFAEdge.h:52
static const double tol
Definition: XFEMFuncs.h:21
void copyIntersection(const EFAEdge &other, unsigned int from_node_id)
Definition: EFAEdge.C:162
std::vector< EFAPoint > _local_node_coor
Definition: EFAElement2D.h:35
EFANode * createLocalNodeFromGlobalNode(const EFANode *global_node) const
Definition: EFAElement.C:70
virtual void getMasterInfo(EFANode *node, std::vector< EFANode *> &master_nodes, std::vector< double > &master_weights) const
Definition: EFAElement2D.C:305
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void normalizePoint(Point &p)
Definition: XFEMFuncs.C:621
unsigned int _num_edges
Definition: EFAElement2D.h:30
unsigned int numNodes() const
Definition: EFAElement.C:34
std::vector< EFAElement * > _children
Definition: EFAElement.h:32
EFAElement2D(unsigned int eid, unsigned int n_nodes)
Definition: EFAElement2D.C:23
static const std::string k
Definition: NS.h:124
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34
void setNode(unsigned int node_id, EFANode *node)
Definition: EFAElement.C:40

◆ createEdges()

void EFAElement2D::createEdges ( )

Definition at line 1464 of file EFAElement2D.C.

Referenced by ElementFragmentAlgorithm::add2DElement(), and ElementFragmentAlgorithm::add2DElements().

1465 {
1466  for (unsigned int i = 0; i < _num_edges; ++i)
1467  {
1468  unsigned int i_plus1(i < (_num_edges - 1) ? i + 1 : 0);
1469  EFAEdge * new_edge = new EFAEdge(_nodes[i], _nodes[i_plus1]);
1470 
1471  if ((_num_edges == 4 && _num_nodes > 4) || (_num_edges == 3 && _num_nodes > 3))
1472  new_edge->setInteriorNode(
1473  _nodes[i + _num_edges]); // '_num_edges' is the offset of interior edge node numbering
1474 
1475  _edges[i] = new_edge;
1476  }
1477 }
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28
void setInteriorNode(EFANode *node)
Definition: EFAEdge.h:52
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ createLocalNodeFromGlobalNode()

EFANode * EFAElement::createLocalNodeFromGlobalNode ( const EFANode global_node) const
inherited

Definition at line 70 of file EFAElement.C.

Referenced by createChild(), EFAElement3D::createChild(), and EFAElement3D::EFAElement3D().

71 {
72  // Given a global node, create a new local node
73  if (global_node->category() != EFANode::N_CATEGORY_PERMANENT &&
74  global_node->category() != EFANode::N_CATEGORY_TEMP &&
76  EFAError("In createLocalNodeFromGlobalNode node is not global");
77 
78  EFANode * new_local_node = nullptr;
79  unsigned int inode = 0;
80  for (; inode < _nodes.size(); ++inode)
81  {
82  if (_nodes[inode] == global_node)
83  {
84  new_local_node = new EFANode(inode, EFANode::N_CATEGORY_LOCAL_INDEX);
85  break;
86  }
87  }
88  if (!new_local_node)
89  EFAError("In createLocalNodeFromGlobalNode could not find global node");
90 
91  return new_local_node;
92 }
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
N_CATEGORY category() const
Definition: EFANode.C:42

◆ deleteInteriorNodes()

void EFAElement2D::deleteInteriorNodes ( )

Definition at line 1444 of file EFAElement2D.C.

Referenced by EFAFragment2D::removeInvalidEmbeddedNodes().

1445 {
1446  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
1447  delete _interior_nodes[i];
1448  _interior_nodes.clear();
1449 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32

◆ edgeContainsTip()

bool EFAElement2D::edgeContainsTip ( unsigned int  edge_id) const

Definition at line 1674 of file EFAElement2D.C.

Referenced by fragmentEdgeAlreadyCut().

1675 {
1676  bool contains_tip = false;
1677  if (_fragments.size() == 1)
1678  {
1679  unsigned int num_frag_edges = 0; // count how many fragment edges this element edge contains
1680  if (_edges[edge_id]->hasIntersection())
1681  {
1682  for (unsigned int j = 0; j < _fragments[0]->numEdges(); ++j)
1683  {
1684  if (_edges[edge_id]->containsEdge(*_fragments[0]->getEdge(j)))
1685  num_frag_edges += 1;
1686  } // j
1687  if (num_frag_edges == 2)
1688  contains_tip = true;
1689  }
1690  }
1691  return contains_tip;
1692 }
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ findGeneralNeighbors()

void EFAElement::findGeneralNeighbors ( const std::map< EFANode *, std::set< EFAElement *>> &  InverseConnectivity)
inherited

Definition at line 208 of file EFAElement.C.

Referenced by setupNeighbors(), and EFAElement3D::setupNeighbors().

210 {
211  _general_neighbors.clear();
212  std::set<EFAElement *> patch_elements;
213  for (unsigned int inode = 0; inode < _num_nodes; ++inode)
214  {
215  auto it = inverse_connectivity.find(_nodes[inode]);
216  if (it != inverse_connectivity.end())
217  patch_elements.insert(it->second.begin(), it->second.end());
218  }
219 
220  std::set<EFAElement *>::iterator eit2;
221  for (eit2 = patch_elements.begin(); eit2 != patch_elements.end(); ++eit2)
222  {
223  EFAElement * neigh_elem = *eit2;
224  if (neigh_elem != this)
225  _general_neighbors.push_back(neigh_elem);
226  }
227 }
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36

◆ fragmentEdgeAlreadyCut()

bool EFAElement2D::fragmentEdgeAlreadyCut ( unsigned int  ElemEdgeID) const

Definition at line 1695 of file EFAElement2D.C.

Referenced by addEdgeCut().

1696 {
1697  // when marking cuts, check if the corresponding frag edge already has been cut
1698  bool has_cut = false;
1699  if (edgeContainsTip(ElemEdgeID))
1700  has_cut = true;
1701  else
1702  {
1703  unsigned int FragEdgeID = std::numeric_limits<unsigned int>::max();
1704  if (getFragmentEdgeID(ElemEdgeID, FragEdgeID))
1705  {
1706  EFAEdge * frag_edge = getFragmentEdge(0, FragEdgeID);
1707  if (frag_edge->hasIntersection())
1708  has_cut = true;
1709  }
1710  }
1711  return has_cut;
1712 }
bool edgeContainsTip(unsigned int edge_id) const
bool hasIntersection() const
Definition: EFAEdge.C:200
bool getFragmentEdgeID(unsigned int elem_edge_id, unsigned int &frag_edge_id) const
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const

◆ fragmentHasTipEdges()

bool EFAElement2D::fragmentHasTipEdges ( ) const

Definition at line 1586 of file EFAElement2D.C.

Referenced by isCrackTipElement().

1587 {
1588  bool has_tip_edges = false;
1589  if (_fragments.size() == 1)
1590  {
1591  for (unsigned int i = 0; i < _num_edges; ++i)
1592  {
1593  unsigned int num_frag_edges = 0; // count how many fragment edges this element edge contains
1594  if (_edges[i]->hasIntersection())
1595  {
1596  for (unsigned int j = 0; j < _fragments[0]->numEdges(); ++j)
1597  {
1598  if (_edges[i]->containsEdge(*_fragments[0]->getEdge(j)))
1599  num_frag_edges += 1;
1600  } // j
1601  if (num_frag_edges == 2)
1602  {
1603  has_tip_edges = true;
1604  break;
1605  }
1606  }
1607  } // i
1608  }
1609  return has_tip_edges;
1610 }
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ fragmentSanityCheck()

void EFAElement2D::fragmentSanityCheck ( unsigned int  n_old_frag_edges,
unsigned int  n_old_frag_cuts 
) const
virtual

Implements EFAElement.

Definition at line 876 of file EFAElement2D.C.

Referenced by updateFragments().

877 {
878  if (n_old_frag_cuts > 3)
879  EFAError("Sanity check: in element ", _id, " frag has more than 3 cut edges");
880 
881  // count permanent and embedded nodes for new fragments
882  std::vector<unsigned int> num_emb;
883  std::vector<unsigned int> num_perm;
884  std::vector<unsigned int> num_emb_perm;
885  for (unsigned int i = 0; i < _fragments.size(); ++i)
886  {
887  num_emb.push_back(0);
888  num_perm.push_back(0);
889  num_emb_perm.push_back(0);
890  std::set<EFANode *> perm_nodes;
891  std::set<EFANode *> emb_nodes;
892  std::set<EFANode *> emb_perm_nodes;
893  for (unsigned int j = 0; j < _fragments[i]->numEdges(); ++j)
894  {
895  for (unsigned int k = 0; k < 2; ++k)
896  {
897  EFANode * temp_node = _fragments[i]->getEdge(j)->getNode(k);
898  if (temp_node->category() == EFANode::N_CATEGORY_PERMANENT)
899  perm_nodes.insert(temp_node);
900  else if (temp_node->category() == EFANode::N_CATEGORY_EMBEDDED)
901  emb_nodes.insert(temp_node);
902  else if (temp_node->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT)
903  emb_perm_nodes.insert(temp_node);
904  else
905  EFAError("Invalid node category");
906  }
907  }
908  num_perm[i] = perm_nodes.size();
909  num_emb[i] = emb_nodes.size();
910  num_emb_perm[i] = emb_perm_nodes.size();
911  }
912 
913  // TODO: For cut-node case, how to check fragment sanity
914  for (unsigned int i = 0; i < _fragments.size(); ++i)
915  if (num_emb_perm[i] != 0)
916  return;
917 
918  unsigned int n_interior_nodes = numInteriorNodes();
919  if (n_interior_nodes > 0 && n_interior_nodes != 1)
920  EFAError("After update_fragments this element has ", n_interior_nodes, " interior nodes");
921 
922  if (n_old_frag_cuts == 0)
923  {
924  if (_fragments.size() != 1 || _fragments[0]->numEdges() != n_old_frag_edges)
925  EFAError("Incorrect link size for element with 0 cuts");
926  }
927  else if (n_old_frag_cuts == 1) // crack tip case
928  {
929  if (_fragments.size() != 1 || _fragments[0]->numEdges() != n_old_frag_edges + 1)
930  EFAError("Incorrect link size for element with 1 cut");
931  }
932  else if (n_old_frag_cuts == 2)
933  {
934  if (_fragments.size() != 2 ||
935  (_fragments[0]->numEdges() + _fragments[1]->numEdges()) != n_old_frag_edges + 4)
936  EFAError("Incorrect link size for element with 2 cuts");
937  }
938  else if (n_old_frag_cuts == 3)
939  {
940  if (_fragments.size() != 3 || (_fragments[0]->numEdges() + _fragments[1]->numEdges() +
941  _fragments[2]->numEdges()) != n_old_frag_edges + 9)
942  EFAError("Incorrect link size for element with 3 cuts");
943  }
944  else
945  EFAError("Unexpected number of old fragment cuts");
946 }
unsigned int _id
Definition: EFAElement.h:27
virtual unsigned int numInteriorNodes() const
Definition: EFAElement2D.C:358
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:124
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34
N_CATEGORY category() const
Definition: EFANode.C:42

◆ getChild()

EFAElement * EFAElement::getChild ( unsigned int  child_id) const
inherited

Definition at line 174 of file EFAElement.C.

Referenced by connectNeighbors(), EFAElement3D::connectNeighbors(), switchNode(), and EFAElement3D::switchNode().

175 {
176  if (child_id < _children.size())
177  return _children[child_id];
178  else
179  EFAError("child_id out of bounds");
180 }
std::vector< EFAElement * > _children
Definition: EFAElement.h:32

◆ getCommonNodes()

std::vector< EFANode * > EFAElement2D::getCommonNodes ( const EFAElement2D other_elem) const

Definition at line 2067 of file EFAElement2D.C.

Referenced by overlaysElement(), and setupNeighbors().

2068 {
2069  std::set<EFANode *> e1nodes(_nodes.begin(),
2070  _nodes.begin() + _num_edges); // only account for corner nodes
2071  std::set<EFANode *> e2nodes(other_elem->_nodes.begin(), other_elem->_nodes.begin() + _num_edges);
2072  std::vector<EFANode *> common_nodes = Efa::getCommonElems(e1nodes, e2nodes);
2073  return common_nodes;
2074 }
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
std::vector< T > getCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:69
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ getCrackTipNeighbor()

unsigned int EFAElement::getCrackTipNeighbor ( unsigned int  index) const
inherited

Definition at line 140 of file EFAElement.C.

141 {
142  if (index < _crack_tip_neighbors.size())
143  return _crack_tip_neighbors[index];
144  else
145  EFAError("in getCrackTipNeighbor index out of bounds");
146 }
std::vector< unsigned int > _crack_tip_neighbors
Definition: EFAElement.h:34

◆ getCrackTipSplitElementID()

unsigned int EFAElement2D::getCrackTipSplitElementID ( ) const

Definition at line 599 of file EFAElement2D.C.

Referenced by XFEM::storeCrackTipOriginAndDirection().

600 {
601  if (isCrackTipElement())
602  {
603  for (unsigned int edge_iter = 0; edge_iter < _num_edges; ++edge_iter)
604  {
605  if ((_edge_neighbors[edge_iter].size() == 2) && (_edges[edge_iter]->hasIntersection()))
606  {
607  if (_edge_neighbors[edge_iter][0] != nullptr &&
608  _edge_neighbors[edge_iter][0]->isCrackTipSplit())
609  {
610  return _edge_neighbors[edge_iter][0]->id();
611  }
612  }
613  }
614  }
615  EFAError("In getCrackTipSplitElementID could not find element id");
616  return 0;
617 }
bool isCrackTipSplit() const
Definition: EFAElement.C:128
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
virtual bool isCrackTipElement() const
Definition: EFAElement2D.C:780
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ getEdge()

EFAEdge * EFAElement2D::getEdge ( unsigned int  edge_id) const

◆ getEdgeNeighbor()

EFAElement2D * EFAElement2D::getEdgeNeighbor ( unsigned int  edge_id,
unsigned int  neighbor_id 
) const

Definition at line 1577 of file EFAElement2D.C.

Referenced by addEdgeCut(), connectNeighbors(), XFEM::cutMeshWithEFA(), neighborSanityCheck(), and printElement().

1578 {
1579  if (_edge_neighbors[edge_id][0] != nullptr && neighbor_id < _edge_neighbors[edge_id].size())
1580  return _edge_neighbors[edge_id][neighbor_id];
1581  else
1582  EFAError("edge neighbor does not exist");
1583 }
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33

◆ getEdgeNodeParametricCoordinate()

bool EFAElement2D::getEdgeNodeParametricCoordinate ( EFANode node,
std::vector< double > &  para_coor 
) const

Definition at line 1411 of file EFAElement2D.C.

Referenced by addFragmentEdgeCut(), and branchingSplit().

1412 {
1413  // get the parametric coords of a node in an element edge
1414  unsigned int edge_id = std::numeric_limits<unsigned int>::max();
1415  bool edge_found = false;
1416  for (unsigned int i = 0; i < _num_edges; ++i)
1417  {
1418  if (_edges[i]->containsNode(node))
1419  {
1420  edge_id = i;
1421  edge_found = true;
1422  break;
1423  }
1424  }
1425  if (edge_found)
1426  {
1427  double rel_dist = _edges[edge_id]->distanceFromNode1(node);
1428  double xi_1d = 2.0 * rel_dist - 1.0; // translate to [-1,1] parent coord syst
1429  mapParametricCoordFrom1Dto2D(edge_id, xi_1d, para_coor);
1430  }
1431  return edge_found;
1432 }
void mapParametricCoordFrom1Dto2D(unsigned int edge_id, double xi_1d, std::vector< double > &para_coor) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ getEdgeNodes()

std::set< EFANode * > EFAElement2D::getEdgeNodes ( unsigned int  edge_id) const

Definition at line 1402 of file EFAElement2D.C.

Referenced by setupNeighbors(), and shouldDuplicateCrackTipSplitElement().

1403 {
1404  std::set<EFANode *> edge_nodes;
1405  edge_nodes.insert(_edges[edge_id]->getNode(0));
1406  edge_nodes.insert(_edges[edge_id]->getNode(1));
1407  return edge_nodes;
1408 }
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46

◆ getFragment()

EFAFragment2D * EFAElement2D::getFragment ( unsigned int  frag_id) const

◆ getFragmentEdge()

EFAEdge * EFAElement2D::getFragmentEdge ( unsigned int  frag_id,
unsigned int  edge_id 
) const

◆ getFragmentEdgeID()

bool EFAElement2D::getFragmentEdgeID ( unsigned int  elem_edge_id,
unsigned int frag_edge_id 
) const

Definition at line 1519 of file EFAElement2D.C.

Referenced by addEdgeCut(), and fragmentEdgeAlreadyCut().

1520 {
1521  // find the fragment edge that is contained by given element edge
1522  // N.B. if the elem edge contains two frag edges, this method will only return
1523  // the first frag edge ID
1524  bool frag_edge_found = false;
1525  frag_edge_id = std::numeric_limits<unsigned int>::max();
1526  if (_fragments.size() == 1)
1527  {
1528  for (unsigned int j = 0; j < _fragments[0]->numEdges(); ++j)
1529  {
1530  if (_edges[elem_edge_id]->containsEdge(*_fragments[0]->getEdge(j)))
1531  {
1532  frag_edge_id = j;
1533  frag_edge_found = true;
1534  break;
1535  }
1536  }
1537  }
1538  return frag_edge_found;
1539 }
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ getGeneralNeighbor()

EFAElement * EFAElement::getGeneralNeighbor ( unsigned int  index) const
inherited

Definition at line 230 of file EFAElement.C.

Referenced by switchNode(), and EFAElement3D::switchNode().

231 {
232  return _general_neighbors[index];
233 }
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36

◆ getGlobalNodeFromLocalNode()

EFANode * EFAElement::getGlobalNodeFromLocalNode ( const EFANode local_node) const
inherited

Definition at line 95 of file EFAElement.C.

96 {
97  // Given a local node, find the global node corresponding to that node
98  if (local_node->category() != EFANode::N_CATEGORY_LOCAL_INDEX)
99  EFAError("In getGlobalNodeFromLocalNode node passed in is not local");
100 
101  EFANode * global_node = _nodes[local_node->id()];
102 
103  if (global_node->category() != EFANode::N_CATEGORY_PERMANENT &&
104  global_node->category() != EFANode::N_CATEGORY_TEMP)
105  EFAError("In getGlobalNodeFromLocalNode, the node stored by the element is not global");
106 
107  return global_node;
108 }
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int id() const
Definition: EFANode.C:36
N_CATEGORY category() const
Definition: EFANode.C:42

◆ getInteriorNode()

EFAFaceNode * EFAElement2D::getInteriorNode ( unsigned int  interior_node_id) const

Definition at line 1435 of file EFAElement2D.C.

Referenced by EFAFragment2D::isSecondaryInteriorEdge().

1436 {
1437  if (interior_node_id < _interior_nodes.size())
1438  return _interior_nodes[interior_node_id];
1439  else
1440  EFAError("interior_node_id out of bounds");
1441 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32

◆ getLocalNodeIndex()

unsigned int EFAElement::getLocalNodeIndex ( EFANode node) const
inherited

Definition at line 111 of file EFAElement.C.

Referenced by XFEM::getEFANodeCoords().

112 {
113  for (unsigned int i = 0; i < _num_nodes; ++i)
114  {
115  if (_nodes[i] == node)
116  return i;
117  }
118  EFAError("In EFAelement::getLocalNodeIndex, cannot find the given node");
119 }
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28

◆ getMasterInfo()

void EFAElement2D::getMasterInfo ( EFANode node,
std::vector< EFANode *> &  master_nodes,
std::vector< double > &  master_weights 
) const
virtual

Implements EFAElement.

Definition at line 305 of file EFAElement2D.C.

Referenced by createChild(), and XFEMCutElem2D::getNodeCoordinates().

308 {
309  // Given a EFANode, find the element edge or fragment edge that contains it
310  // Return its master nodes and weights
311  master_nodes.clear();
312  master_weights.clear();
313  bool masters_found = false;
314  for (unsigned int i = 0; i < _num_edges; ++i) // check element exterior edges
315  {
316  if (_edges[i]->containsNode(node))
317  {
318  masters_found = _edges[i]->getNodeMasters(node, master_nodes, master_weights);
319  if (masters_found)
320  break;
321  else
322  EFAError("In getMasterInfo: cannot find master nodes in element edges");
323  }
324  }
325 
326  if (!masters_found) // check element interior embedded nodes
327  {
328  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
329  {
330  if (_interior_nodes[i]->getNode() == node)
331  {
332  std::vector<double> emb_xi(2, 0.0);
333  emb_xi[0] = _interior_nodes[i]->getParametricCoordinates(0);
334  emb_xi[1] = _interior_nodes[i]->getParametricCoordinates(1);
335  for (unsigned int j = 0; j < _num_edges; ++j)
336  {
337  master_nodes.push_back(_nodes[j]);
338  double weight = 0.0;
339  if (_num_edges == 4)
340  weight = Efa::linearQuadShape2D(j, emb_xi);
341  else if (_num_edges == 3)
342  weight = Efa::linearTriShape2D(j, emb_xi);
343  else
344  EFAError("unknown 2D element");
345  master_weights.push_back(weight);
346  }
347  masters_found = true;
348  break;
349  }
350  }
351  }
352 
353  if (!masters_found)
354  EFAError("In EFAelement2D::getMaterInfo, cannot find the given EFAnode");
355 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
dof_id_type weight(const MeshBase &mesh, const processor_id_type pid)
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
double linearQuadShape2D(unsigned int node_id, std::vector< double > &xi_2d)
Definition: EFAFuncs.C:16
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
double linearTriShape2D(unsigned int node_id, std::vector< double > &xi_2d)
Definition: EFAFuncs.C:23

◆ getNeighborIndex()

unsigned int EFAElement2D::getNeighborIndex ( const EFAElement neighbor_elem) const
virtual

Implements EFAElement.

Definition at line 452 of file EFAElement2D.C.

Referenced by addEdgeCut(), and connectNeighbors().

453 {
454  for (unsigned int i = 0; i < _num_edges; ++i)
455  for (unsigned int j = 0; j < _edge_neighbors[i].size(); ++j)
456  if (_edge_neighbors[i][j] == neighbor_elem)
457  return i;
458 
459  EFAError(
460  "in get_neighbor_index() element: ", _id, " does not have neighbor: ", neighbor_elem->id());
461 }
unsigned int id() const
Definition: EFAElement.C:28
unsigned int _id
Definition: EFAElement.h:27
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ getNode()

EFANode * EFAElement::getNode ( unsigned int  node_id) const
inherited

◆ getNodes()

const std::vector<EFANode *>& EFAElement::getNodes ( ) const
inlineinherited

Definition at line 44 of file EFAElement.h.

44 { return _nodes; }
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29

◆ getNonPhysicalNodes()

void EFAElement2D::getNonPhysicalNodes ( std::set< EFANode *> &  non_physical_nodes) const
virtual

Implements EFAElement.

Definition at line 240 of file EFAElement2D.C.

Referenced by shouldDuplicateCrackTipSplitElement().

241 {
242  // Any nodes that don't belong to any fragment are non-physical
243  // First add all nodes in the element to the set
244  for (unsigned int i = 0; i < _nodes.size(); ++i)
245  non_physical_nodes.insert(_nodes[i]);
246 
247  // Now delete any nodes that are contained in fragments
248  std::set<EFANode *>::iterator sit;
249  for (sit = non_physical_nodes.begin(); sit != non_physical_nodes.end();)
250  {
251  bool erased = false;
252  for (unsigned int i = 0; i < _fragments.size(); ++i)
253  {
254  if (_fragments[i]->containsNode(*sit))
255  {
256  non_physical_nodes.erase(sit++);
257  erased = true;
258  break;
259  }
260  }
261  if (!erased)
262  ++sit;
263  }
264 }
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ getNumCuts()

unsigned int EFAElement2D::getNumCuts ( ) const
virtual

Implements EFAElement.

Definition at line 786 of file EFAElement2D.C.

Referenced by restoreFragment().

787 {
788  unsigned int num_cuts = 0;
789  for (unsigned int i = 0; i < _num_edges; ++i)
790  if (_edges[i]->hasIntersection())
791  num_cuts += _edges[i]->numEmbeddedNodes();
792  return num_cuts;
793 }
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ getParent()

EFAElement * EFAElement::getParent ( ) const
inherited

Definition at line 168 of file EFAElement.C.

169 {
170  return _parent;
171 }
EFAElement * _parent
Definition: EFAElement.h:31

◆ getPhantomNodeOnEdge()

std::set< EFANode * > EFAElement2D::getPhantomNodeOnEdge ( unsigned int  edge_id) const

Definition at line 1495 of file EFAElement2D.C.

Referenced by shouldDuplicateForPhantomCorner().

1496 {
1497  std::set<EFANode *> phantom_nodes;
1498  if (_fragments.size() > 0)
1499  {
1500  for (unsigned int j = 0; j < 2; ++j) // loop ove 2 edge nodes
1501  {
1502  bool node_in_frag = false;
1503  for (unsigned int k = 0; k < _fragments.size(); ++k)
1504  {
1505  if (_fragments[k]->containsNode(_edges[edge_id]->getNode(j)))
1506  {
1507  node_in_frag = true;
1508  break;
1509  }
1510  }
1511  if (!node_in_frag)
1512  phantom_nodes.insert(_edges[edge_id]->getNode(j));
1513  }
1514  }
1515  return phantom_nodes;
1516 }
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:124
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ getTipEdgeID()

unsigned int EFAElement2D::getTipEdgeID ( ) const

Definition at line 1613 of file EFAElement2D.C.

Referenced by XFEM::markCutEdgesByState().

1614 {
1615  // if this element is a crack tip element, returns the crack tip edge's ID
1616  unsigned int tip_edge_id = std::numeric_limits<unsigned int>::max();
1617  if (_fragments.size() == 1) // crack tip element with a partial fragment saved
1618  {
1619  for (unsigned int i = 0; i < _num_edges; ++i)
1620  {
1621  unsigned int num_frag_edges = 0; // count how many fragment edges this element edge contains
1622  if (_edges[i]->hasIntersection())
1623  {
1624  for (unsigned int j = 0; j < _fragments[0]->numEdges(); ++j)
1625  {
1626  if (_edges[i]->containsEdge(*_fragments[0]->getEdge(j)))
1627  num_frag_edges += 1;
1628  }
1629  if (num_frag_edges == 2) // element edge contains two fragment edges
1630  {
1631  tip_edge_id = i;
1632  break;
1633  }
1634  }
1635  }
1636  }
1637  return tip_edge_id;
1638 }
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ getTipEmbeddedNode()

EFANode * EFAElement2D::getTipEmbeddedNode ( ) const

Definition at line 1641 of file EFAElement2D.C.

Referenced by XFEM::markCutEdgesByState(), and XFEM::storeCrackTipOriginAndDirection().

1642 {
1643  // if this element is a crack tip element, returns the crack tip edge's ID
1644  EFANode * tip_emb = nullptr;
1645  if (_fragments.size() == 1) // crack tip element with a partial fragment saved
1646  {
1647  for (unsigned int i = 0; i < _num_edges; ++i)
1648  {
1649  std::vector<EFAEdge *> frag_edges; // count how many fragment edges this element edge contains
1650  if (_edges[i]->hasIntersection())
1651  {
1652  for (unsigned int j = 0; j < _fragments[0]->numEdges(); ++j)
1653  {
1654  if (_edges[i]->containsEdge(*_fragments[0]->getEdge(j)))
1655  frag_edges.push_back(_fragments[0]->getEdge(j));
1656  } // j
1657  if (frag_edges.size() == 2) // element edge contains two fragment edges
1658  {
1659  if (frag_edges[1]->containsNode(frag_edges[0]->getNode(1)))
1660  tip_emb = frag_edges[0]->getNode(1);
1661  else if (frag_edges[1]->containsNode(frag_edges[0]->getNode(0)))
1662  tip_emb = frag_edges[0]->getNode(0);
1663  else
1664  EFAError("Common node can't be found between 2 tip frag edges");
1665  break;
1666  }
1667  }
1668  }
1669  }
1670  return tip_emb;
1671 }
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ id()

unsigned int EFAElement::id ( ) const
inherited

◆ initCrackTip()

void EFAElement2D::initCrackTip ( std::set< EFAElement *> &  CrackTipElements)
virtual

Implements EFAElement.

Definition at line 561 of file EFAElement2D.C.

562 {
563  if (isCrackTipElement())
564  {
565  CrackTipElements.insert(this);
566  for (unsigned int edge_iter = 0; edge_iter < _num_edges; ++edge_iter)
567  {
568  if ((_edge_neighbors[edge_iter].size() == 2) && (_edges[edge_iter]->hasIntersection()))
569  {
570  // Neither neighbor overlays current element. We are on the uncut element ahead of the tip.
571  // Flag neighbors as crack tip split elements and add this element as their crack tip
572  // neighbor.
573  if (_edge_neighbors[edge_iter][0]->overlaysElement(this) ||
574  _edge_neighbors[edge_iter][1]->overlaysElement(this))
575  EFAError("Element has a neighbor that overlays itself");
576 
577  // Make sure the current elment hasn't been flagged as a tip element
579  EFAError("crack_tip_split_element already flagged. In elem: ",
580  _id,
581  " flags: ",
583  " ",
584  _edge_neighbors[edge_iter][0]->isCrackTipSplit(),
585  " ",
586  _edge_neighbors[edge_iter][1]->isCrackTipSplit());
587 
588  _edge_neighbors[edge_iter][0]->setCrackTipSplit();
589  _edge_neighbors[edge_iter][1]->setCrackTipSplit();
590 
591  _edge_neighbors[edge_iter][0]->addCrackTipNeighbor(this);
592  _edge_neighbors[edge_iter][1]->addCrackTipNeighbor(this);
593  }
594  } // edge_iter
595  }
596 }
bool isCrackTipSplit() const
Definition: EFAElement.C:128
unsigned int _id
Definition: EFAElement.h:27
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
virtual bool isCrackTipElement() const
Definition: EFAElement2D.C:780
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool overlaysElement(const EFAElement2D *other_elem) const
Definition: EFAElement2D.C:364
unsigned int _num_edges
Definition: EFAElement2D.h:30
bool _crack_tip_split_element
Definition: EFAElement.h:33

◆ isCrackTipElement()

bool EFAElement2D::isCrackTipElement ( ) const
virtual

Implements EFAElement.

Definition at line 780 of file EFAElement2D.C.

Referenced by getCrackTipSplitElementID(), initCrackTip(), and shouldDuplicateForCrackTip().

781 {
782  return fragmentHasTipEdges();
783 }
bool fragmentHasTipEdges() const

◆ isCrackTipSplit()

bool EFAElement::isCrackTipSplit ( ) const
inherited

Definition at line 128 of file EFAElement.C.

Referenced by getCrackTipSplitElementID(), initCrackTip(), and EFAElement3D::initCrackTip().

129 {
131 }
bool _crack_tip_split_element
Definition: EFAElement.h:33

◆ isEdgePhantom()

bool EFAElement2D::isEdgePhantom ( unsigned int  edge_id) const

Definition at line 1542 of file EFAElement2D.C.

Referenced by XFEM::correctCrackExtensionDirection(), XFEM::markCutEdgesByGeometry(), and XFEM::markCutEdgesByState().

1543 {
1544  bool is_phantom = false;
1545  if (_fragments.size() > 0)
1546  {
1547  bool contain_frag_edge = false;
1548  for (unsigned int i = 0; i < _fragments.size(); ++i)
1549  {
1550  for (unsigned int j = 0; j < _fragments[i]->numEdges(); ++j)
1551  {
1552  if (_edges[edge_id]->containsEdge(*_fragments[i]->getEdge(j)))
1553  {
1554  contain_frag_edge = true;
1555  break;
1556  }
1557  } // j
1558  if (contain_frag_edge)
1559  break;
1560  } // i
1561  if (!contain_frag_edge)
1562  is_phantom = true;
1563  }
1564  return is_phantom;
1565 }
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ isFinalCut()

bool EFAElement2D::isFinalCut ( ) const
virtual

Implements EFAElement.

Definition at line 796 of file EFAElement2D.C.

Referenced by GeometricCutUserObject::execute(), and XFEM::markCutEdgesByState().

797 {
798  // if an element has been cut twice its fragment must have two interior edges
799  bool cut_twice = false;
800  if (_fragments.size() > 0)
801  {
802  unsigned int num_interior_edges = 0;
803  for (unsigned int i = 0; i < _fragments[0]->numEdges(); ++i)
804  {
805  if (_fragments[0]->isEdgeInterior(i))
806  num_interior_edges += 1;
807  }
808  if (num_interior_edges == 2)
809  cut_twice = true;
810  }
811  return cut_twice;
812 }
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ isPartial()

bool EFAElement2D::isPartial ( ) const
virtual

Implements EFAElement.

Definition at line 213 of file EFAElement2D.C.

Referenced by branchingSplit(), XFEMCutElem2D::computeMomentFittingWeights(), and updateFragments().

214 {
215  bool partial = false;
216  if (_fragments.size() > 0)
217  {
218  for (unsigned int i = 0; i < _num_edges; ++i)
219  {
220  bool node_in_frag = false;
221  for (unsigned int j = 0; j < _fragments.size(); ++j)
222  {
223  if (_fragments[j]->containsNode(_nodes[i]))
224  {
225  node_in_frag = true;
226  break;
227  }
228  } // j
229  if (!node_in_frag)
230  {
231  partial = true;
232  break;
233  }
234  } // i
235  }
236  return partial;
237 }
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ mapParametricCoordFrom1Dto2D()

void EFAElement2D::mapParametricCoordFrom1Dto2D ( unsigned int  edge_id,
double  xi_1d,
std::vector< double > &  para_coor 
) const
private

Definition at line 2012 of file EFAElement2D.C.

Referenced by getEdgeNodeParametricCoordinate().

2015 {
2016  para_coor.resize(2, 0.0);
2017  if (_num_edges == 4)
2018  {
2019  if (edge_id == 0)
2020  {
2021  para_coor[0] = xi_1d;
2022  para_coor[1] = -1.0;
2023  }
2024  else if (edge_id == 1)
2025  {
2026  para_coor[0] = 1.0;
2027  para_coor[1] = xi_1d;
2028  }
2029  else if (edge_id == 2)
2030  {
2031  para_coor[0] = -xi_1d;
2032  para_coor[1] = 1.0;
2033  }
2034  else if (edge_id == 3)
2035  {
2036  para_coor[0] = -1.0;
2037  para_coor[1] = -xi_1d;
2038  }
2039  else
2040  EFAError("edge_id out of bounds");
2041  }
2042  else if (_num_edges == 3)
2043  {
2044  if (edge_id == 0)
2045  {
2046  para_coor[0] = 0.5 * (1.0 - xi_1d);
2047  para_coor[1] = 0.5 * (1.0 + xi_1d);
2048  }
2049  else if (edge_id == 1)
2050  {
2051  para_coor[0] = 0.0;
2052  para_coor[1] = 0.5 * (1.0 - xi_1d);
2053  }
2054  else if (edge_id == 2)
2055  {
2056  para_coor[0] = 0.5 * (1.0 + xi_1d);
2057  para_coor[1] = 0.0;
2058  }
2059  else
2060  EFAError("edge_id out of bounds");
2061  }
2062  else
2063  EFAError("unknown element for 2D");
2064 }
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ mergeNodes()

void EFAElement::mergeNodes ( EFANode *&  childNode,
EFANode *&  childOfNeighborNode,
EFAElement childOfNeighborElem,
std::map< unsigned int, EFANode *> &  PermanentNodes,
std::map< unsigned int, EFANode *> &  TempNodes 
)
protectedinherited

Definition at line 242 of file EFAElement.C.

Referenced by connectNeighbors(), and EFAElement3D::connectNeighbors().

247 {
248  // Important: this must be run only on child elements that were just created
249  if (!_parent)
250  EFAError("no getParent element for child element ", _id, " in mergeNodes");
251 
252  EFAElement * childElem = this;
253  if (childNode != childOfNeighborNode)
254  {
255  if (childNode->category() == EFANode::N_CATEGORY_PERMANENT)
256  {
257  if (childOfNeighborNode->category() == EFANode::N_CATEGORY_PERMANENT)
258  {
259  if (childOfNeighborNode->parent() == childNode) // merge into childNode
260  {
261  childOfNeighborElem->switchNode(childNode, childOfNeighborNode, true);
262  if (!Efa::deleteFromMap(PermanentNodes, childOfNeighborNode))
263  {
264  EFAError("Attempted to delete node: ",
265  childOfNeighborNode->id(),
266  " from PermanentNodes, but couldn't find it");
267  }
268  childOfNeighborNode = childNode;
269  }
270  else if (childNode->parent() == childOfNeighborNode) // merge into childOfNeighborNode
271  {
272  childElem->switchNode(childOfNeighborNode, childNode, true);
273  if (!Efa::deleteFromMap(PermanentNodes, childNode))
274  {
275  EFAError("Attempted to delete node: ",
276  childNode->id(),
277  " from PermanentNodes, but couldn't find it");
278  }
279  childNode = childOfNeighborNode;
280  }
281  else if (childNode->parent() != nullptr &&
282  childNode->parent() == childOfNeighborNode->parent())
283  {
284  // merge into childNode if both nodes are child permanent
285  childOfNeighborElem->switchNode(childNode, childOfNeighborNode, true);
286  if (!Efa::deleteFromMap(PermanentNodes,
287  childOfNeighborNode)) // delete childOfNeighborNode
288  {
289  EFAError("Attempted to delete node: ",
290  childOfNeighborNode->id(),
291  " from PermanentNodes, but couldn't find it");
292  }
293  childOfNeighborNode = childNode;
294  }
295  else
296  {
297  EFAError("Attempting to merge nodes: ",
298  childNode->id(),
299  " and ",
300  childOfNeighborNode->id(),
301  " but both are permanent themselves");
302  }
303  }
304  else
305  {
306  if (childOfNeighborNode->parent() != childNode &&
307  childOfNeighborNode->parent() != childNode->parent())
308  {
309  EFAError("Attempting to merge nodes ",
310  childOfNeighborNode->idCatString(),
311  " and ",
312  childNode->idCatString(),
313  " but neither the 2nd node nor its parent is parent of the 1st");
314  }
315  childOfNeighborElem->switchNode(childNode, childOfNeighborNode, true);
316  if (!Efa::deleteFromMap(TempNodes, childOfNeighborNode))
317  EFAError("Attempted to delete node: ",
318  childOfNeighborNode->id(),
319  " from TempNodes, but couldn't find it");
320  childOfNeighborNode = childNode;
321  }
322  }
323  else if (childOfNeighborNode->category() == EFANode::N_CATEGORY_PERMANENT)
324  {
325  if (childNode->parent() != childOfNeighborNode &&
326  childNode->parent() != childOfNeighborNode->parent())
327  {
328  EFAError("Attempting to merge nodes ",
329  childNode->id(),
330  " and ",
331  childOfNeighborNode->id(),
332  " but neither the 2nd node nor its parent is parent of the 1st");
333  }
334  childElem->switchNode(childOfNeighborNode, childNode, true);
335  if (!Efa::deleteFromMap(TempNodes, childNode))
336  EFAError(
337  "Attempted to delete node: ", childNode->id(), " from TempNodes, but couldn't find it");
338  childNode = childOfNeighborNode;
339  }
340  else // both nodes are temporary -- create new permanent node and delete temporary nodes
341  {
342  unsigned int new_node_id = Efa::getNewID(PermanentNodes);
343  EFANode * newNode =
344  new EFANode(new_node_id, EFANode::N_CATEGORY_PERMANENT, childNode->parent());
345  PermanentNodes.insert(std::make_pair(new_node_id, newNode));
346 
347  childOfNeighborElem->switchNode(newNode, childOfNeighborNode, true);
348  childElem->switchNode(newNode, childNode, true);
349 
350  if (childNode->parent() != childOfNeighborNode->parent())
351  {
352  EFAError("Attempting to merge nodes ",
353  childNode->id(),
354  " and ",
355  childOfNeighborNode->id(),
356  " but they don't share a common parent");
357  }
358 
359  if (!Efa::deleteFromMap(TempNodes, childOfNeighborNode))
360  EFAError("Attempted to delete node: ",
361  childOfNeighborNode->id(),
362  " from TempNodes, but couldn't find it");
363  if (!Efa::deleteFromMap(TempNodes, childNode))
364  EFAError(
365  "Attempted to delete node: ", childNode->id(), " from TempNodes, but couldn't find it");
366  childOfNeighborNode = newNode;
367  childNode = newNode;
368  }
369  }
370 }
unsigned int getNewID(std::map< unsigned int, T *> &theMap)
Definition: EFAFuncs.h:38
unsigned int _id
Definition: EFAElement.h:27
std::string idCatString()
Definition: EFANode.C:20
bool deleteFromMap(std::map< unsigned int, T *> &theMap, T *elemToDelete, bool delete_elem=true)
Definition: EFAFuncs.h:22
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)=0
EFAElement * _parent
Definition: EFAElement.h:31
EFANode * parent() const
Definition: EFANode.C:48
unsigned int id() const
Definition: EFANode.C:36
N_CATEGORY category() const
Definition: EFANode.C:42

◆ neighborSanityCheck()

void EFAElement2D::neighborSanityCheck ( ) const
virtual

Implements EFAElement.

Definition at line 528 of file EFAElement2D.C.

529 {
530  for (unsigned int edge_iter = 0; edge_iter < _num_edges; ++edge_iter)
531  {
532  for (unsigned int en_iter = 0; en_iter < _edge_neighbors[edge_iter].size(); ++en_iter)
533  {
534  EFAElement2D * neigh_elem = _edge_neighbors[edge_iter][en_iter];
535  if (neigh_elem != nullptr)
536  {
537  bool found_neighbor = false;
538  for (unsigned int edge_iter2 = 0; edge_iter2 < neigh_elem->numEdges(); ++edge_iter2)
539  {
540  for (unsigned int en_iter2 = 0; en_iter2 < neigh_elem->numEdgeNeighbors(edge_iter2);
541  ++en_iter2)
542  {
543  if (neigh_elem->getEdgeNeighbor(edge_iter2, en_iter2) == this)
544  {
545  if ((en_iter2 > 1) && (en_iter > 1))
546  EFAError(
547  "Element and neighbor element cannot both have >1 neighbors on a common edge");
548  found_neighbor = true;
549  break;
550  }
551  }
552  }
553  if (!found_neighbor)
554  EFAError("Neighbor element doesn't recognize current element as neighbor");
555  }
556  }
557  }
558 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
unsigned int numEdges() const
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ numChildren()

unsigned int EFAElement::numChildren ( ) const
inherited

Definition at line 189 of file EFAElement.C.

Referenced by connectNeighbors(), EFAElement3D::connectNeighbors(), switchNode(), and EFAElement3D::switchNode().

190 {
191  return _children.size();
192 }
std::vector< EFAElement * > _children
Definition: EFAElement.h:32

◆ numCrackTipNeighbors()

unsigned int EFAElement::numCrackTipNeighbors ( ) const
inherited

Definition at line 134 of file EFAElement.C.

135 {
136  return _crack_tip_neighbors.size();
137 }
std::vector< unsigned int > _crack_tip_neighbors
Definition: EFAElement.h:34

◆ numEdgeNeighbors()

unsigned int EFAElement2D::numEdgeNeighbors ( unsigned int  edge_id) const

Definition at line 1568 of file EFAElement2D.C.

Referenced by addEdgeCut(), connectNeighbors(), XFEM::cutMeshWithEFA(), neighborSanityCheck(), printElement(), shouldDuplicateCrackTipSplitElement(), shouldDuplicateForPhantomCorner(), and willCrackTipExtend().

1569 {
1570  unsigned int num_neighbors = 0;
1571  if (_edge_neighbors[edge_id][0])
1572  num_neighbors = _edge_neighbors[edge_id].size();
1573  return num_neighbors;
1574 }
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33

◆ numEdges()

unsigned int EFAElement2D::numEdges ( ) const

◆ numFragments()

unsigned int EFAElement2D::numFragments ( ) const
virtual

◆ numGeneralNeighbors()

unsigned int EFAElement::numGeneralNeighbors ( ) const
inherited

Definition at line 236 of file EFAElement.C.

Referenced by switchNode(), and EFAElement3D::switchNode().

237 {
238  return _general_neighbors.size();
239 }
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36

◆ numInteriorNodes()

unsigned int EFAElement2D::numInteriorNodes ( ) const
virtual

Implements EFAElement.

Definition at line 358 of file EFAElement2D.C.

Referenced by fragmentSanityCheck(), EFAFragment2D::isSecondaryInteriorEdge(), and EFAFragment2D::removeInvalidEmbeddedNodes().

359 {
360  return _interior_nodes.size();
361 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32

◆ numNodes()

unsigned int EFAElement::numNodes ( ) const
inherited

◆ overlaysElement()

bool EFAElement2D::overlaysElement ( const EFAElement2D other_elem) const

Definition at line 364 of file EFAElement2D.C.

Referenced by initCrackTip(), and setupNeighbors().

365 {
366  bool overlays = false;
367 
368  if (other_elem->numEdges() != _num_edges)
369  return overlays;
370 
371  std::vector<EFANode *> common_nodes = getCommonNodes(other_elem);
372 
373  // Find indices of common nodes
374  if (common_nodes.size() == 2)
375  {
376  std::vector<EFANode *> common_nodes_vec(common_nodes.begin(), common_nodes.end());
377 
378  unsigned int e1n1idx = _num_edges + 1;
379  unsigned int e1n2idx = _num_edges + 1;
380  for (unsigned int i = 0; i < _num_edges; ++i)
381  {
382  if (_nodes[i] == common_nodes_vec[0])
383  {
384  e1n1idx = i;
385  }
386  else if (_nodes[i] == common_nodes_vec[1])
387  {
388  e1n2idx = i;
389  }
390  }
391 
392  if (e1n1idx > _num_edges || e1n2idx > _num_edges)
393  EFAError("in overlays_elem() couldn't find common node");
394 
395  bool e1ascend = false;
396  unsigned int e1n1idx_plus1(e1n1idx < (_num_edges - 1) ? e1n1idx + 1 : 0);
397  unsigned int e1n1idx_minus1(e1n1idx > 0 ? e1n1idx - 1 : _num_edges - 1);
398  if (e1n2idx == e1n1idx_plus1)
399  {
400  e1ascend = true;
401  }
402  else
403  {
404  if (e1n2idx != e1n1idx_minus1)
405  EFAError("in overlays_elem() common nodes must be adjacent to each other");
406  }
407 
408  unsigned int e2n1idx = _num_edges + 1;
409  unsigned int e2n2idx = _num_edges + 1;
410  for (unsigned int i = 0; i < _num_edges; ++i)
411  {
412  if (other_elem->getNode(i) == common_nodes_vec[0])
413  {
414  e2n1idx = i;
415  }
416  else if (other_elem->getNode(i) == common_nodes_vec[1])
417  {
418  e2n2idx = i;
419  }
420  }
421  if (e2n1idx > other_elem->numNodes() || e2n2idx > other_elem->numNodes())
422  EFAError("in overlays_elem() couldn't find common node");
423 
424  bool e2ascend = false;
425  unsigned int e2n1idx_plus1(e2n1idx < (_num_edges - 1) ? e2n1idx + 1 : 0);
426  unsigned int e2n1idx_minus1(e2n1idx > 0 ? e2n1idx - 1 : _num_edges - 1);
427  if (e2n2idx == e2n1idx_plus1)
428  {
429  e2ascend = true;
430  }
431  else
432  {
433  if (e2n2idx != e2n1idx_minus1)
434  EFAError("in overlays_elem() common nodes must be adjacent to each other");
435  }
436 
437  // if indices both ascend or descend, they overlay
438  if ((e1ascend && e2ascend) || (!e1ascend && !e2ascend))
439  {
440  overlays = true;
441  }
442  }
443  else if (common_nodes.size() > 2)
444  {
445  // TODO: We probably need more error checking here.
446  overlays = true;
447  }
448  return overlays;
449 }
std::vector< EFANode * > getCommonNodes(const EFAElement2D *other_elem) const
unsigned int numEdges() const
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
unsigned int _num_edges
Definition: EFAElement2D.h:30
unsigned int numNodes() const
Definition: EFAElement.C:34

◆ printElement()

void EFAElement2D::printElement ( std::ostream &  ostream) const
virtual

Implements EFAElement.

Definition at line 1317 of file EFAElement2D.C.

1318 {
1319  ostream << std::setw(4);
1320  ostream << _id << " | ";
1321  for (unsigned int j = 0; j < _num_nodes; ++j)
1322  {
1323  ostream << std::setw(5) << _nodes[j]->idCatString();
1324  }
1325 
1326  ostream << " | ";
1327  for (unsigned int j = 0; j < _num_edges; ++j)
1328  {
1329  ostream << std::setw(4);
1330  if (_edges[j]->hasIntersection())
1331  {
1332  if (_edges[j]->numEmbeddedNodes() > 1)
1333  {
1334  ostream << "[";
1335  for (unsigned int k = 0; k < _edges[j]->numEmbeddedNodes(); ++k)
1336  {
1337  ostream << _edges[j]->getEmbeddedNode(k)->id();
1338  if (k == _edges[j]->numEmbeddedNodes() - 1)
1339  ostream << "]";
1340  else
1341  ostream << " ";
1342  }
1343  }
1344  else
1345  ostream << _edges[j]->getEmbeddedNode(0)->id() << " ";
1346  }
1347  else
1348  ostream << " -- ";
1349  }
1350  ostream << " | ";
1351  for (unsigned int j = 0; j < _num_edges; ++j)
1352  {
1353  if (numEdgeNeighbors(j) > 1)
1354  {
1355  ostream << "[";
1356  for (unsigned int k = 0; k < numEdgeNeighbors(j); ++k)
1357  {
1358  ostream << getEdgeNeighbor(j, k)->id();
1359  if (k == numEdgeNeighbors(j) - 1)
1360  ostream << "]";
1361  else
1362  ostream << " ";
1363  }
1364  ostream << " ";
1365  }
1366  else
1367  {
1368  ostream << std::setw(4);
1369  if (numEdgeNeighbors(j) == 1)
1370  ostream << getEdgeNeighbor(j, 0)->id() << " ";
1371  else
1372  ostream << " -- ";
1373  }
1374  }
1375  ostream << " | ";
1376  for (unsigned int j = 0; j < _fragments.size(); ++j)
1377  {
1378  ostream << std::setw(4);
1379  ostream << " " << j << " | ";
1380  for (unsigned int k = 0; k < _fragments[j]->numEdges(); ++k)
1381  {
1382  EFANode * prt_node = getFragmentEdge(j, k)->getNode(0);
1383  unsigned int kprev(k > 0 ? k - 1 : _fragments[j]->numEdges() - 1);
1384  if (!getFragmentEdge(j, kprev)->containsNode(prt_node))
1385  prt_node = getFragmentEdge(j, k)->getNode(1);
1386  ostream << std::setw(5) << prt_node->idCatString();
1387  }
1388  }
1389  ostream << std::endl;
1390 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
unsigned int id() const
Definition: EFAElement.C:28
unsigned int _id
Definition: EFAElement.h:27
std::string idCatString()
Definition: EFANode.C:20
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
unsigned int numEdges() const
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
static const std::string k
Definition: NS.h:124
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ printNodes()

void EFAElement::printNodes ( std::ostream &  ostream) const
inherited

Definition at line 61 of file EFAElement.C.

62 {
63  ostream << "***** nodes for element " << _id << " *****" << std::endl;
64  for (unsigned int i = 0; i < _num_nodes; ++i)
65  ostream << "addr " << _nodes[i] << ", ID " << _nodes[i]->idCatString() << ", category "
66  << _nodes[i]->category() << std::endl;
67 }
unsigned int _id
Definition: EFAElement.h:27
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28

◆ removePhantomEmbeddedNode()

void EFAElement2D::removePhantomEmbeddedNode ( )
virtual

Implements EFAElement.

Definition at line 1156 of file EFAElement2D.C.

Referenced by createChild().

1157 {
1158  // remove the embedded nodes on edge that are not inside the real part
1159  if (_fragments.size() > 0)
1160  {
1161  for (unsigned int i = 0; i < _num_edges; ++i)
1162  {
1163  std::vector<EFANode *> nodes_to_delete;
1164  for (unsigned int j = 0; j < _edges[i]->numEmbeddedNodes(); ++j)
1165  {
1166  if (!_fragments[0]->containsNode(_edges[i]->getEmbeddedNode(j)))
1167  nodes_to_delete.push_back(_edges[i]->getEmbeddedNode(j));
1168  }
1169  for (unsigned int j = 0; j < nodes_to_delete.size(); ++j)
1170  _edges[i]->removeEmbeddedNode(nodes_to_delete[j]);
1171  } // i
1172  }
1173 }
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ restoreFragment()

void EFAElement2D::restoreFragment ( const EFAElement *const  from_elem)
virtual

Implements EFAElement.

Definition at line 949 of file EFAElement2D.C.

950 {
951  const EFAElement2D * from_elem2d = dynamic_cast<const EFAElement2D *>(from_elem);
952  if (!from_elem2d)
953  EFAError("from_elem is not of EFAelement2D type");
954 
955  // restore fragments
956  if (_fragments.size() != 0)
957  EFAError("in restoreFragmentInfo elements must not have any pre-existing fragments");
958  for (unsigned int i = 0; i < from_elem2d->numFragments(); ++i)
959  _fragments.push_back(new EFAFragment2D(this, true, from_elem2d, i));
960 
961  // restore interior nodes
962  if (_interior_nodes.size() != 0)
963  EFAError("in restoreFragmentInfo elements must not have any pre-exsiting interior nodes");
964  for (unsigned int i = 0; i < from_elem2d->_interior_nodes.size(); ++i)
965  _interior_nodes.push_back(new EFAFaceNode(*from_elem2d->_interior_nodes[i]));
966 
967  // restore edge intersections
968  if (getNumCuts() != 0)
969  EFAError("In restoreEdgeIntersection: edge cuts already exist in element ", _id);
970  for (unsigned int i = 0; i < _num_edges; ++i)
971  {
972  if (from_elem2d->_edges[i]->hasIntersection())
973  _edges[i]->copyIntersection(*from_elem2d->_edges[i], 0);
974  if (_edges[i]->numEmbeddedNodes() > 2)
975  EFAError("elem ", _id, " has an edge with >2 cuts");
976  }
977 
978  // replace all local nodes with global nodes
979  for (unsigned int i = 0; i < from_elem2d->numNodes(); ++i)
980  {
981  if (from_elem2d->_nodes[i]->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
982  switchNode(
983  _nodes[i], from_elem2d->_nodes[i], false); // EFAelement is not a child of any parent
984  else
985  EFAError("In restoreFragmentInfo all of from_elem's nodes must be local");
986  }
987 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
unsigned int _id
Definition: EFAElement.h:27
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement2D.C:267
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
virtual unsigned int getNumCuts() const
Definition: EFAElement2D.C:786
unsigned int _num_edges
Definition: EFAElement2D.h:30
unsigned int numNodes() const
Definition: EFAElement.C:34
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ setCrackTipSplit()

void EFAElement::setCrackTipSplit ( )
inherited

Definition at line 122 of file EFAElement.C.

123 {
125 }
bool _crack_tip_split_element
Definition: EFAElement.h:33

◆ setEdge()

void EFAElement2D::setEdge ( unsigned int  edge_id,
EFAEdge edge 
)

Definition at line 1458 of file EFAElement2D.C.

Referenced by createChild().

1459 {
1460  _edges[edge_id] = edge;
1461 }
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31

◆ setLocalCoordinates()

void EFAElement2D::setLocalCoordinates ( )
private

Definition at line 141 of file EFAElement2D.C.

Referenced by EFAElement2D().

142 {
143  if (_num_edges == 4)
144  {
145  /*
146  3 6 2
147  QUAD9(QUAD8): o-----o-----o
148  | |
149  | 8 |
150  7 o o o 5
151  | |
152  | |
153  o-----o-----o
154  0 4 1
155 
156  */
158  _local_node_coor[0] = EFAPoint(0.0, 0.0, 0.0);
159  _local_node_coor[1] = EFAPoint(1.0, 0.0, 0.0);
160  _local_node_coor[2] = EFAPoint(1.0, 1.0, 0.0);
161  _local_node_coor[3] = EFAPoint(0.0, 1.0, 0.0);
162 
163  if (_num_nodes > 4)
164  {
165  _local_node_coor[4] = EFAPoint(0.5, 0.0, 0.0);
166  _local_node_coor[5] = EFAPoint(1.0, 0.5, 0.0);
167  _local_node_coor[6] = EFAPoint(0.5, 1.0, 0.0);
168  _local_node_coor[7] = EFAPoint(0.0, 0.5, 0.0);
169  }
170 
171  if (_num_nodes > 8)
172  _local_node_coor[8] = EFAPoint(0.5, 0.5, 0.0);
173  }
174  else
175  {
176  /*
177  TRI7: 2
178  o
179  | \
180  | \
181  5 o o 4
182  | o \
183  | 6 \
184  o-----o-----o
185  0 3 1
186  */
188  _local_node_coor[0] = EFAPoint(0.0, 0.0, 0.0);
189  _local_node_coor[1] = EFAPoint(1.0, 0.0, 0.0);
190  _local_node_coor[2] = EFAPoint(0.0, 1.0, 0.0);
191 
192  if (_num_nodes > 3)
193  {
194  _local_node_coor[3] = EFAPoint(0.5, 0.0, 0.0);
195  _local_node_coor[4] = EFAPoint(0.5, 0.5, 0.0);
196  _local_node_coor[5] = EFAPoint(0.0, 0.5, 0.0);
197  }
198 
199  if (_num_nodes > 6)
200  {
201  _local_node_coor[6] = EFAPoint(1 / 3., 1 / 3., 0.0);
202  }
203  }
204 }
unsigned int _num_nodes
Definition: EFAElement.h:28
std::vector< EFAPoint > _local_node_coor
Definition: EFAElement2D.h:35
unsigned int _num_edges
Definition: EFAElement2D.h:30

◆ setNode()

void EFAElement::setNode ( unsigned int  node_id,
EFANode node 
)
inherited

◆ setParent()

void EFAElement::setParent ( EFAElement parent)
inherited

Definition at line 183 of file EFAElement.C.

Referenced by createChild(), and EFAElement3D::createChild().

184 {
185  _parent = parent;
186 }
EFAElement * _parent
Definition: EFAElement.h:31

◆ setupNeighbors()

void EFAElement2D::setupNeighbors ( std::map< EFANode *, std::set< EFAElement *>> &  InverseConnectivityMap)
virtual

Implements EFAElement.

Definition at line 472 of file EFAElement2D.C.

473 {
474  findGeneralNeighbors(inverse_connectivity_map);
475  for (unsigned int eit2 = 0; eit2 < _general_neighbors.size(); ++eit2)
476  {
477  EFAElement2D * neigh_elem = dynamic_cast<EFAElement2D *>(_general_neighbors[eit2]);
478  if (!neigh_elem)
479  EFAError("neighbor_elem is not of EFAelement2D type");
480 
481  std::vector<EFANode *> common_nodes = getCommonNodes(neigh_elem);
482  if (common_nodes.size() >= 2)
483  {
484  for (unsigned int edge_iter = 0; edge_iter < _num_edges; ++edge_iter)
485  {
486  std::set<EFANode *> edge_nodes = getEdgeNodes(edge_iter);
487  bool is_edge_neighbor = false;
488 
489  // Must share nodes on this edge
490  if (Efa::numCommonElems(edge_nodes, common_nodes) == 2 && (!overlaysElement(neigh_elem)))
491  {
492  // Fragments must match up.
493  if ((_fragments.size() > 1) || (neigh_elem->numFragments() > 1))
494  EFAError("in updateEdgeNeighbors: Cannot have more than 1 fragment");
495  else if ((_fragments.size() == 1) && (neigh_elem->numFragments() == 1))
496  {
497  if (_fragments[0]->isConnected(neigh_elem->getFragment(0)))
498  is_edge_neighbor = true;
499  }
500  else // If there are no fragments to match up, consider them neighbors
501  is_edge_neighbor = true;
502  }
503 
504  if (is_edge_neighbor)
505  {
506  if (_edge_neighbors[edge_iter][0])
507  {
508  if (_edge_neighbors[edge_iter].size() > 1)
509  {
510  EFAError("Element ",
511  _id,
512  " already has 2 edge neighbors: ",
513  _edge_neighbors[edge_iter][0]->id(),
514  " ",
515  _edge_neighbors[edge_iter][1]->id());
516  }
517  _edge_neighbors[edge_iter].push_back(neigh_elem);
518  }
519  else
520  _edge_neighbors[edge_iter][0] = neigh_elem;
521  }
522  }
523  }
524  }
525 }
std::vector< EFANode * > getCommonNodes(const EFAElement2D *other_elem) const
unsigned int _id
Definition: EFAElement.h:27
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
EFAFragment2D * getFragment(unsigned int frag_id) const
void findGeneralNeighbors(const std::map< EFANode *, std::set< EFAElement *>> &InverseConnectivity)
Definition: EFAElement.C:208
std::set< EFANode * > getEdgeNodes(unsigned int edge_id) const
unsigned int numCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:49
bool overlaysElement(const EFAElement2D *other_elem) const
Definition: EFAElement2D.C:364
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ shouldDuplicateCrackTipSplitElement()

bool EFAElement2D::shouldDuplicateCrackTipSplitElement ( const std::set< EFAElement *> &  CrackTipElements)
virtual

Implements EFAElement.

Definition at line 644 of file EFAElement2D.C.

Referenced by shouldDuplicateForCrackTip().

645 {
646  // Determine whether element at crack tip should be duplicated. It should be duplicated
647  // if the crack will extend into the next element, or if it has a non-physical node
648  // connected to a face where a crack terminates, but will extend.
649 
650  bool should_duplicate = false;
651  if (_fragments.size() == 1)
652  {
653  std::vector<unsigned int> split_neighbors;
654  if (willCrackTipExtend(split_neighbors))
655  should_duplicate = true;
656  else
657  {
658  // The element may not be at the crack tip, but could have a non-physical node
659  // connected to a crack tip face (on a neighbor element) that will be split. We need to
660  // duplicate in that case as well.
661  std::set<EFANode *> non_physical_nodes;
662  getNonPhysicalNodes(non_physical_nodes);
663 
664  for (unsigned int eit = 0; eit < _general_neighbors.size(); ++eit)
665  {
666  EFAElement2D * neigh_elem = dynamic_cast<EFAElement2D *>(_general_neighbors[eit]);
667  if (!neigh_elem)
668  EFAError("general elem is not of type EFAelement2D");
669 
670  // check if a general neighbor is an old crack tip element and will be split
671  std::set<EFAElement *>::iterator sit;
672  sit = CrackTipElements.find(neigh_elem);
673  if (sit != CrackTipElements.end() && neigh_elem->numFragments() > 1)
674  {
675  for (unsigned int i = 0; i < neigh_elem->numEdges(); ++i)
676  {
677  std::set<EFANode *> neigh_edge_nodes = neigh_elem->getEdgeNodes(i);
678  if (neigh_elem->numEdgeNeighbors(i) == 2 &&
679  Efa::numCommonElems(neigh_edge_nodes, non_physical_nodes) > 0)
680  {
681  should_duplicate = true;
682  break;
683  }
684  } // i
685  }
686  if (should_duplicate)
687  break;
688  } // eit
689  }
690  } // IF one fragment
691  return should_duplicate;
692 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
virtual void getNonPhysicalNodes(std::set< EFANode *> &non_physical_nodes) const
Definition: EFAElement2D.C:240
unsigned int numEdges() const
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
std::set< EFANode * > getEdgeNodes(unsigned int edge_id) const
unsigned int numCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:49
virtual bool willCrackTipExtend(std::vector< unsigned int > &split_neighbors) const
Definition: EFAElement2D.C:734
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ shouldDuplicateForCrackTip()

bool EFAElement2D::shouldDuplicateForCrackTip ( const std::set< EFAElement *> &  CrackTipElements)
virtual

Implements EFAElement.

Definition at line 620 of file EFAElement2D.C.

Referenced by createChild().

621 {
622  // This method is called in createChildElements()
623  // Only duplicate when
624  // 1) currElem will be a NEW crack tip element
625  // 2) currElem is a crack tip split element at last time step and the tip will extend
626  // 3) currElem is the neighbor of a to-be-second-split element which has another neighbor
627  // sharing a phantom node with currElem
628  bool should_duplicate = false;
629  if (_fragments.size() == 1)
630  {
631  std::set<EFAElement *>::iterator sit;
632  sit = CrackTipElements.find(this);
633  if (sit == CrackTipElements.end() && isCrackTipElement())
634  should_duplicate = true;
635  else if (shouldDuplicateCrackTipSplitElement(CrackTipElements))
636  should_duplicate = true;
638  should_duplicate = true;
639  }
640  return should_duplicate;
641 }
virtual bool shouldDuplicateForPhantomCorner()
Definition: EFAElement2D.C:695
virtual bool isCrackTipElement() const
Definition: EFAElement2D.C:780
virtual bool shouldDuplicateCrackTipSplitElement(const std::set< EFAElement *> &CrackTipElements)
Definition: EFAElement2D.C:644
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ shouldDuplicateForPhantomCorner()

bool EFAElement2D::shouldDuplicateForPhantomCorner ( )
virtual

Implements EFAElement.

Definition at line 695 of file EFAElement2D.C.

Referenced by shouldDuplicateForCrackTip().

696 {
697  // if a partial element will be split for a second time and it has two neighbor elements
698  // sharing one phantom node with the aforementioned partial element, then the two neighbor
699  // elements should be duplicated
700  bool should_duplicate = false;
701  if (_fragments.size() == 1 && (!_crack_tip_split_element))
702  {
703  for (unsigned int i = 0; i < _num_edges; ++i)
704  {
705  std::set<EFANode *> phantom_nodes = getPhantomNodeOnEdge(i);
706  if (phantom_nodes.size() > 0 && numEdgeNeighbors(i) == 1)
707  {
708  EFAElement2D * neighbor_elem = _edge_neighbors[i][0];
709  if (neighbor_elem->numFragments() > 1) // neighbor will be split
710  {
711  for (unsigned int j = 0; j < neighbor_elem->numEdges(); ++j)
712  {
713  if (!neighbor_elem->getEdge(j)->equivalent(*_edges[i]) &&
714  neighbor_elem->numEdgeNeighbors(j) > 0)
715  {
716  std::set<EFANode *> neigh_phantom_nodes = neighbor_elem->getPhantomNodeOnEdge(j);
717  if (Efa::numCommonElems(phantom_nodes, neigh_phantom_nodes) > 0)
718  {
719  should_duplicate = true;
720  break;
721  }
722  }
723  } // j
724  }
725  }
726  if (should_duplicate)
727  break;
728  } // i
729  }
730  return should_duplicate;
731 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
EFAEdge * getEdge(unsigned int edge_id) const
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
unsigned int numEdges() const
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
unsigned int numCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:49
bool equivalent(const EFAEdge &other) const
Definition: EFAEdge.C:38
std::set< EFANode * > getPhantomNodeOnEdge(unsigned int edge_id) const
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_edges
Definition: EFAElement2D.h:30
bool _crack_tip_split_element
Definition: EFAElement.h:33
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ switchEmbeddedNode()

void EFAElement2D::switchEmbeddedNode ( EFANode new_node,
EFANode old_node 
)
virtual

Implements EFAElement.

Definition at line 294 of file EFAElement2D.C.

295 {
296  for (unsigned int i = 0; i < _num_edges; ++i)
297  _edges[i]->switchNode(new_emb_node, old_emb_node);
298  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
299  _interior_nodes[i]->switchNode(new_emb_node, old_emb_node);
300  for (unsigned int i = 0; i < _fragments.size(); ++i)
301  _fragments[i]->switchNode(new_emb_node, old_emb_node);
302 }
std::vector< EFAFaceNode * > _interior_nodes
Definition: EFAElement2D.h:32
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement2D.C:267
unsigned int _num_edges
Definition: EFAElement2D.h:30
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ switchNode()

void EFAElement2D::switchNode ( EFANode new_node,
EFANode old_node,
bool  descend_to_parent 
)
virtual

Implements EFAElement.

Definition at line 267 of file EFAElement2D.C.

Referenced by connectNeighbors(), restoreFragment(), switchEmbeddedNode(), and updateFragmentNode().

268 {
269  // We are not switching any embedded nodes here
270  for (unsigned int i = 0; i < _num_nodes; ++i)
271  {
272  if (_nodes[i] == old_node)
273  _nodes[i] = new_node;
274  }
275  for (unsigned int i = 0; i < _fragments.size(); ++i)
276  _fragments[i]->switchNode(new_node, old_node);
277 
278  for (unsigned int i = 0; i < _edges.size(); ++i)
279  _edges[i]->switchNode(new_node, old_node);
280 
281  if (_parent && descend_to_parent)
282  {
283  _parent->switchNode(new_node, old_node, false);
284  for (unsigned int i = 0; i < _parent->numGeneralNeighbors(); ++i)
285  {
286  EFAElement * neigh_elem = _parent->getGeneralNeighbor(i); // generalized neighbor element
287  for (unsigned int k = 0; k < neigh_elem->numChildren(); ++k)
288  neigh_elem->getChild(k)->switchNode(new_node, old_node, false);
289  }
290  }
291 }
unsigned int numChildren() const
Definition: EFAElement.C:189
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
unsigned int numGeneralNeighbors() const
Definition: EFAElement.C:236
EFAElement * getChild(unsigned int child_id) const
Definition: EFAElement.C:174
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement2D.C:267
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)=0
EFAElement * _parent
Definition: EFAElement.h:31
EFAElement * getGeneralNeighbor(unsigned int index) const
Definition: EFAElement.C:230
static const std::string k
Definition: NS.h:124
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ updateFragmentNode()

void EFAElement2D::updateFragmentNode ( )
virtual

Implements EFAElement.

Definition at line 1306 of file EFAElement2D.C.

1307 {
1308  for (unsigned int j = 0; j < _num_nodes; ++j)
1309  {
1310  if (_nodes[j]->parent() != nullptr &&
1311  _nodes[j]->parent()->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT)
1312  switchNode(_nodes[j], _nodes[j]->parent(), false);
1313  }
1314 }
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement2D.C:267
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
unsigned int _num_nodes
Definition: EFAElement.h:28
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")

◆ updateFragments()

void EFAElement2D::updateFragments ( const std::set< EFAElement *> &  CrackTipElements,
std::map< unsigned int, EFANode *> &  EmbeddedNodes 
)
virtual

Implements EFAElement.

Definition at line 815 of file EFAElement2D.C.

817 {
818  // combine the crack-tip edges in a fragment to a single intersected edge
819  std::set<EFAElement *>::iterator sit;
820  sit = CrackTipElements.find(this);
821  if (sit != CrackTipElements.end()) // curr_elem is a crack tip element
822  {
823  if (_fragments.size() == 1)
824  _fragments[0]->combineTipEdges();
825  else
826  EFAError("crack tip elem ", _id, " must have 1 fragment");
827  }
828 
829  // if a fragment only has 1 intersection which is in an interior edge
830  // remove this embedded node (MUST DO THIS AFTER combine_tip_edges())
831  if (_fragments.size() == 1)
832  _fragments[0]->removeInvalidEmbeddedNodes(EmbeddedNodes);
833 
834  // for an element with no fragment, create one fragment identical to the element
835  if (_fragments.size() == 0)
836  _fragments.push_back(new EFAFragment2D(this, true, this));
837  if (_fragments.size() != 1)
838  EFAError("Element ", _id, " must have 1 fragment at this point");
839 
840  // count fragment's cut edges
841  unsigned int num_cut_frag_edges = _fragments[0]->getNumCuts();
842  unsigned int num_cut_nodes = _fragments[0]->getNumCutNodes();
843  unsigned int num_frag_edges = _fragments[0]->numEdges();
844  if (num_cut_frag_edges > 3)
845  EFAError("In element ", _id, " there are more than 2 cut fragment edges");
846 
847  if (num_cut_frag_edges == 0 && num_cut_nodes == 0)
848  {
849  if (!isPartial()) // delete the temp frag for an uncut elem
850  {
851  delete _fragments[0];
852  _fragments.clear();
853  }
854  // Element has already been cut. Don't recreate fragments because we
855  // would create multiple fragments to cover the entire element and
856  // lose the information about what part of this element is physical.
857  return;
858  }
859 
860  // split one fragment into one, two or three new fragments
861  std::vector<EFAFragment2D *> new_frags;
862  if (num_cut_frag_edges == 3)
863  new_frags = branchingSplit(EmbeddedNodes);
864  else
865  new_frags = _fragments[0]->split();
866 
867  delete _fragments[0]; // delete the old fragment
868  _fragments.clear();
869  for (unsigned int i = 0; i < new_frags.size(); ++i)
870  _fragments.push_back(new_frags[i]);
871 
872  fragmentSanityCheck(num_frag_edges, num_cut_frag_edges);
873 }
virtual void fragmentSanityCheck(unsigned int n_old_frag_edges, unsigned int n_old_frag_cuts) const
Definition: EFAElement2D.C:876
std::vector< EFAFragment2D * > branchingSplit(std::map< unsigned int, EFANode *> &EmbeddedNodes)
unsigned int _id
Definition: EFAElement.h:27
virtual bool isPartial() const
Definition: EFAElement2D.C:213
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

◆ willCrackTipExtend()

bool EFAElement2D::willCrackTipExtend ( std::vector< unsigned int > &  split_neighbors) const
virtual

Implements EFAElement.

Definition at line 734 of file EFAElement2D.C.

Referenced by shouldDuplicateCrackTipSplitElement().

735 {
736  // Determine whether the current element is a crack tip element for which the crack will
737  // extend into the next element.
738  // N.B. this is called at the beginning of createChildElements
739  bool will_extend = false;
740  if (_fragments.size() == 1 && _crack_tip_split_element)
741  {
742  for (unsigned int i = 0; i < _crack_tip_neighbors.size(); ++i)
743  {
744  unsigned int neigh_idx = _crack_tip_neighbors[i];
745  if (numEdgeNeighbors(neigh_idx) != 1)
746  EFAError("in will_crack_tip_extend() element: ",
747  _id,
748  " has: ",
749  _edge_neighbors[neigh_idx].size(),
750  " on edge: ",
751  neigh_idx);
752 
753  EFAElement2D * neighbor_elem = _edge_neighbors[neigh_idx][0];
754  if (neighbor_elem->numFragments() > 2)
755  EFAError("in will_crack_tip_extend() element: ",
756  neighbor_elem->id(),
757  " has: ",
758  neighbor_elem->numFragments(),
759  " fragments");
760  else if (neighbor_elem->numFragments() == 2)
761  {
762  EFAFragment2D * frag1 = neighbor_elem->getFragment(0);
763  EFAFragment2D * frag2 = neighbor_elem->getFragment(1);
764  std::vector<EFANode *> neigh_cut_nodes = frag1->getCommonNodes(frag2);
765  if (neigh_cut_nodes.size() != 2)
766  EFAError("2 frags in a elem does not share 2 common nodes");
767  if (_edges[neigh_idx]->isEmbeddedNode(neigh_cut_nodes[0]) ||
768  _edges[neigh_idx]->isEmbeddedNode(neigh_cut_nodes[1]))
769  {
770  split_neighbors.push_back(neigh_idx);
771  will_extend = true;
772  }
773  }
774  } // i
775  }
776  return will_extend;
777 }
unsigned int numEdgeNeighbors(unsigned int edge_id) const
unsigned int id() const
Definition: EFAElement.C:28
unsigned int _id
Definition: EFAElement.h:27
std::vector< std::vector< EFAElement2D * > > _edge_neighbors
Definition: EFAElement2D.h:33
std::vector< EFAEdge * > _edges
Definition: EFAElement2D.h:31
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
std::vector< EFANode * > getCommonNodes(EFAFragment *other) const
Definition: EFAFragment.C:20
EFAFragment2D * getFragment(unsigned int frag_id) const
bool _crack_tip_split_element
Definition: EFAElement.h:33
std::vector< unsigned int > _crack_tip_neighbors
Definition: EFAElement.h:34
std::vector< EFAFragment2D * > _fragments
Definition: EFAElement2D.h:34

Member Data Documentation

◆ _children

std::vector<EFAElement *> EFAElement::_children
protectedinherited

◆ _crack_tip_neighbors

std::vector<unsigned int> EFAElement::_crack_tip_neighbors
protectedinherited

◆ _crack_tip_split_element

bool EFAElement::_crack_tip_split_element
protectedinherited

◆ _edge_neighbors

std::vector<std::vector<EFAElement2D *> > EFAElement2D::_edge_neighbors
private

◆ _edges

std::vector<EFAEdge *> EFAElement2D::_edges
private

◆ _fragments

std::vector<EFAFragment2D *> EFAElement2D::_fragments
private

◆ _general_neighbors

std::vector<EFAElement *> EFAElement::_general_neighbors
protectedinherited

◆ _id

unsigned int EFAElement::_id
protectedinherited

◆ _interior_nodes

std::vector<EFAFaceNode *> EFAElement2D::_interior_nodes
private

◆ _local_node_coor

std::vector<EFAPoint> EFAElement2D::_local_node_coor
private

Definition at line 35 of file EFAElement2D.h.

Referenced by createChild(), and setLocalCoordinates().

◆ _local_nodes

std::vector<EFANode *> EFAElement::_local_nodes
protectedinherited

◆ _nodes

std::vector<EFANode *> EFAElement::_nodes
protectedinherited

◆ _num_edges

unsigned int EFAElement2D::_num_edges
private

◆ _num_nodes

unsigned int EFAElement::_num_nodes
protectedinherited

◆ _parent

EFAElement* EFAElement::_parent
protectedinherited

The documentation for this class was generated from the following files: