https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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.

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
void setLocalCoordinates()
unsigned int _num_edges
std::vector< EFAEdge * > _edges

◆ 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)
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}
std::vector< EFAPoint > _local_node_coor
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
std::vector< EFAFaceNode * > _interior_nodes
std::vector< EFAFragment2D * > _fragments
std::vector< EFANode * > _nodes
Definition EFAElement.h:29
unsigned int _num_nodes
Definition EFAElement.h:28
unsigned int _id
Definition EFAElement.h:27
EFANode * createLocalNodeFromGlobalNode(const EFANode *global_node) const
Definition EFAElement.C:70
std::vector< EFANode * > _local_nodes
Definition EFAElement.h:30
unsigned int id() const
Definition EFAElement.C:28
@ N_CATEGORY_EMBEDDED_PERMANENT
Definition EFANode.h:22
@ N_CATEGORY_TEMP
Definition EFANode.h:20
@ N_CATEGORY_PERMANENT
Definition EFANode.h:19
@ N_CATEGORY_LOCAL_INDEX
Definition EFANode.h:23

◆ 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
EFAEdge * getEdge(unsigned int edge_id) const
Definition EFAFace.h:50
unsigned int numNodes() const
Definition EFAFace.C:87
EFAFaceNode * getInteriorNode(unsigned int index) const
Definition EFAFace.C:641
unsigned int numInteriorNodes() const
Definition EFAFace.C:236
EFANode * getNode(unsigned int node_id) const
Definition EFAFace.C:99

◆ ~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}

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.

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}
Point xi
unsigned int numEmbeddedNodes() const
Definition EFAEdge.C:341
EFANode * getNode(unsigned int index) const
Definition EFAEdge.C:181
void addIntersection(double position, EFANode *embedded_node_tmp, EFANode *from_node)
Definition EFAEdge.C:132
virtual unsigned int getNeighborIndex(const EFAElement *neighbor_elem) const
void addEdgeCut(unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode * > &EmbeddedNodes, bool add_to_neighbor)
bool fragmentEdgeAlreadyCut(unsigned int ElemEdgeID) const
EFAEdge * getEdge(unsigned int edge_id) const
bool getFragmentEdgeID(unsigned int elem_edge_id, unsigned int &frag_edge_id) const
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
unsigned int numEdgeNeighbors(unsigned int edge_id) const
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
@ N_CATEGORY_EMBEDDED
Definition EFANode.h:21
unsigned int getNewID(std::map< unsigned int, T * > &theMap)
Definition EFAFuncs.h:38
static const double tol
Definition XFEMFuncs.h:21

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

◆ 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.

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}
Point eta
double getIntersection(unsigned int emb_id, EFANode *from_node) const
Definition EFAEdge.C:239
bool hasIntersectionAtPosition(double position, EFANode *from_node) const
Definition EFAEdge.C:213
bool hasIntersection() const
Definition EFAEdge.C:200
bool getEdgeNodeParametricCoordinate(EFANode *node, std::vector< double > &para_coor) const
N_CATEGORY category() const
Definition EFANode.C:42

Referenced by ElementFragmentAlgorithm::addFragEdgeIntersection().

◆ 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.

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
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}
unsigned int id() const
Definition EFANode.C:36
void setCategory(EFANode::N_CATEGORY category)
Definition EFANode.C:60
bool deleteFromMap(std::map< unsigned int, T * > &theMap, T *elemToDelete, bool delete_elem=true)
Definition EFAFuncs.h:22

Referenced by ElementFragmentAlgorithm::addElemNodeIntersection().

◆ branchingSplit()

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

Definition at line 1922 of file EFAElement2D.C.

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}
virtual bool isPartial() const
EFANode * getNode(unsigned int node_id) const
Definition EFAElement.C:46
bool containsNode(EFANode *node) const
Definition EFAElement.C:52
void addEdge(EFAEdge *new_edge)

Referenced by updateFragments().

◆ 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< EFAElement * > _general_neighbors
Definition EFAElement.h:36

◆ clearParentAndChildren()

void EFAElement::clearParentAndChildren ( )
inherited

Definition at line 201 of file EFAElement.C.

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

Referenced by ElementFragmentAlgorithm::clearAncestry().

◆ 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}
EFANode * getInteriorNode() const
Definition EFAEdge.h:51
virtual unsigned int numFragments() const
EFAFragment2D * getFragment(unsigned int frag_id) const
void mergeNodes(EFANode *&childNode, EFANode *&childOfNeighborNode, EFAElement *childOfNeighborElem, std::map< unsigned int, EFANode * > &PermanentNodes, std::map< unsigned int, EFANode * > &TempNodes)
Definition EFAElement.C:242
EFAElement * getChild(unsigned int child_id) const
Definition EFAElement.C:174
unsigned int numChildren() const
Definition EFAElement.C:189
EFANode * parent() const
Definition EFANode.C:48

◆ 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}
const Real p
void setInteriorNode(EFANode *node)
Definition EFAEdge.h:52
void copyIntersection(const EFAEdge &other, unsigned int from_node_id)
Definition EFAEdge.C:162
virtual bool shouldDuplicateForCrackTip(const std::set< EFAElement * > &CrackTipElements)
void setEdge(unsigned int edge_id, EFAEdge *edge)
virtual void getMasterInfo(EFANode *node, std::vector< EFANode * > &master_nodes, std::vector< double > &master_weights) const
virtual void removePhantomEmbeddedNode()
unsigned int numNodes() const
Definition EFAElement.C:34
void setNode(unsigned int node_id, EFANode *node)
Definition EFAElement.C:40
void setParent(EFAElement *parent)
Definition EFAElement.C:183
bool isEdgeInterior(unsigned int edge_id) const
unsigned int numEdges() const
void normalizePoint(Point &p)
Definition XFEMFuncs.C:621

◆ createEdges()

void EFAElement2D::createEdges ( )

Definition at line 1464 of file EFAElement2D.C.

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}

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

◆ createLocalNodeFromGlobalNode()

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

Definition at line 70 of file EFAElement.C.

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}

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

◆ deleteInteriorNodes()

void EFAElement2D::deleteInteriorNodes ( )

Definition at line 1444 of file EFAElement2D.C.

1445{
1446 for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
1447 delete _interior_nodes[i];
1448 _interior_nodes.clear();
1449}

Referenced by EFAFragment2D::removeInvalidEmbeddedNodes().

◆ edgeContainsTip()

bool EFAElement2D::edgeContainsTip ( unsigned int  edge_id) const

Definition at line 1674 of file EFAElement2D.C.

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}

Referenced by fragmentEdgeAlreadyCut().

◆ findGeneralNeighbors()

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

Definition at line 208 of file EFAElement.C.

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}

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

◆ fragmentEdgeAlreadyCut()

bool EFAElement2D::fragmentEdgeAlreadyCut ( unsigned int  ElemEdgeID) const

Definition at line 1695 of file EFAElement2D.C.

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

Referenced by addEdgeCut().

◆ fragmentHasTipEdges()

bool EFAElement2D::fragmentHasTipEdges ( ) const

Definition at line 1586 of file EFAElement2D.C.

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}

Referenced by isCrackTipElement().

◆ 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.

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}
virtual unsigned int numInteriorNodes() const

Referenced by updateFragments().

◆ getChild()

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

Definition at line 174 of file EFAElement.C.

175{
176 if (child_id < _children.size())
177 return _children[child_id];
178 else
179 EFAError("child_id out of bounds");
180}

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

◆ getCommonNodes()

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

Definition at line 2067 of file EFAElement2D.C.

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< T > getCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition EFAFuncs.h:69

Referenced by overlaysElement(), and setupNeighbors().

◆ 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}

◆ getCrackTipSplitElementID()

unsigned int EFAElement2D::getCrackTipSplitElementID ( ) const

Definition at line 599 of file EFAElement2D.C.

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}
virtual bool isCrackTipElement() const
bool isCrackTipSplit() const
Definition EFAElement.C:128

Referenced by XFEM::storeCrackTipOriginAndDirection().

◆ 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.

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}

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

◆ getEdgeNodeParametricCoordinate()

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

Definition at line 1411 of file EFAElement2D.C.

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

Referenced by addFragmentEdgeCut(), and branchingSplit().

◆ getEdgeNodes()

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

Definition at line 1402 of file EFAElement2D.C.

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}

Referenced by setupNeighbors(), and shouldDuplicateCrackTipSplitElement().

◆ 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.

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}

Referenced by addEdgeCut(), and fragmentEdgeAlreadyCut().

◆ getGeneralNeighbor()

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

Definition at line 230 of file EFAElement.C.

231{
232 return _general_neighbors[index];
233}

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

◆ 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}

◆ getInteriorNode()

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

Definition at line 1435 of file EFAElement2D.C.

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}

Referenced by EFAFragment2D::isSecondaryInteriorEdge().

◆ getLocalNodeIndex()

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

Definition at line 111 of file EFAElement.C.

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}

Referenced by XFEM::getEFANodeCoords().

◆ 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.

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}
double linearTriShape2D(unsigned int node_id, std::vector< double > &xi_2d)
Definition EFAFuncs.C:23
double linearQuadShape2D(unsigned int node_id, std::vector< double > &xi_2d)
Definition EFAFuncs.C:16
dof_id_type weight(const MeshBase &mesh, const processor_id_type pid)

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

◆ getNeighborIndex()

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

Implements EFAElement.

Definition at line 452 of file EFAElement2D.C.

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}

Referenced by addEdgeCut(), and connectNeighbors().

◆ 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; }

◆ getNonPhysicalNodes()

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

Implements EFAElement.

Definition at line 240 of file EFAElement2D.C.

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}

Referenced by shouldDuplicateCrackTipSplitElement().

◆ getNumCuts()

unsigned int EFAElement2D::getNumCuts ( ) const
virtual

Implements EFAElement.

Definition at line 786 of file EFAElement2D.C.

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}

Referenced by restoreFragment().

◆ getParent()

EFAElement * EFAElement::getParent ( ) const
inherited

Definition at line 168 of file EFAElement.C.

169{
170 return _parent;
171}

◆ getPhantomNodeOnEdge()

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

Definition at line 1495 of file EFAElement2D.C.

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}

Referenced by shouldDuplicateForPhantomCorner().

◆ getTipEdgeID()

unsigned int EFAElement2D::getTipEdgeID ( ) const

Definition at line 1613 of file EFAElement2D.C.

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}

Referenced by XFEM::markCutEdgesByState().

◆ getTipEmbeddedNode()

EFANode * EFAElement2D::getTipEmbeddedNode ( ) const

Definition at line 1641 of file EFAElement2D.C.

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}

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

◆ 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 overlaysElement(const EFAElement2D *other_elem) const
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.

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

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

◆ isCrackTipSplit()

bool EFAElement::isCrackTipSplit ( ) const
inherited

Definition at line 128 of file EFAElement.C.

129{
131}

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

◆ isEdgePhantom()

bool EFAElement2D::isEdgePhantom ( unsigned int  edge_id) const

Definition at line 1542 of file EFAElement2D.C.

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}

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

◆ isFinalCut()

bool EFAElement2D::isFinalCut ( ) const
virtual

Implements EFAElement.

Definition at line 796 of file EFAElement2D.C.

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}

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

◆ isPartial()

bool EFAElement2D::isPartial ( ) const
virtual

Implements EFAElement.

Definition at line 213 of file EFAElement2D.C.

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}

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

◆ 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.

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}

Referenced by getEdgeNodeParametricCoordinate().

◆ 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.

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}
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)=0
std::string idCatString()
Definition EFANode.C:20

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

◆ 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 numEdges() const

◆ numChildren()

unsigned int EFAElement::numChildren ( ) const
inherited

Definition at line 189 of file EFAElement.C.

190{
191 return _children.size();
192}

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

◆ numCrackTipNeighbors()

unsigned int EFAElement::numCrackTipNeighbors ( ) const
inherited

Definition at line 134 of file EFAElement.C.

135{
136 return _crack_tip_neighbors.size();
137}

◆ numEdgeNeighbors()

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

Definition at line 1568 of file EFAElement2D.C.

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}

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

◆ 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.

237{
238 return _general_neighbors.size();
239}

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

◆ numInteriorNodes()

unsigned int EFAElement2D::numInteriorNodes ( ) const
virtual

Implements EFAElement.

Definition at line 358 of file EFAElement2D.C.

359{
360 return _interior_nodes.size();
361}

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

◆ numNodes()

unsigned int EFAElement::numNodes ( ) const
inherited

◆ overlaysElement()

bool EFAElement2D::overlaysElement ( const EFAElement2D other_elem) const

Definition at line 364 of file EFAElement2D.C.

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

Referenced by initCrackTip(), and setupNeighbors().

◆ 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}

◆ 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}

◆ removePhantomEmbeddedNode()

void EFAElement2D::removePhantomEmbeddedNode ( )
virtual

Implements EFAElement.

Definition at line 1156 of file EFAElement2D.C.

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}

Referenced by createChild().

◆ 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)
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}
virtual unsigned int getNumCuts() const

◆ setCrackTipSplit()

void EFAElement::setCrackTipSplit ( )
inherited

Definition at line 122 of file EFAElement.C.

123{
125}

◆ setEdge()

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

Definition at line 1458 of file EFAElement2D.C.

1459{
1460 _edges[edge_id] = edge;
1461}

Referenced by createChild().

◆ setLocalCoordinates()

void EFAElement2D::setLocalCoordinates ( )
private

Definition at line 141 of file EFAElement2D.C.

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}

Referenced by EFAElement2D().

◆ 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.

184{
185 _parent = parent;
186}

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

◆ 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::set< EFANode * > getEdgeNodes(unsigned int edge_id) const
void findGeneralNeighbors(const std::map< EFANode *, std::set< EFAElement * > > &InverseConnectivity)
Definition EFAElement.C:208
unsigned int numCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition EFAFuncs.h:49

◆ shouldDuplicateCrackTipSplitElement()

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

Implements EFAElement.

Definition at line 644 of file EFAElement2D.C.

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}
virtual bool willCrackTipExtend(std::vector< unsigned int > &split_neighbors) const
virtual void getNonPhysicalNodes(std::set< EFANode * > &non_physical_nodes) const

Referenced by shouldDuplicateForCrackTip().

◆ shouldDuplicateForCrackTip()

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

Implements EFAElement.

Definition at line 620 of file EFAElement2D.C.

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()
virtual bool shouldDuplicateCrackTipSplitElement(const std::set< EFAElement * > &CrackTipElements)

Referenced by createChild().

◆ shouldDuplicateForPhantomCorner()

bool EFAElement2D::shouldDuplicateForPhantomCorner ( )
virtual

Implements EFAElement.

Definition at line 695 of file EFAElement2D.C.

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}
bool equivalent(const EFAEdge &other) const
Definition EFAEdge.C:38
std::set< EFANode * > getPhantomNodeOnEdge(unsigned int edge_id) const

Referenced by shouldDuplicateForCrackTip().

◆ 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}

◆ 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.

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}
EFAElement * getGeneralNeighbor(unsigned int index) const
Definition EFAElement.C:230
unsigned int numGeneralNeighbors() const
Definition EFAElement.C:236

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

◆ 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}

◆ 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
std::vector< EFAFragment2D * > branchingSplit(std::map< unsigned int, EFANode * > &EmbeddedNodes)

◆ willCrackTipExtend()

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

Implements EFAElement.

Definition at line 734 of file EFAElement2D.C.

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}
std::vector< EFANode * > getCommonNodes(EFAFragment *other) const
Definition EFAFragment.C:20

Referenced by shouldDuplicateCrackTipSplitElement().

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: