https://mooseframework.inl.gov
Public Member Functions | Public Attributes | Protected Attributes | Private Member Functions | Private Attributes | List of all members
XFEM Class Referenceabstract

This is the XFEM class. More...

#include <XFEM.h>

Inheritance diagram for XFEM:
[legend]

Public Member Functions

 XFEM (const InputParameters &params)
 
 ~XFEM ()
 
void addGeometricCut (GeometricCutUserObject *geometric_cut)
 
void addStateMarkedElem (unsigned int elem_id, RealVectorValue &normal)
 
void addStateMarkedElem (unsigned int elem_id, RealVectorValue &normal, unsigned int marked_side)
 
void addStateMarkedFrag (unsigned int elem_id, RealVectorValue &normal)
 
void clearStateMarkedElems ()
 
void addGeomMarkedElem2D (const unsigned int elem_id, const Xfem::GeomMarkedElemInfo2D geom_info, const unsigned int interface_id)
 Add information about a new cut to be performed on a specific 2d element. More...
 
void addGeomMarkedElem3D (const unsigned int elem_id, const Xfem::GeomMarkedElemInfo3D geom_info, const unsigned int interface_id)
 Add information about a new cut to be performed on a specific 3d element. More...
 
void clearGeomMarkedElems ()
 Clear out the list of elements to be marked for cutting. More...
 
virtual bool update (Real time, const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux) override
 
virtual void initSolution (const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux) override
 
void buildEFAMesh ()
 
bool markCuts (Real time)
 
bool markCutEdgesByGeometry ()
 
bool markCutEdgesByState (Real time)
 
bool markCutFacesByGeometry ()
 
bool markCutFacesByState ()
 
bool initCutIntersectionEdge (Point cut_origin, RealVectorValue cut_normal, Point &edge_p1, Point &edge_p2, Real &dist)
 
bool cutMeshWithEFA (const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux)
 
bool healMesh ()
 Potentially heal the mesh by merging some of the pairs of partial elements cut by XFEM back into single elements if indicated by the cutting objects. More...
 
virtual bool updateHeal () override
 
Point getEFANodeCoords (EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
 
Real getPhysicalVolumeFraction (const Elem *elem) const
 Get the volume fraction of an element that is physical. More...
 
bool isPointInsidePhysicalDomain (const Elem *elem, const Point &point) const
 Return true if the point is inside the element physical domain Note: if this element is not cut, return true too. More...
 
Real getCutPlane (const Elem *elem, const Xfem::XFEM_CUTPLANE_QUANTITY quantity, unsigned int plane_id) const
 Get specified component of normal or origin for cut plane for a given element. More...
 
bool isElemAtCrackTip (const Elem *elem) const
 
bool isElemCut (const Elem *elem, XFEMCutElem *&xfce) const
 
bool isElemCut (const Elem *elem) const
 
void getFragmentFaces (const Elem *elem, std::vector< std::vector< Point >> &frag_faces, bool displaced_mesh=false) const
 
void storeCrackTipOriginAndDirection ()
 
void correctCrackExtensionDirection (const Elem *elem, EFAElement2D *CEMElem, EFAEdge *orig_edge, Point normal, Point crack_tip_origin, Point crack_tip_direction, Real &distance_keep, unsigned int &edge_id_keep, Point &normal_keep)
 
void getCrackTipOrigin (std::map< unsigned int, const Elem *> &elem_id_crack_tip, std::vector< Point > &crack_front_points)
 
Xfem::XFEM_QRULEgetXFEMQRule ()
 
void setXFEMQRule (std::string &xfem_qrule)
 
void setCrackGrowthMethod (bool use_crack_growth_increment, Real crack_growth_increment)
 
void setDebugOutputLevel (unsigned int debug_output_level)
 Controls amount of debugging information output. More...
 
void setMinWeightMultiplier (Real min_weight_multiplier)
 Controls the minimum average weight multiplier for each element. More...
 
virtual bool getXFEMWeights (MooseArray< Real > &weights, const Elem *elem, QBase *qrule, const MooseArray< Point > &q_points) override
 
virtual bool getXFEMFaceWeights (MooseArray< Real > &weights, const Elem *elem, QBase *qrule, const MooseArray< Point > &q_points, unsigned int side) override
 
virtual const ElementPairLocator::ElementPairListgetXFEMCutElemPairs (unsigned int interface_id)
 Get the list of cut element pairs corresponding to a given interface ID. More...
 
virtual const ElementPairLocator::ElementPairListgetXFEMDisplacedCutElemPairs (unsigned int interface_id)
 Get the list of cut element pairs on the displaced mesh corresponding to a given interface ID. More...
 
virtual unsigned int getGeometricCutID (const GeometricCutUserObject *gcu)
 Get the interface ID corresponding to a given GeometricCutUserObject. More...
 
virtual void getXFEMIntersectionInfo (const Elem *elem, unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, bool displaced_mesh=false) const
 
virtual void getXFEMqRuleOnLine (std::vector< Point > &intersection_points, std::vector< Point > &quad_pts, std::vector< Real > &quad_wts) const
 
virtual void getXFEMqRuleOnSurface (std::vector< Point > &intersection_points, std::vector< Point > &quad_pts, std::vector< Real > &quad_wts) const
 
bool has_secondary_cut ()
 
EFAElement2DgetEFAElem2D (const Elem *elem)
 Get the EFAElement2D object for a specified libMesh element. More...
 
EFAElement3DgetEFAElem3D (const Elem *elem)
 Get the EFAElement3D object for a specified libMesh element. More...
 
void getFragmentEdges (const Elem *elem, EFAElement2D *CEMElem, std::vector< std::vector< Point >> &frag_edges) const
 
void getFragmentFaces (const Elem *elem, EFAElement3D *CEMElem, std::vector< std::vector< Point >> &frag_faces) const
 
const std::map< const Elem *, std::vector< Point > > & getCrackTipOriginMap () const
 
CutSubdomainID getCutSubdomainID (const GeometricCutUserObject *gcuo, const Elem *cut_elem, const Elem *parent_elem=nullptr) const
 Determine which cut subdomain the element belongs to relative to the cut. More...
 
void setMesh (MooseMesh *mesh)
 
void setDisplacedMesh (MooseMesh *displaced_mesh)
 
void setMaterialData (const std::vector< MaterialData * > &data)
 
void setBoundaryMaterialData (const std::vector< MaterialData * > &data)
 
virtual bool getXFEMWeights (MooseArray< Real > &weights, const Elem *elem, libMesh::QBase *qrule, const MooseArray< Point > &q_points)=0
 
virtual bool getXFEMFaceWeights (MooseArray< Real > &weights, const Elem *elem, libMesh::QBase *qrule, const MooseArray< Point > &q_points, unsigned int side)=0
 

Public Attributes

const ConsoleStream _console
 

Protected Attributes

FEProblemBase_fe_problem
 
std::vector< MaterialData *> _material_data
 
std::vector< MaterialData *> _bnd_material_data
 
MooseMesh_moose_mesh
 
MooseMesh_moose_displaced_mesh
 
MeshBase * _mesh
 
MeshBase * _displaced_mesh
 

Private Member Functions

void storeSolutionForNode (const Node *node_to_store_to, const Node *node_to_store_from, SystemBase &sys, std::map< unique_id_type, std::vector< Real >> &stored_solution, const NumericVector< Number > &current_solution, const NumericVector< Number > &old_solution, const NumericVector< Number > &older_solution)
 Store the solution in stored_solution for a given node. More...
 
void storeSolutionForElement (const Elem *elem_to_store_to, const Elem *elem_to_store_from, SystemBase &sys, std::map< unique_id_type, std::vector< Real >> &stored_solution, const NumericVector< Number > &current_solution, const NumericVector< Number > &old_solution, const NumericVector< Number > &older_solution)
 Store the solution in stored_solution for a given element. More...
 
void setSolution (SystemBase &sys, const std::map< unique_id_type, std::vector< Real >> &stored_solution, NumericVector< Number > &current_solution, NumericVector< Number > &old_solution, NumericVector< Number > &older_solution)
 Set the solution for all locally-owned nodes/elements that have stored values. More...
 
void setSolutionForDOFs (const std::vector< Real > &stored_solution, const std::vector< dof_id_type > &stored_solution_dofs, NumericVector< Number > &current_solution, NumericVector< Number > &old_solution, NumericVector< Number > &older_solution)
 Set the solution for a set of DOFs. More...
 
std::vector< dof_id_typegetElementSolutionDofs (const Elem *elem, SystemBase &sys) const
 Get a vector of the dof indices for all components of all variables associated with an element. More...
 
std::vector< dof_id_typegetNodeSolutionDofs (const Node *node, SystemBase &sys) const
 Get a vector of the dof indices for all components of all variables associated with a node. More...
 
const GeometricCutUserObjectgetGeometricCutForElem (const Elem *elem) const
 Get the GeometricCutUserObject associated with an element. More...
 
void storeMaterialPropertiesForElementHelper (const Elem *elem, MaterialPropertyStorage &storage)
 
void storeMaterialPropertiesForElement (const Elem *parent_elem, const Elem *child_elem)
 Helper function to store the material properties of a healed element. More...
 
void loadMaterialPropertiesForElementHelper (const Elem *elem, const Xfem::CachedMaterialProperties &cached_props, MaterialPropertyStorage &storage) const
 Load the material properties. More...
 
void loadMaterialPropertiesForElement (const Elem *elem, const Elem *elem_from, std::unordered_map< const Elem *, Xfem::CutElemInfo > &cached_cei) const
 Helper function to store the material properties of a healed element. More...
 
const Node * pickFirstPhysicalNode (const Elem *e, const Elem *e0) const
 Return the first node in the provided element that is found to be in the physical domain. More...
 

Private Attributes

bool _has_secondary_cut
 
Xfem::XFEM_QRULE _XFEM_qrule
 
bool _use_crack_growth_increment
 
Real _crack_growth_increment
 
std::vector< const GeometricCutUserObject * > _geometric_cuts
 
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
 
std::set< const Elem * > _crack_tip_elems
 
std::set< const Elem * > _crack_tip_elems_to_be_healed
 
std::map< unsigned int, ElementPairLocator::ElementPairList_sibling_elems
 
std::map< unsigned int, ElementPairLocator::ElementPairList_sibling_displaced_elems
 
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
 
std::map< const Elem *, RealVectorValue_state_marked_elems
 
std::set< const Elem * > _state_marked_frags
 
std::map< const Elem *, unsigned int_state_marked_elem_sides
 
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo2D > > _geom_marked_elems_2d
 Data structure for storing information about all 2D elements to be cut by geometry. More...
 
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo3D > > _geom_marked_elems_3d
 Data structure for storing information about all 3D elements to be cut by geometry. More...
 
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
 Data structure for storing the elements cut by specific geometric cutters. More...
 
std::map< const GeometricCutUserObject *, unsigned int_geom_marker_id_map
 Data structure for storing the GeommetricCutUserObjects and their corresponding id. More...
 
ElementFragmentAlgorithm _efa_mesh
 
unsigned int _debug_output_level
 Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mesh 3: Full dump of element fragment algorithm mesh. More...
 
Real _min_weight_multiplier
 The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partial elements. More...
 
std::map< unique_id_type, std::vector< Real > > _cached_solution
 Data structure to store the nonlinear solution for nodes/elements affected by XFEM For each node/element, this is stored as a vector that contains all components of all applicable variables in an order defined by getElementSolutionDofs() or getNodeSolutionDofs(). More...
 
std::map< unique_id_type, std::vector< Real > > _cached_aux_solution
 Data structure to store the auxiliary solution for nodes/elements affected by XFEM For each node/element, this is stored as a vector that contains all components of all applicable variables in an order defined by getElementSolutionDofs() or getNodeSolutionDofs(). More...
 
std::unordered_map< const Elem *, Xfem::CutElemInfo_geom_cut_elems
 All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK. More...
 
std::unordered_map< const Elem *, Xfem::CutElemInfo_old_geom_cut_elems
 All geometrically cut elements and their CutElemInfo before the current execution of XFEM_MARK. More...
 

Detailed Description

This is the XFEM class.

This class implements algorithms for dynamic mesh modification in support of a phantom node approach for XFEM

Definition at line 107 of file XFEM.h.

Constructor & Destructor Documentation

◆ XFEM()

XFEM::XFEM ( const InputParameters params)
explicit

Definition at line 36 of file XFEM.C.

37  : XFEMInterface(params),
38  _efa_mesh(Moose::out),
41 {
42 #ifndef LIBMESH_ENABLE_UNIQUE_ID
43  mooseError("MOOSE requires unique ids to be enabled in libmesh (configure with "
44  "--enable-unique-id) to use XFEM!");
45 #endif
46  _has_secondary_cut = false;
47 }
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
Definition: XFEM.h:369
void mooseError(Args &&... args)
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
bool _has_secondary_cut
Definition: XFEM.h:327
XFEMInterface(const InputParameters &params)
Real _min_weight_multiplier
The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partia...
Definition: XFEM.h:373

◆ ~XFEM()

XFEM::~XFEM ( )

Definition at line 49 of file XFEM.C.

50 {
51  for (std::map<unique_id_type, XFEMCutElem *>::iterator cemit = _cut_elem_map.begin();
52  cemit != _cut_elem_map.end();
53  ++cemit)
54  delete cemit->second;
55 }
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336

Member Function Documentation

◆ addGeometricCut()

void XFEM::addGeometricCut ( GeometricCutUserObject geometric_cut)

Definition at line 58 of file XFEM.C.

59 {
60  _geometric_cuts.push_back(geometric_cut);
61 
62  geometric_cut->setInterfaceID(_geometric_cuts.size() - 1);
63 
64  _geom_marker_id_map[geometric_cut] = _geometric_cuts.size() - 1;
65 }
std::vector< const GeometricCutUserObject * > _geometric_cuts
Definition: XFEM.h:334
std::map< const GeometricCutUserObject *, unsigned int > _geom_marker_id_map
Data structure for storing the GeommetricCutUserObjects and their corresponding id.
Definition: XFEM.h:360
void setInterfaceID(unsigned int interface_id)
Set the interface ID for this cutting object.

◆ addGeomMarkedElem2D()

void XFEM::addGeomMarkedElem2D ( const unsigned int  elem_id,
const Xfem::GeomMarkedElemInfo2D  geom_info,
const unsigned int  interface_id 
)

Add information about a new cut to be performed on a specific 2d element.

Parameters
elem_idThe id of the element to be cut
geom_infoThe object containing information about the cut to be performed
interface_idThe ID of the interface

Definition at line 160 of file XFEM.C.

163 {
164  Elem * elem = _mesh->elem_ptr(elem_id);
165  _geom_marked_elems_2d[elem].push_back(geom_info);
166  _geom_marker_id_elems[interface_id].insert(elem_id);
167 }
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo2D > > _geom_marked_elems_2d
Data structure for storing information about all 2D elements to be cut by geometry.
Definition: XFEM.h:351
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
Definition: XFEM.h:357
MeshBase * _mesh

◆ addGeomMarkedElem3D()

void XFEM::addGeomMarkedElem3D ( const unsigned int  elem_id,
const Xfem::GeomMarkedElemInfo3D  geom_info,
const unsigned int  interface_id 
)

Add information about a new cut to be performed on a specific 3d element.

Parameters
elem_idThe id of the element to be cut
geom_infoThe object containing information about the cut to be performed
interface_idThe ID of the interface

Definition at line 170 of file XFEM.C.

173 {
174  Elem * elem = _mesh->elem_ptr(elem_id);
175  _geom_marked_elems_3d[elem].push_back(geom_info);
176  _geom_marker_id_elems[interface_id].insert(elem_id);
177 }
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo3D > > _geom_marked_elems_3d
Data structure for storing information about all 3D elements to be cut by geometry.
Definition: XFEM.h:354
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
Definition: XFEM.h:357
MeshBase * _mesh

◆ addStateMarkedElem() [1/2]

void XFEM::addStateMarkedElem ( unsigned int  elem_id,
RealVectorValue normal 
)

Definition at line 114 of file XFEM.C.

Referenced by addStateMarkedElem(), and addStateMarkedFrag().

115 {
116  Elem * elem = _mesh->elem_ptr(elem_id);
117  std::map<const Elem *, RealVectorValue>::iterator mit;
118  mit = _state_marked_elems.find(elem);
119  if (mit != _state_marked_elems.end())
120  mooseError(" ERROR: element ", elem->id(), " already marked for crack growth.");
121  _state_marked_elems[elem] = normal;
122 }
void mooseError(Args &&... args)
MeshBase * _mesh
std::map< const Elem *, RealVectorValue > _state_marked_elems
Definition: XFEM.h:346

◆ addStateMarkedElem() [2/2]

void XFEM::addStateMarkedElem ( unsigned int  elem_id,
RealVectorValue normal,
unsigned int  marked_side 
)

Definition at line 125 of file XFEM.C.

126 {
127  addStateMarkedElem(elem_id, normal);
128  Elem * elem = _mesh->elem_ptr(elem_id);
129  std::map<const Elem *, unsigned int>::iterator mit;
130  mit = _state_marked_elem_sides.find(elem);
131  if (mit != _state_marked_elem_sides.end())
132  mooseError(" ERROR: side of element ", elem->id(), " already marked for crack initiation.");
133 
134  _state_marked_elem_sides[elem] = marked_side;
135 }
void mooseError(Args &&... args)
MeshBase * _mesh
void addStateMarkedElem(unsigned int elem_id, RealVectorValue &normal)
Definition: XFEM.C:114
std::map< const Elem *, unsigned int > _state_marked_elem_sides
Definition: XFEM.h:348

◆ addStateMarkedFrag()

void XFEM::addStateMarkedFrag ( unsigned int  elem_id,
RealVectorValue normal 
)

Definition at line 138 of file XFEM.C.

139 {
140  addStateMarkedElem(elem_id, normal);
141  Elem * elem = _mesh->elem_ptr(elem_id);
142  std::set<const Elem *>::iterator mit;
143  mit = _state_marked_frags.find(elem);
144  if (mit != _state_marked_frags.end())
145  mooseError(
146  " ERROR: element ", elem->id(), " already marked for fragment-secondary crack initiation.");
147 
148  _state_marked_frags.insert(elem);
149 }
void mooseError(Args &&... args)
std::set< const Elem * > _state_marked_frags
Definition: XFEM.h:347
MeshBase * _mesh
void addStateMarkedElem(unsigned int elem_id, RealVectorValue &normal)
Definition: XFEM.C:114

◆ buildEFAMesh()

void XFEM::buildEFAMesh ( )

Definition at line 343 of file XFEM.C.

Referenced by update(), and updateHeal().

344 {
345  _efa_mesh.reset();
346 
347  // Load all existing elements in to EFA mesh
348  for (auto & elem : _mesh->element_ptr_range())
349  {
350  std::vector<unsigned int> quad;
351  for (unsigned int i = 0; i < elem->n_nodes(); ++i)
352  quad.push_back(elem->node_id(i));
353 
354  if (_mesh->mesh_dimension() == 2)
355  _efa_mesh.add2DElement(quad, elem->id());
356  else if (_mesh->mesh_dimension() == 3)
357  _efa_mesh.add3DElement(quad, elem->id());
358  else
359  mooseError("XFEM only works for 2D and 3D");
360  }
361 
362  // Restore fragment information for elements that have been previously cut
363  for (auto & elem : _mesh->element_ptr_range())
364  {
365  std::map<unique_id_type, XFEMCutElem *>::iterator cemit = _cut_elem_map.find(elem->unique_id());
366  if (cemit != _cut_elem_map.end())
367  {
368  XFEMCutElem * xfce = cemit->second;
369  EFAElement * CEMElem = _efa_mesh.getElemByID(elem->id());
370  _efa_mesh.restoreFragmentInfo(CEMElem, xfce->getEFAElement());
371  }
372  }
373 
374  // Must update edge neighbors before restore edge intersections. Otherwise, when we
375  // add edge intersections, we do not have neighbor information to use.
376  // Correction: no need to use neighbor info now
379 }
void mooseError(Args &&... args)
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
EFAElement * add3DElement(const std::vector< unsigned int > &quad, unsigned int id)
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
virtual const EFAElement * getEFAElement() const =0
void restoreFragmentInfo(EFAElement *const elem, const EFAElement *const from_elem)
MeshBase * _mesh
EFAElement * add2DElement(const std::vector< unsigned int > &quad, unsigned int id)
EFAElement * getElemByID(unsigned int id)

◆ clearGeomMarkedElems()

void XFEM::clearGeomMarkedElems ( )

Clear out the list of elements to be marked for cutting.

Called after cutting is done.

Definition at line 180 of file XFEM.C.

Referenced by update().

181 {
182  _geom_marked_elems_2d.clear();
183  _geom_marked_elems_3d.clear();
184 }
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo3D > > _geom_marked_elems_3d
Data structure for storing information about all 3D elements to be cut by geometry.
Definition: XFEM.h:354
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo2D > > _geom_marked_elems_2d
Data structure for storing information about all 2D elements to be cut by geometry.
Definition: XFEM.h:351

◆ clearStateMarkedElems()

void XFEM::clearStateMarkedElems ( )

Definition at line 152 of file XFEM.C.

Referenced by update().

153 {
154  _state_marked_elems.clear();
155  _state_marked_frags.clear();
156  _state_marked_elem_sides.clear();
157 }
std::set< const Elem * > _state_marked_frags
Definition: XFEM.h:347
std::map< const Elem *, unsigned int > _state_marked_elem_sides
Definition: XFEM.h:348
std::map< const Elem *, RealVectorValue > _state_marked_elems
Definition: XFEM.h:346

◆ correctCrackExtensionDirection()

void XFEM::correctCrackExtensionDirection ( const Elem *  elem,
EFAElement2D CEMElem,
EFAEdge orig_edge,
Point  normal,
Point  crack_tip_origin,
Point  crack_tip_direction,
Real distance_keep,
unsigned int edge_id_keep,
Point &  normal_keep 
)

Definition at line 451 of file XFEM.C.

Referenced by markCutEdgesByState().

460 {
461  std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
462  Point edge1(0.0, 0.0, 0.0);
463  Point edge2(0.0, 0.0, 0.0);
464  Point left_angle(0.0, 0.0, 0.0);
465  Point right_angle(0.0, 0.0, 0.0);
466  Point left_angle_normal(0.0, 0.0, 0.0);
467  Point right_angle_normal(0.0, 0.0, 0.0);
468  Point crack_direction_normal(0.0, 0.0, 0.0);
469  Point edge1_to_tip(0.0, 0.0, 0.0);
470  Point edge2_to_tip(0.0, 0.0, 0.0);
471  Point edge1_to_tip_normal(0.0, 0.0, 0.0);
472  Point edge2_to_tip_normal(0.0, 0.0, 0.0);
473 
474  Real cos_45 = std::cos(45.0 / 180.0 * 3.14159);
475  Real sin_45 = std::sin(45.0 / 180.0 * 3.14159);
476 
477  left_angle(0) = cos_45 * crack_tip_direction(0) - sin_45 * crack_tip_direction(1);
478  left_angle(1) = sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
479 
480  right_angle(0) = cos_45 * crack_tip_direction(0) + sin_45 * crack_tip_direction(1);
481  right_angle(1) = -sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
482 
483  left_angle_normal(0) = -left_angle(1);
484  left_angle_normal(1) = left_angle(0);
485 
486  right_angle_normal(0) = -right_angle(1);
487  right_angle_normal(1) = right_angle(0);
488 
489  crack_direction_normal(0) = -crack_tip_direction(1);
490  crack_direction_normal(1) = crack_tip_direction(0);
491 
492  Real angle_min = 0.0;
493  Real distance = 0.0;
494  unsigned int nsides = CEMElem->numEdges();
495 
496  for (unsigned int i = 0; i < nsides; ++i)
497  {
498  if (!orig_edge->isPartialOverlap(*CEMElem->getEdge(i)))
499  {
500  edge_ends[0] = getEFANodeCoords(CEMElem->getEdge(i)->getNode(0), CEMElem, elem);
501  edge_ends[1] = getEFANodeCoords(CEMElem->getEdge(i)->getNode(1), CEMElem, elem);
502 
503  edge1_to_tip = (edge_ends[0] * 0.95 + edge_ends[1] * 0.05) - crack_tip_origin;
504  edge2_to_tip = (edge_ends[0] * 0.05 + edge_ends[1] * 0.95) - crack_tip_origin;
505 
506  edge1_to_tip /= pow(edge1_to_tip.norm_sq(), 0.5);
507  edge2_to_tip /= pow(edge2_to_tip.norm_sq(), 0.5);
508 
509  edge1_to_tip_normal(0) = -edge1_to_tip(1);
510  edge1_to_tip_normal(1) = edge1_to_tip(0);
511 
512  edge2_to_tip_normal(0) = -edge2_to_tip(1);
513  edge2_to_tip_normal(1) = edge2_to_tip(0);
514 
515  Real angle_edge1_normal = edge1_to_tip_normal * normal;
516  Real angle_edge2_normal = edge2_to_tip_normal * normal;
517 
518  if (std::abs(angle_edge1_normal) > std::abs(angle_min) &&
519  (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
520  {
521  edge_id_keep = i;
522  distance_keep = 0.05;
523  normal_keep = edge1_to_tip_normal;
524  angle_min = angle_edge1_normal;
525  }
526  else if (std::abs(angle_edge2_normal) > std::abs(angle_min) &&
527  (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
528  {
529  edge_id_keep = i;
530  distance_keep = 0.95;
531  normal_keep = edge2_to_tip_normal;
532  angle_min = angle_edge2_normal;
533  }
534 
536  crack_tip_origin, left_angle_normal, edge_ends[0], edge_ends[1], distance) &&
537  (!CEMElem->isEdgePhantom(i)))
538  {
539  if (std::abs(left_angle_normal * normal) > std::abs(angle_min) &&
540  (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
541  {
542  edge_id_keep = i;
543  distance_keep = distance;
544  normal_keep = left_angle_normal;
545  angle_min = left_angle_normal * normal;
546  }
547  }
548  else if (initCutIntersectionEdge(
549  crack_tip_origin, right_angle_normal, edge_ends[0], edge_ends[1], distance) &&
550  (!CEMElem->isEdgePhantom(i)))
551  {
552  if (std::abs(right_angle_normal * normal) > std::abs(angle_min) &&
553  (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
554  {
555  edge_id_keep = i;
556  distance_keep = distance;
557  normal_keep = right_angle_normal;
558  angle_min = right_angle_normal * normal;
559  }
560  }
561  else if (initCutIntersectionEdge(crack_tip_origin,
562  crack_direction_normal,
563  edge_ends[0],
564  edge_ends[1],
565  distance) &&
566  (!CEMElem->isEdgePhantom(i)))
567  {
568  if (std::abs(crack_direction_normal * normal) > std::abs(angle_min) &&
569  (crack_tip_direction * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
570  {
571  edge_id_keep = i;
572  distance_keep = distance;
573  normal_keep = crack_direction_normal;
574  angle_min = crack_direction_normal * normal;
575  }
576  }
577  }
578  }
579 
580  // avoid small volume fraction cut
581  if ((distance_keep - 0.05) < 0.0)
582  {
583  distance_keep = 0.05;
584  }
585  else if ((distance_keep - 0.95) > 0.0)
586  {
587  distance_keep = 0.95;
588  }
589 }
bool isPartialOverlap(const EFAEdge &other) const
Definition: EFAEdge.C:59
PetscInt nsides
EFAEdge * getEdge(unsigned int edge_id) const
unsigned int numEdges() const
bool isEdgePhantom(unsigned int edge_id) const
Real distance(const Point &p)
bool initCutIntersectionEdge(Point cut_origin, RealVectorValue cut_normal, Point &edge_p1, Point &edge_p2, Real &dist)
Definition: XFEM.C:905
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
Point getEFANodeCoords(EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
Definition: XFEM.C:1603

◆ cutMeshWithEFA()

bool XFEM::cutMeshWithEFA ( const std::vector< std::shared_ptr< NonlinearSystemBase >> &  nl,
AuxiliarySystem aux 
)

Definition at line 1108 of file XFEM.C.

Referenced by update().

1110 {
1111  if (nls.size() != 1)
1112  mooseError("XFEM does not currently support multiple nonlinear systems");
1113 
1114  std::map<unsigned int, Node *> efa_id_to_new_node;
1115  std::map<unsigned int, Node *> efa_id_to_new_node2;
1116  std::map<unsigned int, Elem *> efa_id_to_new_elem;
1117  _cached_solution.clear();
1118  _cached_aux_solution.clear();
1119 
1120  // Copy the current geometric cut element info (from last time) into the
1121  // _old_geom_cut_elems.
1123  _geom_cut_elems.clear();
1124 
1126 
1127  if (_debug_output_level > 2)
1128  {
1129  _console << "\nXFEM Element fragment algorithm mesh prior to cutting:\n";
1130  _console << std::flush;
1131  _efa_mesh.printMesh();
1132  }
1133 
1135 
1136  if (_debug_output_level > 2)
1137  {
1138  _console << "\nXFEM Element fragment algorithm mesh after cutting:\n";
1139  _console << std::flush;
1140  _efa_mesh.printMesh();
1141  }
1142 
1143  const std::vector<EFANode *> new_nodes = _efa_mesh.getNewNodes();
1144  const std::vector<EFAElement *> new_elements = _efa_mesh.getChildElements();
1145  const std::vector<EFAElement *> delete_elements = _efa_mesh.getParentElements();
1146 
1147  bool mesh_changed = (new_nodes.size() + new_elements.size() + delete_elements.size() > 0);
1148 
1149  // Prepare to cache solution on DOFs modified by XFEM
1150  if (mesh_changed)
1151  {
1152  nls[0]->serializeSolution();
1153  aux.serializeSolution();
1154  if (_debug_output_level > 1)
1155  _console << "\n";
1156  }
1157  NumericVector<Number> & current_solution = *nls[0]->system().current_local_solution;
1158  NumericVector<Number> & old_solution = nls[0]->solutionOld();
1159  NumericVector<Number> & older_solution = nls[0]->solutionOlder();
1160  NumericVector<Number> & current_aux_solution = *aux.system().current_local_solution;
1161  NumericVector<Number> & old_aux_solution = aux.solutionOld();
1162  NumericVector<Number> & older_aux_solution = aux.solutionOlder();
1163 
1164  std::map<Node *, Node *> new_nodes_to_parents;
1165 
1166  // Add new nodes
1167  for (unsigned int i = 0; i < new_nodes.size(); ++i)
1168  {
1169  unsigned int new_node_id = new_nodes[i]->id();
1170  unsigned int parent_id = new_nodes[i]->parent()->id();
1171 
1172  Node * parent_node = _mesh->node_ptr(parent_id);
1173  Node * new_node = Node::build(*parent_node, _mesh->max_node_id()).release();
1174  _mesh->add_node(new_node);
1175 
1176  new_nodes_to_parents[new_node] = parent_node;
1177 
1178  new_node->set_n_systems(parent_node->n_systems());
1179  efa_id_to_new_node.insert(std::make_pair(new_node_id, new_node));
1180  if (_debug_output_level > 1)
1181  _console << "XFEM added new node: " << new_node->id() << std::endl;
1182  if (_displaced_mesh)
1183  {
1184  const Node * parent_node2 = _displaced_mesh->node_ptr(parent_id);
1185  Node * new_node2 = Node::build(*parent_node2, _displaced_mesh->max_node_id()).release();
1186  _displaced_mesh->add_node(new_node2);
1187 
1188  new_node2->set_n_systems(parent_node2->n_systems());
1189  efa_id_to_new_node2.insert(std::make_pair(new_node_id, new_node2));
1190  }
1191  }
1192 
1193  // Add new elements
1194  std::map<unsigned int, std::vector<const Elem *>> temporary_parent_children_map;
1195 
1196  std::vector<boundary_id_type> parent_boundary_ids;
1197 
1198  for (unsigned int i = 0; i < new_elements.size(); ++i)
1199  {
1200  unsigned int parent_id = new_elements[i]->getParent()->id();
1201  unsigned int efa_child_id = new_elements[i]->id();
1202 
1203  Elem * parent_elem = _mesh->elem_ptr(parent_id);
1204  Elem * libmesh_elem = Elem::build(parent_elem->type()).release();
1205 
1206  for (unsigned int m = 0; m < _geometric_cuts.size(); ++m)
1207  {
1208  for (auto & it : _sibling_elems[_geometric_cuts[m]->getInterfaceID()])
1209  {
1210  if (parent_elem == it.first)
1211  it.first = libmesh_elem;
1212  else if (parent_elem == it.second)
1213  it.second = libmesh_elem;
1214  }
1215  }
1216 
1217  // parent has at least two children
1218  if (new_elements[i]->getParent()->numChildren() > 1)
1219  temporary_parent_children_map[parent_elem->id()].push_back(libmesh_elem);
1220 
1221  Elem * parent_elem2 = nullptr;
1222  Elem * libmesh_elem2 = nullptr;
1223  if (_displaced_mesh)
1224  {
1225  parent_elem2 = _displaced_mesh->elem_ptr(parent_id);
1226  libmesh_elem2 = Elem::build(parent_elem2->type()).release();
1227 
1228  for (unsigned int m = 0; m < _geometric_cuts.size(); ++m)
1229  {
1230  for (auto & it : _sibling_displaced_elems[_geometric_cuts[m]->getInterfaceID()])
1231  {
1232  if (parent_elem2 == it.first)
1233  it.first = libmesh_elem2;
1234  else if (parent_elem2 == it.second)
1235  it.second = libmesh_elem2;
1236  }
1237  }
1238  }
1239 
1240  for (unsigned int j = 0; j < new_elements[i]->numNodes(); ++j)
1241  {
1242  unsigned int node_id = new_elements[i]->getNode(j)->id();
1243  Node * libmesh_node;
1244 
1245  std::map<unsigned int, Node *>::iterator nit = efa_id_to_new_node.find(node_id);
1246  if (nit != efa_id_to_new_node.end())
1247  libmesh_node = nit->second;
1248  else
1249  libmesh_node = _mesh->node_ptr(node_id);
1250 
1251  if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1252  libmesh_node->processor_id() = parent_elem->processor_id();
1253 
1254  libmesh_elem->set_node(j, libmesh_node);
1255 
1256  // Store solution for all nodes affected by XFEM (even existing nodes)
1257  if (parent_elem->is_semilocal(_mesh->processor_id()))
1258  {
1259  Node * solution_node = libmesh_node; // Node from which to store solution
1260  if (new_nodes_to_parents.find(libmesh_node) != new_nodes_to_parents.end())
1261  solution_node = new_nodes_to_parents[libmesh_node];
1262 
1263  if ((_moose_mesh->isSemiLocal(solution_node)) ||
1264  (libmesh_node->processor_id() == _mesh->processor_id()))
1265  {
1266  storeSolutionForNode(libmesh_node,
1267  solution_node,
1268  *nls[0],
1270  current_solution,
1271  old_solution,
1272  older_solution);
1273  storeSolutionForNode(libmesh_node,
1274  solution_node,
1275  aux,
1277  current_aux_solution,
1278  old_aux_solution,
1279  older_aux_solution);
1280  }
1281  }
1282 
1283  Node * parent_node = parent_elem->node_ptr(j);
1284  _mesh->get_boundary_info().boundary_ids(parent_node, parent_boundary_ids);
1285  _mesh->get_boundary_info().add_node(libmesh_node, parent_boundary_ids);
1286 
1287  if (_displaced_mesh)
1288  {
1289  std::map<unsigned int, Node *>::iterator nit2 = efa_id_to_new_node2.find(node_id);
1290  if (nit2 != efa_id_to_new_node2.end())
1291  libmesh_node = nit2->second;
1292  else
1293  libmesh_node = _displaced_mesh->node_ptr(node_id);
1294 
1295  if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1296  libmesh_node->processor_id() = parent_elem2->processor_id();
1297 
1298  libmesh_elem2->set_node(j, libmesh_node);
1299 
1300  parent_node = parent_elem2->node_ptr(j);
1301  _displaced_mesh->get_boundary_info().boundary_ids(parent_node, parent_boundary_ids);
1302  _displaced_mesh->get_boundary_info().add_node(libmesh_node, parent_boundary_ids);
1303  }
1304  }
1305 
1306  libmesh_elem->set_p_level(parent_elem->p_level());
1307  libmesh_elem->set_p_refinement_flag(parent_elem->p_refinement_flag());
1308  _mesh->add_elem(libmesh_elem);
1309  libmesh_elem->set_n_systems(parent_elem->n_systems());
1310  libmesh_elem->subdomain_id() = parent_elem->subdomain_id();
1311  libmesh_elem->processor_id() = parent_elem->processor_id();
1312 
1313  // The crack tip origin map is stored before cut, thus the elem should be updated with new
1314  // element.
1315  std::map<const Elem *, std::vector<Point>>::iterator mit =
1316  _elem_crack_origin_direction_map.find(parent_elem);
1317  if (mit != _elem_crack_origin_direction_map.end())
1318  {
1319  std::vector<Point> crack_data = _elem_crack_origin_direction_map[parent_elem];
1321  _elem_crack_origin_direction_map[libmesh_elem] = crack_data;
1322  }
1323 
1324  if (_debug_output_level > 1)
1325  _console << "XFEM added new element: " << libmesh_elem->id() << std::endl;
1326 
1327  XFEMCutElem * xfce = nullptr;
1328  if (_mesh->mesh_dimension() == 2)
1329  {
1330  EFAElement2D * new_efa_elem2d = dynamic_cast<EFAElement2D *>(new_elements[i]);
1331  if (!new_efa_elem2d)
1332  mooseError("EFAelem is not of EFAelement2D type");
1333  xfce = new XFEMCutElem2D(libmesh_elem,
1334  new_efa_elem2d,
1335  _fe_problem->assembly(0, /*nl_sys_num=*/0).qRule()->n_points(),
1336  libmesh_elem->n_sides());
1337  }
1338  else if (_mesh->mesh_dimension() == 3)
1339  {
1340  EFAElement3D * new_efa_elem3d = dynamic_cast<EFAElement3D *>(new_elements[i]);
1341  if (!new_efa_elem3d)
1342  mooseError("EFAelem is not of EFAelement3D type");
1343  xfce = new XFEMCutElem3D(libmesh_elem,
1344  new_efa_elem3d,
1345  _fe_problem->assembly(0, /*nl_sys_num=*/0).qRule()->n_points(),
1346  libmesh_elem->n_sides());
1347  }
1348  _cut_elem_map.insert(std::pair<unique_id_type, XFEMCutElem *>(libmesh_elem->unique_id(), xfce));
1349  efa_id_to_new_elem.insert(std::make_pair(efa_child_id, libmesh_elem));
1350 
1351  if (_displaced_mesh)
1352  {
1353  libmesh_elem2->set_p_level(parent_elem2->p_level());
1354  libmesh_elem2->set_p_refinement_flag(parent_elem2->p_refinement_flag());
1355  _displaced_mesh->add_elem(libmesh_elem2);
1356  libmesh_elem2->set_n_systems(parent_elem2->n_systems());
1357  libmesh_elem2->subdomain_id() = parent_elem2->subdomain_id();
1358  libmesh_elem2->processor_id() = parent_elem2->processor_id();
1359  }
1360 
1361  unsigned int n_sides = parent_elem->n_sides();
1362  for (unsigned int side = 0; side < n_sides; ++side)
1363  {
1364  _mesh->get_boundary_info().boundary_ids(parent_elem, side, parent_boundary_ids);
1365  _mesh->get_boundary_info().add_side(libmesh_elem, side, parent_boundary_ids);
1366  }
1367  if (_displaced_mesh)
1368  {
1369  n_sides = parent_elem2->n_sides();
1370  for (unsigned int side = 0; side < n_sides; ++side)
1371  {
1372  _displaced_mesh->get_boundary_info().boundary_ids(parent_elem2, side, parent_boundary_ids);
1373  _displaced_mesh->get_boundary_info().add_side(libmesh_elem2, side, parent_boundary_ids);
1374  }
1375  }
1376 
1377  unsigned int n_edges = parent_elem->n_edges();
1378  for (unsigned int edge = 0; edge < n_edges; ++edge)
1379  {
1380  _mesh->get_boundary_info().edge_boundary_ids(parent_elem, edge, parent_boundary_ids);
1381  _mesh->get_boundary_info().add_edge(libmesh_elem, edge, parent_boundary_ids);
1382  }
1383  if (_displaced_mesh)
1384  {
1385  n_edges = parent_elem2->n_edges();
1386  for (unsigned int edge = 0; edge < n_edges; ++edge)
1387  {
1388  _displaced_mesh->get_boundary_info().edge_boundary_ids(
1389  parent_elem2, edge, parent_boundary_ids);
1390  _displaced_mesh->get_boundary_info().add_edge(libmesh_elem2, edge, parent_boundary_ids);
1391  }
1392  }
1393 
1394  // TODO: Also need to copy neighbor material data
1395  if (parent_elem->processor_id() == _mesh->processor_id())
1396  {
1397  if (_material_data[0]->getMaterialPropertyStorage().hasStatefulProperties())
1398  _material_data[0]->copy(*libmesh_elem, *parent_elem, 0);
1399 
1400  if (_bnd_material_data[0]->getMaterialPropertyStorage().hasStatefulProperties())
1401  for (unsigned int side = 0; side < parent_elem->n_sides(); ++side)
1402  {
1403  _mesh->get_boundary_info().boundary_ids(parent_elem, side, parent_boundary_ids);
1404  std::vector<boundary_id_type>::iterator it_bd = parent_boundary_ids.begin();
1405  for (; it_bd != parent_boundary_ids.end(); ++it_bd)
1406  {
1407  if (_fe_problem->needBoundaryMaterialOnSide(*it_bd, 0))
1408  _bnd_material_data[0]->copy(*libmesh_elem, *parent_elem, side);
1409  }
1410  }
1411 
1412  // Store the current information about the geometrically cut element, and load cached material
1413  // properties into the new child element, if any.
1414  const GeometricCutUserObject * gcuo = getGeometricCutForElem(parent_elem);
1415  if (gcuo && gcuo->shouldHealMesh())
1416  {
1417  CutSubdomainID gcsid = getCutSubdomainID(gcuo, libmesh_elem, parent_elem);
1418  Xfem::CutElemInfo cei(parent_elem, gcuo, gcsid);
1419  _geom_cut_elems.emplace(libmesh_elem, cei);
1420  // Find the element to copy data from.
1421  // Iterate through the old geometrically cut elements, if its parent element AND the
1422  // geometric cut user object AND the cut subdomain ID are the same as the
1423  // current element, then that must be it.
1424  for (auto old_cei : _old_geom_cut_elems)
1425  if (cei.match(old_cei.second))
1426  {
1427  loadMaterialPropertiesForElement(libmesh_elem, old_cei.first, _old_geom_cut_elems);
1428  if (_debug_output_level > 1)
1429  _console << "XFEM set material properties for element: " << libmesh_elem->id()
1430  << "\n";
1431  break;
1432  }
1433  }
1434 
1435  // Store solution for all elements affected by XFEM
1436  storeSolutionForElement(libmesh_elem,
1437  parent_elem,
1438  *nls[0],
1440  current_solution,
1441  old_solution,
1442  older_solution);
1443  storeSolutionForElement(libmesh_elem,
1444  parent_elem,
1445  aux,
1447  current_aux_solution,
1448  old_aux_solution,
1449  older_aux_solution);
1450  }
1451  }
1452 
1453  // delete elements
1454  for (std::size_t i = 0; i < delete_elements.size(); ++i)
1455  {
1456  Elem * elem_to_delete = _mesh->elem_ptr(delete_elements[i]->id());
1457 
1458  // delete the XFEMCutElem object for any elements that are to be deleted
1459  std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
1460  _cut_elem_map.find(elem_to_delete->unique_id());
1461  if (cemit != _cut_elem_map.end())
1462  {
1463  delete cemit->second;
1464  _cut_elem_map.erase(cemit);
1465  }
1466 
1467  // remove the property storage of deleted element/side
1468  _material_data[0]->eraseProperty(elem_to_delete);
1469  _bnd_material_data[0]->eraseProperty(elem_to_delete);
1470 
1471  elem_to_delete->nullify_neighbors();
1472  _mesh->get_boundary_info().remove(elem_to_delete);
1473  unsigned int deleted_elem_id = elem_to_delete->id();
1474  _mesh->delete_elem(elem_to_delete);
1475  if (_debug_output_level > 1)
1476  _console << "XFEM deleted element: " << deleted_elem_id << std::endl;
1477 
1478  if (_displaced_mesh)
1479  {
1480  Elem * elem_to_delete2 = _displaced_mesh->elem_ptr(delete_elements[i]->id());
1481  elem_to_delete2->nullify_neighbors();
1482  _displaced_mesh->get_boundary_info().remove(elem_to_delete2);
1483  _displaced_mesh->delete_elem(elem_to_delete2);
1484  }
1485  }
1486 
1487  for (std::map<unsigned int, std::vector<const Elem *>>::iterator it =
1488  temporary_parent_children_map.begin();
1489  it != temporary_parent_children_map.end();
1490  ++it)
1491  {
1492  std::vector<const Elem *> & sibling_elem_vec = it->second;
1493  // TODO: for cut-node case, how to find the sibling elements?
1494  // if (sibling_elem_vec.size() != 2)
1495  // mooseError("Must have exactly 2 sibling elements");
1496 
1497  for (unsigned int i = 0; i < _geometric_cuts.size(); ++i)
1498  for (auto const & elem_id : _geom_marker_id_elems[_geometric_cuts[i]->getInterfaceID()])
1499  if (it->first == elem_id)
1500  _sibling_elems[_geometric_cuts[i]->getInterfaceID()].push_back(
1501  std::make_pair(sibling_elem_vec[0], sibling_elem_vec[1]));
1502  }
1503 
1504  // add sibling elems on displaced mesh
1505  if (_displaced_mesh)
1506  {
1507  for (unsigned int i = 0; i < _geometric_cuts.size(); ++i)
1508  {
1509  for (auto & se : _sibling_elems[_geometric_cuts[i]->getInterfaceID()])
1510  {
1511  Elem * elem = _displaced_mesh->elem_ptr(se.first->id());
1512  Elem * elem_pair = _displaced_mesh->elem_ptr(se.second->id());
1513  _sibling_displaced_elems[_geometric_cuts[i]->getInterfaceID()].push_back(
1514  std::make_pair(elem, elem_pair));
1515  }
1516  }
1517  }
1518 
1519  // clear the temporary map
1520  temporary_parent_children_map.clear();
1521 
1522  // Store information about crack tip elements
1523  if (mesh_changed)
1524  {
1525  _crack_tip_elems.clear();
1527  const std::set<EFAElement *> CrackTipElements = _efa_mesh.getCrackTipElements();
1528  std::set<EFAElement *>::const_iterator sit;
1529  for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
1530  {
1531  unsigned int eid = (*sit)->id();
1532  Elem * crack_tip_elem;
1533  std::map<unsigned int, Elem *>::iterator eit = efa_id_to_new_elem.find(eid);
1534  if (eit != efa_id_to_new_elem.end())
1535  crack_tip_elem = eit->second;
1536  else
1537  crack_tip_elem = _mesh->elem_ptr(eid);
1538  _crack_tip_elems.insert(crack_tip_elem);
1539 
1540  // Store the crack tip elements which are going to be healed
1541  for (unsigned int i = 0; i < _geometric_cuts.size(); ++i)
1542  {
1543  if (_geometric_cuts[i]->shouldHealMesh())
1544  {
1545  for (auto const & mie : _geom_marker_id_elems[_geometric_cuts[i]->getInterfaceID()])
1546  if ((*sit)->getParent() != nullptr)
1547  {
1548  if (_mesh->mesh_dimension() == 2)
1549  {
1550  EFAElement2D * efa_elem2d = dynamic_cast<EFAElement2D *>((*sit)->getParent());
1551  if (!efa_elem2d)
1552  mooseError("EFAelem is not of EFAelement2D type");
1553 
1554  for (unsigned int edge_id = 0; edge_id < efa_elem2d->numEdges(); ++edge_id)
1555  {
1556  for (unsigned int en_iter = 0; en_iter < efa_elem2d->numEdgeNeighbors(edge_id);
1557  ++en_iter)
1558  {
1559  EFAElement2D * edge_neighbor = efa_elem2d->getEdgeNeighbor(edge_id, en_iter);
1560  if (edge_neighbor != nullptr && edge_neighbor->id() == mie)
1561  _crack_tip_elems_to_be_healed.insert(crack_tip_elem);
1562  }
1563  }
1564  }
1565  else if (_mesh->mesh_dimension() == 3)
1566  {
1567  EFAElement3D * efa_elem3d = dynamic_cast<EFAElement3D *>((*sit)->getParent());
1568  if (!efa_elem3d)
1569  mooseError("EFAelem is not of EFAelement3D type");
1570 
1571  for (unsigned int face_id = 0; face_id < efa_elem3d->numFaces(); ++face_id)
1572  {
1573  for (unsigned int fn_iter = 0; fn_iter < efa_elem3d->numFaceNeighbors(face_id);
1574  ++fn_iter)
1575  {
1576  EFAElement3D * face_neighbor = efa_elem3d->getFaceNeighbor(face_id, fn_iter);
1577  if (face_neighbor != nullptr && face_neighbor->id() == mie)
1578  _crack_tip_elems_to_be_healed.insert(crack_tip_elem);
1579  }
1580  }
1581  }
1582  }
1583  }
1584  }
1585  }
1586  }
1587 
1588  if (_debug_output_level > 0)
1589  {
1590  _console << "\nXFEM mesh cutting with element fragment algorithm complete\n";
1591  _console << "# new nodes: " << new_nodes.size() << "\n";
1592  _console << "# new elements: " << new_elements.size() << "\n";
1593  _console << "# deleted elements: " << delete_elements.size() << "\n";
1594  _console << std::flush;
1595  }
1596 
1597  // store virtual nodes
1598  // store cut edge info
1599  return mesh_changed;
1600 }
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
Definition: XFEM.h:369
const GeometricCutUserObject * getGeometricCutForElem(const Elem *elem) const
Get the GeometricCutUserObject associated with an element.
Definition: XFEM.C:2180
unsigned int numEdgeNeighbors(unsigned int edge_id) const
EFAElement3D * getFaceNeighbor(unsigned int face_id, unsigned int neighbor_id) const
CutSubdomainID getCutSubdomainID(const GeometricCutUserObject *gcuo, const Elem *cut_elem, const Elem *parent_elem=nullptr) const
Determine which cut subdomain the element belongs to relative to the cut.
Definition: XFEM.C:2296
std::vector< const GeometricCutUserObject * > _geometric_cuts
Definition: XFEM.h:334
unsigned int id() const
Definition: EFAElement.C:28
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_elems
Definition: XFEM.h:339
bool shouldHealMesh() const
Should the elements cut by this cutting object be healed in the current time step?
void mooseError(Args &&... args)
bool isSemiLocal(Node *const node) const
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_displaced_elems
Definition: XFEM.h:340
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
const std::vector< EFAElement * > & getChildElements()
std::set< const Elem * > _crack_tip_elems
Definition: XFEM.h:337
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
NumericVector< Number > & solutionOlder()
unsigned int numEdges() const
std::set< const Elem * > _crack_tip_elems_to_be_healed
Definition: XFEM.h:338
std::map< unique_id_type, std::vector< Real > > _cached_aux_solution
Data structure to store the auxiliary solution for nodes/elements affected by XFEM For each node/elem...
Definition: XFEM.h:391
unsigned int numFaces() const
unsigned int CutSubdomainID
Definition: XFEMAppTypes.h:15
FEProblemBase * _fe_problem
std::vector< MaterialData *> _bnd_material_data
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
void updateTopology(bool mergeUncutVirtualEdges=true)
const std::vector< EFAElement * > & getParentElements()
void loadMaterialPropertiesForElement(const Elem *elem, const Elem *elem_from, std::unordered_map< const Elem *, Xfem::CutElemInfo > &cached_cei) const
Helper function to store the material properties of a healed element.
Definition: XFEM.C:2262
const std::vector< EFANode * > & getNewNodes()
std::vector< MaterialData *> _material_data
void storeSolutionForElement(const Elem *elem_to_store_to, const Elem *elem_to_store_from, SystemBase &sys, std::map< unique_id_type, std::vector< Real >> &stored_solution, const NumericVector< Number > &current_solution, const NumericVector< Number > &old_solution, const NumericVector< Number > &older_solution)
Store the solution in stored_solution for a given element.
Definition: XFEM.C:2027
unsigned int n_points() const
void storeSolutionForNode(const Node *node_to_store_to, const Node *node_to_store_from, SystemBase &sys, std::map< unique_id_type, std::vector< Real >> &stored_solution, const NumericVector< Number > &current_solution, const NumericVector< Number > &old_solution, const NumericVector< Number > &older_solution)
Store the solution in stored_solution for a given node.
Definition: XFEM.C:1993
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
Definition: XFEM.h:342
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
Definition: XFEM.h:357
MeshBase * _mesh
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
MooseMesh * _moose_mesh
MeshBase * _displaced_mesh
const libMesh::QBase *const & qRule() const
std::unique_ptr< NumericVector< Number > > current_local_solution
std::map< unique_id_type, std::vector< Real > > _cached_solution
Data structure to store the nonlinear solution for nodes/elements affected by XFEM For each node/elem...
Definition: XFEM.h:382
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const ConsoleStream _console
virtual void serializeSolution()
virtual libMesh::System & system() override
NumericVector< Number > & solutionOld()
Information about a cut element.
Definition: XFEM.h:57
const std::set< EFAElement * > & getCrackTipElements()
unsigned int numFaceNeighbors(unsigned int face_id) const
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK...
Definition: XFEM.h:397
std::unordered_map< const Elem *, Xfem::CutElemInfo > _old_geom_cut_elems
All geometrically cut elements and their CutElemInfo before the current execution of XFEM_MARK...
Definition: XFEM.h:403

◆ getCrackTipOrigin()

void XFEM::getCrackTipOrigin ( std::map< unsigned int, const Elem *> &  elem_id_crack_tip,
std::vector< Point > &  crack_front_points 
)

Definition at line 68 of file XFEM.C.

70 {
71  elem_id_crack_tip.clear();
72  crack_front_points.clear();
73  crack_front_points.resize(_elem_crack_origin_direction_map.size());
74 
75  unsigned int crack_tip_index = 0;
76  // This map is used to sort the order in _elem_crack_origin_direction_map such that every process
77  // has same order
78  std::map<unsigned int, const Elem *> elem_id_map;
79 
80  int m = -1;
81  for (std::map<const Elem *, std::vector<Point>>::iterator mit1 =
84  ++mit1)
85  {
86  unsigned int elem_id = mit1->first->id();
87  if (elem_id == std::numeric_limits<unsigned int>::max())
88  {
89  elem_id_map[m] = mit1->first;
90  m--;
91  }
92  else
93  elem_id_map[elem_id] = mit1->first;
94  }
95 
96  for (std::map<unsigned int, const Elem *>::iterator mit1 = elem_id_map.begin();
97  mit1 != elem_id_map.end();
98  mit1++)
99  {
100  const Elem * elem = mit1->second;
101  std::map<const Elem *, std::vector<Point>>::iterator mit2 =
103  if (mit2 != _elem_crack_origin_direction_map.end())
104  {
105  elem_id_crack_tip[crack_tip_index] = mit2->first;
106  crack_front_points[crack_tip_index] =
107  (mit2->second)[0]; // [0] stores origin coordinates and [1] stores direction
108  crack_tip_index++;
109  }
110  }
111 }
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
Definition: XFEM.h:342

◆ getCrackTipOriginMap()

const std::map<const Elem *, std::vector<Point> >& XFEM::getCrackTipOriginMap ( ) const
inline

Definition at line 311 of file XFEM.h.

312  {
314  }
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
Definition: XFEM.h:342

◆ getCutPlane()

Real XFEM::getCutPlane ( const Elem *  elem,
const Xfem::XFEM_CUTPLANE_QUANTITY  quantity,
unsigned int  plane_id 
) const

Get specified component of normal or origin for cut plane for a given element.

Definition at line 1673 of file XFEM.C.

1676 {
1677  Real comp = 0.0;
1678  Point planedata(0.0, 0.0, 0.0);
1679  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1680  it = _cut_elem_map.find(elem->unique_id());
1681  if (it != _cut_elem_map.end())
1682  {
1683  const XFEMCutElem * xfce = it->second;
1684  const EFAElement * EFAelem = xfce->getEFAElement();
1685  if (EFAelem->isPartial()) // exclude the full crack tip elements
1686  {
1687  if ((unsigned int)quantity < 3)
1688  {
1689  unsigned int index = (unsigned int)quantity;
1690  planedata = xfce->getCutPlaneOrigin(plane_id, _displaced_mesh);
1691  comp = planedata(index);
1692  }
1693  else if ((unsigned int)quantity < 6)
1694  {
1695  unsigned int index = (unsigned int)quantity - 3;
1696  planedata = xfce->getCutPlaneNormal(plane_id, _displaced_mesh);
1697  comp = planedata(index);
1698  }
1699  else
1700  mooseError("In get_cut_plane index out of range");
1701  }
1702  }
1703  return comp;
1704 }
void mooseError(Args &&... args)
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
virtual bool isPartial() const =0
virtual const EFAElement * getEFAElement() const =0
virtual Point getCutPlaneOrigin(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MeshBase * _displaced_mesh
virtual Point getCutPlaneNormal(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
void ErrorVector unsigned int

◆ getCutSubdomainID()

CutSubdomainID XFEM::getCutSubdomainID ( const GeometricCutUserObject gcuo,
const Elem *  cut_elem,
const Elem *  parent_elem = nullptr 
) const

Determine which cut subdomain the element belongs to relative to the cut.

Parameters
gcuoThe GeometricCutUserObject for the cut
cut_elemThe element being cut
parent_elemThe parent element

Definition at line 2296 of file XFEM.C.

Referenced by cutMeshWithEFA().

2299 {
2300  if (!parent_elem)
2301  parent_elem = cut_elem;
2302  // Pick any node from the parent element that is inside the physical domain and return its
2303  // CutSubdomainID.
2304  const Node * node = pickFirstPhysicalNode(cut_elem, parent_elem);
2305  return gcuo->getCutSubdomainID(node);
2306 }
const Node * pickFirstPhysicalNode(const Elem *e, const Elem *e0) const
Return the first node in the provided element that is found to be in the physical domain...
Definition: XFEM.C:2309
virtual CutSubdomainID getCutSubdomainID(const Node *) const
Get CutSubdomainID telling which side the node belongs to relative to the cut.

◆ getEFAElem2D()

EFAElement2D * XFEM::getEFAElem2D ( const Elem *  elem)

Get the EFAElement2D object for a specified libMesh element.

Parameters
elemPointer to the libMesh element for which the object is requested

Definition at line 1753 of file XFEM.C.

Referenced by markCutEdgesByGeometry(), and markCutEdgesByState().

1754 {
1755  EFAElement * EFAelem = _efa_mesh.getElemByID(elem->id());
1756  EFAElement2D * EFAelem2D = dynamic_cast<EFAElement2D *>(EFAelem);
1757 
1758  if (!EFAelem2D)
1759  mooseError("EFAelem is not of EFAelement2D type");
1760 
1761  return EFAelem2D;
1762 }
void mooseError(Args &&... args)
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
EFAElement * getElemByID(unsigned int id)

◆ getEFAElem3D()

EFAElement3D * XFEM::getEFAElem3D ( const Elem *  elem)

Get the EFAElement3D object for a specified libMesh element.

Parameters
elemPointer to the libMesh element for which the object is requested

Definition at line 1765 of file XFEM.C.

Referenced by markCutFacesByGeometry().

1766 {
1767  EFAElement * EFAelem = _efa_mesh.getElemByID(elem->id());
1768  EFAElement3D * EFAelem3D = dynamic_cast<EFAElement3D *>(EFAelem);
1769 
1770  if (!EFAelem3D)
1771  mooseError("EFAelem is not of EFAelement3D type");
1772 
1773  return EFAelem3D;
1774 }
void mooseError(Args &&... args)
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
EFAElement * getElemByID(unsigned int id)

◆ getEFANodeCoords()

Point XFEM::getEFANodeCoords ( EFANode CEMnode,
EFAElement CEMElem,
const Elem *  elem,
MeshBase *  displaced_mesh = nullptr 
) const

Definition at line 1603 of file XFEM.C.

Referenced by correctCrackExtensionDirection(), getFragmentEdges(), getFragmentFaces(), and markCutEdgesByState().

1607 {
1608  Point node_coor(0.0, 0.0, 0.0);
1609  std::vector<EFANode *> master_nodes;
1610  std::vector<Point> master_points;
1611  std::vector<double> master_weights;
1612 
1613  CEMElem->getMasterInfo(CEMnode, master_nodes, master_weights);
1614  for (std::size_t i = 0; i < master_nodes.size(); ++i)
1615  {
1616  if (master_nodes[i]->category() == EFANode::N_CATEGORY_PERMANENT)
1617  {
1618  unsigned int local_node_id = CEMElem->getLocalNodeIndex(master_nodes[i]);
1619  const Node * node = elem->node_ptr(local_node_id);
1620  if (displaced_mesh)
1621  node = displaced_mesh->node_ptr(node->id());
1622  Point node_p((*node)(0), (*node)(1), (*node)(2));
1623  master_points.push_back(node_p);
1624  }
1625  else
1626  mooseError("master nodes must be permanent");
1627  }
1628  for (std::size_t i = 0; i < master_nodes.size(); ++i)
1629  node_coor += master_weights[i] * master_points[i];
1630 
1631  return node_coor;
1632 }
void mooseError(Args &&... args)
virtual void getMasterInfo(EFANode *node, std::vector< EFANode *> &master_nodes, std::vector< double > &master_weights) const =0
unsigned int getLocalNodeIndex(EFANode *node) const
Definition: EFAElement.C:111

◆ getElementSolutionDofs()

std::vector< dof_id_type > XFEM::getElementSolutionDofs ( const Elem *  elem,
SystemBase sys 
) const
private

Get a vector of the dof indices for all components of all variables associated with an element.

Parameters
elemElement for which dof indices are found
sysSystem for which the dof indices are found

Definition at line 2122 of file XFEM.C.

Referenced by setSolution(), and storeSolutionForElement().

2123 {
2124  SubdomainID sid = elem->subdomain_id();
2125  const std::vector<MooseVariableFEBase *> & vars = sys.getVariables(0);
2126  std::vector<dof_id_type> solution_dofs;
2127  solution_dofs.reserve(vars.size()); // just an approximation
2128  for (auto var : vars)
2129  {
2130  if (!var->isNodal())
2131  {
2132  const std::set<SubdomainID> & var_subdomains = sys.getSubdomainsForVar(var->number());
2133  if (var_subdomains.empty() || var_subdomains.find(sid) != var_subdomains.end())
2134  {
2135  unsigned int n_comp = elem->n_comp(sys.number(), var->number());
2136  for (unsigned int icomp = 0; icomp < n_comp; ++icomp)
2137  {
2138  dof_id_type elem_dof = elem->dof_number(sys.number(), var->number(), icomp);
2139  solution_dofs.push_back(elem_dof);
2140  }
2141  }
2142  }
2143  }
2144  return solution_dofs;
2145 }
const std::vector< MooseVariableFieldBase *> & getVariables(THREAD_ID tid)
char ** vars
unsigned int number() const
const std::set< SubdomainID > & getSubdomainsForVar(unsigned int var_number) const
uint8_t dof_id_type

◆ getFragmentEdges()

void XFEM::getFragmentEdges ( const Elem *  elem,
EFAElement2D CEMElem,
std::vector< std::vector< Point >> &  frag_edges 
) const

Definition at line 1777 of file XFEM.C.

1780 {
1781  // N.B. CEMElem here has global EFAnode
1782  frag_edges.clear();
1783  if (CEMElem->numFragments() > 0)
1784  {
1785  if (CEMElem->numFragments() > 1)
1786  mooseError("element ", elem->id(), " has more than one fragment at this point");
1787  for (unsigned int i = 0; i < CEMElem->getFragment(0)->numEdges(); ++i)
1788  {
1789  std::vector<Point> p_line(2, Point(0.0, 0.0, 0.0));
1790  p_line[0] = getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(0), CEMElem, elem);
1791  p_line[1] = getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(1), CEMElem, elem);
1792  frag_edges.push_back(p_line);
1793  }
1794  }
1795 }
void mooseError(Args &&... args)
unsigned int numEdges() const
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
EFAFragment2D * getFragment(unsigned int frag_id) const
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
Point getEFANodeCoords(EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
Definition: XFEM.C:1603
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const

◆ getFragmentFaces() [1/2]

void XFEM::getFragmentFaces ( const Elem *  elem,
std::vector< std::vector< Point >> &  frag_faces,
bool  displaced_mesh = false 
) const

Definition at line 1736 of file XFEM.C.

1739 {
1740  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1741  it = _cut_elem_map.find(elem->unique_id());
1742  if (it != _cut_elem_map.end())
1743  {
1744  const XFEMCutElem * xfce = it->second;
1745  if (displaced_mesh)
1746  xfce->getFragmentFaces(frag_faces, _displaced_mesh);
1747  else
1748  xfce->getFragmentFaces(frag_faces);
1749  }
1750 }
virtual void getFragmentFaces(std::vector< std::vector< Point >> &frag_faces, MeshBase *displaced_mesh=nullptr) const =0
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
MeshBase * _displaced_mesh

◆ getFragmentFaces() [2/2]

void XFEM::getFragmentFaces ( const Elem *  elem,
EFAElement3D CEMElem,
std::vector< std::vector< Point >> &  frag_faces 
) const

Definition at line 1798 of file XFEM.C.

1801 {
1802  // N.B. CEMElem here has global EFAnode
1803  frag_faces.clear();
1804  if (CEMElem->numFragments() > 0)
1805  {
1806  if (CEMElem->numFragments() > 1)
1807  mooseError("element ", elem->id(), " has more than one fragment at this point");
1808  for (unsigned int i = 0; i < CEMElem->getFragment(0)->numFaces(); ++i)
1809  {
1810  unsigned int num_face_nodes = CEMElem->getFragmentFace(0, i)->numNodes();
1811  std::vector<Point> p_line(num_face_nodes, Point(0.0, 0.0, 0.0));
1812  for (unsigned int j = 0; j < num_face_nodes; ++j)
1813  p_line[j] = getEFANodeCoords(CEMElem->getFragmentFace(0, i)->getNode(j), CEMElem, elem);
1814  frag_faces.push_back(p_line);
1815  }
1816  }
1817 }
EFAFragment3D * getFragment(unsigned int frag_id) const
void mooseError(Args &&... args)
virtual unsigned int numFragments() const
Definition: EFAElement3D.C:272
EFANode * getNode(unsigned int node_id) const
Definition: EFAFace.C:99
unsigned int numNodes() const
Definition: EFAFace.C:87
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
EFAFace * getFragmentFace(unsigned int frag_id, unsigned int face_id) const
Point getEFANodeCoords(EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
Definition: XFEM.C:1603
unsigned int numFaces() const

◆ getGeometricCutForElem()

const GeometricCutUserObject * XFEM::getGeometricCutForElem ( const Elem *  elem) const
private

Get the GeometricCutUserObject associated with an element.

Parameters
elemThe element
Returns
A constant pointer to the GeometricCutUserObject, nullptr if nothing found

Definition at line 2180 of file XFEM.C.

Referenced by cutMeshWithEFA().

2181 {
2182  for (auto gcmit : _geom_marker_id_elems)
2183  {
2184  std::set<unsigned int> elems = gcmit.second;
2185  if (elems.find(elem->id()) != elems.end())
2186  return _geometric_cuts[gcmit.first];
2187  }
2188  return nullptr;
2189 }
std::vector< const GeometricCutUserObject * > _geometric_cuts
Definition: XFEM.h:334
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
Definition: XFEM.h:357

◆ getGeometricCutID()

virtual unsigned int XFEM::getGeometricCutID ( const GeometricCutUserObject gcu)
inlinevirtual

Get the interface ID corresponding to a given GeometricCutUserObject.

Parameters
gcupointer to the GeometricCutUserObject
Returns
the interface ID

Definition at line 274 of file XFEM.h.

275  {
276  return _geom_marker_id_map[gcu];
277  };
std::map< const GeometricCutUserObject *, unsigned int > _geom_marker_id_map
Data structure for storing the GeommetricCutUserObjects and their corresponding id.
Definition: XFEM.h:360

◆ getNodeSolutionDofs()

std::vector< dof_id_type > XFEM::getNodeSolutionDofs ( const Node *  node,
SystemBase sys 
) const
private

Get a vector of the dof indices for all components of all variables associated with a node.

Parameters
nodeNode for which dof indices are found
sysSystem for which the dof indices are found

Definition at line 2148 of file XFEM.C.

Referenced by setSolution(), and storeSolutionForNode().

2149 {
2150  const std::set<SubdomainID> & sids = _moose_mesh->getNodeBlockIds(*node);
2151  const std::vector<MooseVariableFEBase *> & vars = sys.getVariables(0);
2152  std::vector<dof_id_type> solution_dofs;
2153  solution_dofs.reserve(vars.size()); // just an approximation
2154  for (auto var : vars)
2155  {
2156  if (var->isNodal())
2157  {
2158  const std::set<SubdomainID> & var_subdomains = sys.getSubdomainsForVar(var->number());
2159  std::set<SubdomainID> intersect;
2160  set_intersection(var_subdomains.begin(),
2161  var_subdomains.end(),
2162  sids.begin(),
2163  sids.end(),
2164  std::inserter(intersect, intersect.begin()));
2165  if (var_subdomains.empty() || !intersect.empty())
2166  {
2167  unsigned int n_comp = node->n_comp(sys.number(), var->number());
2168  for (unsigned int icomp = 0; icomp < n_comp; ++icomp)
2169  {
2170  dof_id_type node_dof = node->dof_number(sys.number(), var->number(), icomp);
2171  solution_dofs.push_back(node_dof);
2172  }
2173  }
2174  }
2175  }
2176  return solution_dofs;
2177 }
const std::vector< MooseVariableFieldBase *> & getVariables(THREAD_ID tid)
char ** vars
const std::set< SubdomainID > & getNodeBlockIds(const Node &node) const
unsigned int number() const
MooseMesh * _moose_mesh
const std::set< SubdomainID > & getSubdomainsForVar(unsigned int var_number) const
uint8_t dof_id_type

◆ getPhysicalVolumeFraction()

Real XFEM::getPhysicalVolumeFraction ( const Elem *  elem) const

Get the volume fraction of an element that is physical.

Definition at line 1635 of file XFEM.C.

Referenced by markCutEdgesByState().

1636 {
1637  Real phys_volfrac = 1.0;
1638  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1639  it = _cut_elem_map.find(elem->unique_id());
1640  if (it != _cut_elem_map.end())
1641  {
1642  XFEMCutElem * xfce = it->second;
1643  const EFAElement * EFAelem = xfce->getEFAElement();
1644  if (EFAelem->isPartial())
1645  { // exclude the full crack tip elements
1647  phys_volfrac = xfce->getPhysicalVolumeFraction();
1648  }
1649  }
1650 
1651  return phys_volfrac;
1652 }
Real getPhysicalVolumeFraction() const
Returns the volume fraction of the element fragment.
Definition: XFEMCutElem.C:51
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
virtual bool isPartial() const =0
virtual const EFAElement * getEFAElement() const =0
virtual void computePhysicalVolumeFraction()=0
Computes the volume fraction of the element fragment.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ getXFEMCutElemPairs()

virtual const ElementPairLocator::ElementPairList* XFEM::getXFEMCutElemPairs ( unsigned int  interface_id)
inlinevirtual

Get the list of cut element pairs corresponding to a given interface ID.

Parameters
interface_idThe ID of the interface
Returns
the list of elements cut by that interface

Definition at line 252 of file XFEM.h.

253  {
254  return &_sibling_elems[interface_id];
255  }
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_elems
Definition: XFEM.h:339

◆ getXFEMDisplacedCutElemPairs()

virtual const ElementPairLocator::ElementPairList* XFEM::getXFEMDisplacedCutElemPairs ( unsigned int  interface_id)
inlinevirtual

Get the list of cut element pairs on the displaced mesh corresponding to a given interface ID.

Parameters
interface_idThe ID of the interface
Returns
the list of elements cut by that interface

Definition at line 264 of file XFEM.h.

265  {
266  return &_sibling_displaced_elems[interface_id];
267  }
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_displaced_elems
Definition: XFEM.h:340

◆ getXFEMFaceWeights()

bool XFEM::getXFEMFaceWeights ( MooseArray< Real > &  weights,
const Elem *  elem,
QBase *  qrule,
const MooseArray< Point > &  q_points,
unsigned int  side 
)
overridevirtual

Definition at line 1885 of file XFEM.C.

1890 {
1891  bool have_weights = false;
1892  XFEMCutElem * xfce = nullptr;
1893  if (isElemCut(elem, xfce))
1894  {
1895  mooseAssert(xfce != nullptr, "Must have valid XFEMCutElem object here");
1896  xfce->getFaceWeightMultipliers(weights, qrule, getXFEMQRule(), q_points, side);
1897  have_weights = true;
1898  }
1899  return have_weights;
1900 }
void getFaceWeightMultipliers(MooseArray< Real > &face_weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points, unsigned int side)
Definition: XFEMCutElem.C:77
Xfem::XFEM_QRULE & getXFEMQRule()
Definition: XFEM.C:1820
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition: XFEM.C:1713

◆ getXFEMIntersectionInfo()

void XFEM::getXFEMIntersectionInfo ( const Elem *  elem,
unsigned int  plane_id,
Point &  normal,
std::vector< Point > &  intersectionPoints,
bool  displaced_mesh = false 
) const
virtual

Definition at line 1903 of file XFEM.C.

1908 {
1909  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1910  it = _cut_elem_map.find(elem->unique_id());
1911  if (it != _cut_elem_map.end())
1912  {
1913  const XFEMCutElem * xfce = it->second;
1914  if (displaced_mesh)
1915  xfce->getIntersectionInfo(plane_id, normal, intersectionPoints, _displaced_mesh);
1916  else
1917  xfce->getIntersectionInfo(plane_id, normal, intersectionPoints);
1918  }
1919 }
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
virtual void getIntersectionInfo(unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, MeshBase *displaced_mesh=nullptr) const =0
MeshBase * _displaced_mesh

◆ getXFEMQRule()

Xfem::XFEM_QRULE & XFEM::getXFEMQRule ( )

Definition at line 1820 of file XFEM.C.

Referenced by getXFEMFaceWeights(), and getXFEMWeights().

1821 {
1822  return _XFEM_qrule;
1823 }
Xfem::XFEM_QRULE _XFEM_qrule
Definition: XFEM.h:329

◆ getXFEMqRuleOnLine()

void XFEM::getXFEMqRuleOnLine ( std::vector< Point > &  intersection_points,
std::vector< Point > &  quad_pts,
std::vector< Real > &  quad_wts 
) const
virtual

Definition at line 1922 of file XFEM.C.

1925 {
1926  Point p1 = intersection_points[0];
1927  Point p2 = intersection_points[1];
1928 
1929  // number of quadrature points
1930  std::size_t num_qpoints = 2;
1931 
1932  // quadrature coordinates
1933  Real xi0 = -std::sqrt(1.0 / 3.0);
1934  Real xi1 = std::sqrt(1.0 / 3.0);
1935 
1936  quad_wts.resize(num_qpoints);
1937  quad_pts.resize(num_qpoints);
1938 
1939  Real integ_jacobian = pow((p1 - p2).norm_sq(), 0.5) * 0.5;
1940 
1941  quad_wts[0] = 1.0 * integ_jacobian;
1942  quad_wts[1] = 1.0 * integ_jacobian;
1943 
1944  quad_pts[0] = (1.0 - xi0) / 2.0 * p1 + (1.0 + xi0) / 2.0 * p2;
1945  quad_pts[1] = (1.0 - xi1) / 2.0 * p1 + (1.0 + xi1) / 2.0 * p2;
1946 }
auto norm_sq(const T &a)
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ getXFEMqRuleOnSurface()

void XFEM::getXFEMqRuleOnSurface ( std::vector< Point > &  intersection_points,
std::vector< Point > &  quad_pts,
std::vector< Real > &  quad_wts 
) const
virtual

Definition at line 1949 of file XFEM.C.

1952 {
1953  std::size_t nnd_pe = intersection_points.size();
1954  Point xcrd(0.0, 0.0, 0.0);
1955  for (std::size_t i = 0; i < nnd_pe; ++i)
1956  xcrd += intersection_points[i];
1957  xcrd /= nnd_pe;
1958 
1959  quad_pts.resize(nnd_pe);
1960  quad_wts.resize(nnd_pe);
1961 
1962  Real jac = 0.0;
1963 
1964  for (std::size_t j = 0; j < nnd_pe; ++j) // loop all sub-tris
1965  {
1966  std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
1967  std::vector<Point> subtrig_points(3, Point(0.0, 0.0, 0.0)); // sub-trig nodal coords
1968 
1969  int jplus1 = j < nnd_pe - 1 ? j + 1 : 0;
1970  subtrig_points[0] = xcrd;
1971  subtrig_points[1] = intersection_points[j];
1972  subtrig_points[2] = intersection_points[jplus1];
1973 
1974  std::vector<std::vector<Real>> sg2;
1975  Xfem::stdQuadr2D(3, 1, sg2); // get sg2
1976  for (std::size_t l = 0; l < sg2.size(); ++l) // loop all int pts on a sub-trig
1977  {
1978  Xfem::shapeFunc2D(3, sg2[l], subtrig_points, shape, jac, true); // Get shape
1979  std::vector<Real> tsg_line(3, 0.0);
1980  for (std::size_t k = 0; k < 3; ++k) // loop sub-trig nodes
1981  {
1982  tsg_line[0] += shape[k][2] * subtrig_points[k](0);
1983  tsg_line[1] += shape[k][2] * subtrig_points[k](1);
1984  tsg_line[2] += shape[k][2] * subtrig_points[k](2);
1985  }
1986  quad_pts[j + l] = Point(tsg_line[0], tsg_line[1], tsg_line[2]);
1987  quad_wts[j + l] = sg2[l][3] * jac;
1988  }
1989  }
1990 }
void shapeFunc2D(unsigned int nen, std::vector< Real > &ss, std::vector< Point > &xl, std::vector< std::vector< Real >> &shp, Real &xsj, bool natl_flg)
Definition: XFEMFuncs.C:269
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void stdQuadr2D(unsigned int nen, unsigned int iord, std::vector< std::vector< Real >> &sg2)
Definition: XFEMFuncs.C:96
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:134

◆ getXFEMWeights()

bool XFEM::getXFEMWeights ( MooseArray< Real > &  weights,
const Elem *  elem,
QBase *  qrule,
const MooseArray< Point > &  q_points 
)
overridevirtual

Definition at line 1856 of file XFEM.C.

1860 {
1861  bool have_weights = false;
1862  XFEMCutElem * xfce = nullptr;
1863  if (isElemCut(elem, xfce))
1864  {
1865  mooseAssert(xfce != nullptr, "Must have valid XFEMCutElem object here");
1866  xfce->getWeightMultipliers(weights, qrule, getXFEMQRule(), q_points);
1867  have_weights = true;
1868 
1869  Real ave_weight_multiplier = 0;
1870  for (unsigned int i = 0; i < weights.size(); ++i)
1871  ave_weight_multiplier += weights[i];
1872  ave_weight_multiplier /= weights.size();
1873 
1874  if (ave_weight_multiplier < _min_weight_multiplier)
1875  {
1876  const Real amount_to_add = _min_weight_multiplier - ave_weight_multiplier;
1877  for (unsigned int i = 0; i < weights.size(); ++i)
1878  weights[i] += amount_to_add;
1879  }
1880  }
1881  return have_weights;
1882 }
unsigned int size() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Xfem::XFEM_QRULE & getXFEMQRule()
Definition: XFEM.C:1820
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition: XFEM.C:1713
void getWeightMultipliers(MooseArray< Real > &weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points)
Definition: XFEMCutElem.C:63
Real _min_weight_multiplier
The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partia...
Definition: XFEM.h:373

◆ has_secondary_cut()

bool XFEM::has_secondary_cut ( )
inline

Definition at line 290 of file XFEM.h.

290 { return _has_secondary_cut; }
bool _has_secondary_cut
Definition: XFEM.h:327

◆ healMesh()

bool XFEM::healMesh ( )

Potentially heal the mesh by merging some of the pairs of partial elements cut by XFEM back into single elements if indicated by the cutting objects.

Returns
true if the mesh has been modified due to healing

Definition at line 924 of file XFEM.C.

Referenced by updateHeal().

925 {
926  bool mesh_changed = false;
927 
928  std::set<Node *> nodes_to_delete;
929  std::set<Node *> nodes_to_delete_displaced;
930  std::set<unsigned int> cutelems_to_delete;
931  unsigned int deleted_elem_count = 0;
932  std::vector<std::string> healed_geometric_cuts;
933 
934  for (unsigned int i = 0; i < _geometric_cuts.size(); ++i)
935  {
936  if (_geometric_cuts[i]->shouldHealMesh())
937  {
938  healed_geometric_cuts.push_back(_geometric_cuts[i]->name());
939  for (auto & it : _sibling_elems[_geometric_cuts[i]->getInterfaceID()])
940  {
941  Elem * elem1 = const_cast<Elem *>(it.first);
942  Elem * elem2 = const_cast<Elem *>(it.second);
943 
944  std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
945  _cut_elem_map.find(elem1->unique_id());
946  if (cemit != _cut_elem_map.end())
947  {
948  const XFEMCutElem * xfce = cemit->second;
949 
950  cutelems_to_delete.insert(elem1->unique_id());
951 
952  for (unsigned int in = 0; in < elem1->n_nodes(); ++in)
953  {
954  Node * e1node = elem1->node_ptr(in);
955  Node * e2node = elem2->node_ptr(in);
956  if (!xfce->isPointPhysical(*e1node) &&
957  e1node != e2node) // This would happen at the crack tip
958  {
959  elem1->set_node(in, e2node);
960  nodes_to_delete.insert(e1node);
961  }
962  else if (e1node != e2node)
963  nodes_to_delete.insert(e2node);
964  }
965  }
966  else
967  mooseError("Could not find XFEMCutElem for element to be kept in healing");
968 
969  // Store the material properties of the elements to be healed. So that if the element is
970  // immediately re-cut, we can restore the material properties (especially those stateful
971  // ones).
972  std::vector<const Elem *> healed_elems = {elem1, elem2};
973 
974  if (_geometric_cuts[i]->shouldHealMesh())
975  // If the parent element will not be re-cut, then all of its nodes must have the same
976  // CutSubdomainID. Therefore, just query the first node in this parent element to
977  // get its CutSubdomainID.
978  for (auto e : healed_elems)
979  if (elem1->processor_id() == _mesh->processor_id() &&
980  e->processor_id() == _mesh->processor_id())
981  {
982  storeMaterialPropertiesForElement(/*parent_elem = */ elem1, /*child_elem = */ e);
983  // In case the healed element is not re-cut, copy the corresponding material
984  // properties to the parent element now than later.
985  CutSubdomainID parent_gcsid =
986  _geometric_cuts[i]->getCutSubdomainID(elem1->node_ptr(0));
987  CutSubdomainID gcsid = _geom_cut_elems[e]._cut_subdomain_id;
988  if (parent_gcsid == gcsid)
990  }
991 
992  if (_displaced_mesh)
993  {
994  Elem * elem1_displaced = _displaced_mesh->elem_ptr(it.first->id());
995  Elem * elem2_displaced = _displaced_mesh->elem_ptr(it.second->id());
996 
997  std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
998  _cut_elem_map.find(elem1_displaced->unique_id());
999  if (cemit != _cut_elem_map.end())
1000  {
1001  const XFEMCutElem * xfce = cemit->second;
1002 
1003  for (unsigned int in = 0; in < elem1_displaced->n_nodes(); ++in)
1004  {
1005  Node * e1node_displaced = elem1_displaced->node_ptr(in);
1006  Node * e2node_displaced = elem2_displaced->node_ptr(in);
1007  if (!xfce->isPointPhysical(*elem1->node_ptr(in)) &&
1008  e1node_displaced != e2node_displaced)
1009  {
1010  elem1_displaced->set_node(in, e2node_displaced);
1011  nodes_to_delete_displaced.insert(e1node_displaced);
1012  }
1013  else if (e1node_displaced != e2node_displaced)
1014  nodes_to_delete_displaced.insert(e2node_displaced);
1015  }
1016  }
1017  else
1018  mooseError("Could not find XFEMCutElem for element to be kept in healing");
1019 
1020  elem2_displaced->nullify_neighbors();
1021  _displaced_mesh->get_boundary_info().remove(elem2_displaced);
1022  _displaced_mesh->delete_elem(elem2_displaced);
1023  }
1024 
1025  // remove the property storage of deleted element/side
1026  _material_data[0]->eraseProperty(elem2);
1027  _bnd_material_data[0]->eraseProperty(elem2);
1028 
1029  cutelems_to_delete.insert(elem2->unique_id());
1030  elem2->nullify_neighbors();
1031  _mesh->get_boundary_info().remove(elem2);
1032  unsigned int deleted_elem_id = elem2->id();
1033  _mesh->delete_elem(elem2);
1034  if (_debug_output_level > 1)
1035  {
1036  if (deleted_elem_count == 0)
1037  _console << "\n";
1038  _console << "XFEM healing deleted element: " << deleted_elem_id << std::endl;
1039  }
1040  ++deleted_elem_count;
1041  mesh_changed = true;
1042  }
1043  }
1044  }
1045 
1046  for (auto & sit : nodes_to_delete)
1047  {
1048  Node * node_to_delete = sit;
1049  dof_id_type deleted_node_id = node_to_delete->id();
1050  _mesh->get_boundary_info().remove(node_to_delete);
1051  _mesh->delete_node(node_to_delete);
1052  if (_debug_output_level > 1)
1053  _console << "XFEM healing deleted node: " << deleted_node_id << std::endl;
1054  }
1055 
1056  if (_displaced_mesh)
1057  {
1058  for (auto & sit : nodes_to_delete_displaced)
1059  {
1060  Node * node_to_delete_displaced = sit;
1061  _displaced_mesh->get_boundary_info().remove(node_to_delete_displaced);
1062  _displaced_mesh->delete_node(node_to_delete_displaced);
1063  }
1064  }
1065 
1066  for (auto & ced : cutelems_to_delete)
1067  if (_cut_elem_map.find(ced) != _cut_elem_map.end())
1068  {
1069  delete _cut_elem_map.find(ced)->second;
1070  _cut_elem_map.erase(ced);
1071  }
1072 
1073  for (unsigned int i = 0; i < _geometric_cuts.size(); ++i)
1074  if (_geometric_cuts[i]->shouldHealMesh())
1075  _sibling_elems[_geometric_cuts[i]->getInterfaceID()].clear();
1076 
1077  if (_displaced_mesh)
1078  {
1079  for (unsigned int i = 0; i < _geometric_cuts.size(); ++i)
1080  if (_geometric_cuts[i]->shouldHealMesh())
1081  _sibling_displaced_elems[_geometric_cuts[i]->getInterfaceID()].clear();
1082  }
1083 
1084  for (auto & ceh : _crack_tip_elems_to_be_healed)
1085  {
1086  _crack_tip_elems.erase(ceh);
1088  delete _cut_elem_map.find(ceh->unique_id())->second;
1089  _cut_elem_map.erase(ceh->unique_id());
1090  }
1091 
1092  if (!healed_geometric_cuts.empty() && _debug_output_level > 0)
1093  {
1094  _console << "\nXFEM mesh healing complete\n";
1095  _console << "Names of healed geometric cut objects: ";
1096  for (auto geomcut : healed_geometric_cuts)
1097  _console << geomcut << " ";
1098  _console << "\n";
1099  _console << "# deleted nodes: " << nodes_to_delete.size() << "\n";
1100  _console << "# deleted elements: " << deleted_elem_count << "\n";
1101  _console << std::flush;
1102  }
1103 
1104  return mesh_changed;
1105 }
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
Definition: XFEM.h:369
void storeMaterialPropertiesForElement(const Elem *parent_elem, const Elem *child_elem)
Helper function to store the material properties of a healed element.
Definition: XFEM.C:2210
std::vector< const GeometricCutUserObject * > _geometric_cuts
Definition: XFEM.h:334
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_elems
Definition: XFEM.h:339
void mooseError(Args &&... args)
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_displaced_elems
Definition: XFEM.h:340
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
std::set< const Elem * > _crack_tip_elems
Definition: XFEM.h:337
std::set< const Elem * > _crack_tip_elems_to_be_healed
Definition: XFEM.h:338
unsigned int CutSubdomainID
Definition: XFEMAppTypes.h:15
std::vector< MaterialData *> _bnd_material_data
void loadMaterialPropertiesForElement(const Elem *elem, const Elem *elem_from, std::unordered_map< const Elem *, Xfem::CutElemInfo > &cached_cei) const
Helper function to store the material properties of a healed element.
Definition: XFEM.C:2262
std::vector< MaterialData *> _material_data
const std::string name
Definition: Setup.h:21
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
Definition: XFEM.h:342
MeshBase * _mesh
MeshBase * _displaced_mesh
const ConsoleStream _console
uint8_t dof_id_type
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK...
Definition: XFEM.h:397
bool isPointPhysical(const Point &p) const
Definition: XFEMCutElem.C:193

◆ initCutIntersectionEdge()

bool XFEM::initCutIntersectionEdge ( Point  cut_origin,
RealVectorValue  cut_normal,
Point &  edge_p1,
Point &  edge_p2,
Real dist 
)

Definition at line 905 of file XFEM.C.

Referenced by correctCrackExtensionDirection(), and markCutEdgesByState().

907 {
908  dist = 0.0;
909  bool does_intersect = false;
910  Point origin2p1 = edge_p1 - cut_origin;
911  Real plane2p1 = cut_normal(0) * origin2p1(0) + cut_normal(1) * origin2p1(1);
912  Point origin2p2 = edge_p2 - cut_origin;
913  Real plane2p2 = cut_normal(0) * origin2p2(0) + cut_normal(1) * origin2p2(1);
914 
915  if (plane2p1 * plane2p2 < 0.0)
916  {
917  dist = -plane2p1 / (plane2p2 - plane2p1);
918  does_intersect = true;
919  }
920  return does_intersect;
921 }
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ initSolution()

void XFEM::initSolution ( const std::vector< std::shared_ptr< NonlinearSystemBase >> &  nl,
AuxiliarySystem aux 
)
overridevirtual

Implements XFEMInterface.

Definition at line 312 of file XFEM.C.

314 {
315  if (nls.size() != 1)
316  mooseError("XFEM does not currently support multiple nonlinear systems");
317 
318  nls[0]->serializeSolution();
319  aux.serializeSolution();
320  NumericVector<Number> & current_solution = *nls[0]->system().current_local_solution;
321  NumericVector<Number> & old_solution = nls[0]->solutionOld();
322  NumericVector<Number> & older_solution = nls[0]->solutionOlder();
323  NumericVector<Number> & current_aux_solution = *aux.system().current_local_solution;
324  NumericVector<Number> & old_aux_solution = aux.solutionOld();
325  NumericVector<Number> & older_aux_solution = aux.solutionOlder();
326 
327  setSolution(*nls[0], _cached_solution, current_solution, old_solution, older_solution);
328  setSolution(
329  aux, _cached_aux_solution, current_aux_solution, old_aux_solution, older_aux_solution);
330 
331  current_solution.close();
332  old_solution.close();
333  older_solution.close();
334  current_aux_solution.close();
335  old_aux_solution.close();
336  older_aux_solution.close();
337 
338  _cached_solution.clear();
339  _cached_aux_solution.clear();
340 }
void setSolution(SystemBase &sys, const std::map< unique_id_type, std::vector< Real >> &stored_solution, NumericVector< Number > &current_solution, NumericVector< Number > &old_solution, NumericVector< Number > &older_solution)
Set the solution for all locally-owned nodes/elements that have stored values.
Definition: XFEM.C:2061
void mooseError(Args &&... args)
NumericVector< Number > & solutionOlder()
std::map< unique_id_type, std::vector< Real > > _cached_aux_solution
Data structure to store the auxiliary solution for nodes/elements affected by XFEM For each node/elem...
Definition: XFEM.h:391
virtual void close()=0
std::unique_ptr< NumericVector< Number > > current_local_solution
std::map< unique_id_type, std::vector< Real > > _cached_solution
Data structure to store the nonlinear solution for nodes/elements affected by XFEM For each node/elem...
Definition: XFEM.h:382
virtual void serializeSolution()
virtual libMesh::System & system() override
NumericVector< Number > & solutionOld()

◆ isElemAtCrackTip()

bool XFEM::isElemAtCrackTip ( const Elem *  elem) const

Definition at line 1707 of file XFEM.C.

Referenced by markCutEdgesByGeometry(), and markCutEdgesByState().

1708 {
1709  return (_crack_tip_elems.find(elem) != _crack_tip_elems.end());
1710 }
std::set< const Elem * > _crack_tip_elems
Definition: XFEM.h:337

◆ isElemCut() [1/2]

bool XFEM::isElemCut ( const Elem *  elem,
XFEMCutElem *&  xfce 
) const

Definition at line 1713 of file XFEM.C.

Referenced by getXFEMFaceWeights(), getXFEMWeights(), and isElemCut().

1714 {
1715  const auto it = _cut_elem_map.find(elem->unique_id());
1716  if (it != _cut_elem_map.end())
1717  {
1718  xfce = it->second;
1719  const EFAElement * EFAelem = xfce->getEFAElement();
1720  if (EFAelem->isPartial()) // exclude the full crack tip elements
1721  return true;
1722  }
1723 
1724  xfce = nullptr;
1725  return false;
1726 }
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
virtual bool isPartial() const =0
virtual const EFAElement * getEFAElement() const =0

◆ isElemCut() [2/2]

bool XFEM::isElemCut ( const Elem *  elem) const

Definition at line 1729 of file XFEM.C.

1730 {
1731  XFEMCutElem * xfce;
1732  return isElemCut(elem, xfce);
1733 }
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition: XFEM.C:1713

◆ isPointInsidePhysicalDomain()

bool XFEM::isPointInsidePhysicalDomain ( const Elem *  elem,
const Point &  point 
) const

Return true if the point is inside the element physical domain Note: if this element is not cut, return true too.

Definition at line 1655 of file XFEM.C.

Referenced by pickFirstPhysicalNode().

1656 {
1657  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1658  it = _cut_elem_map.find(elem->unique_id());
1659  if (it != _cut_elem_map.end())
1660  {
1661  XFEMCutElem * xfce = it->second;
1662 
1663  if (xfce->isPointPhysical(point))
1664  return true;
1665  }
1666  else
1667  return true;
1668 
1669  return false;
1670 }
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
bool isPointPhysical(const Point &p) const
Definition: XFEMCutElem.C:193

◆ loadMaterialPropertiesForElement()

void XFEM::loadMaterialPropertiesForElement ( const Elem *  elem,
const Elem *  elem_from,
std::unordered_map< const Elem *, Xfem::CutElemInfo > &  cached_cei 
) const
private

Helper function to store the material properties of a healed element.

Parameters
elemThe cut element to restore material properties to.
elem_fromThe element to copy material properties from.
cached_ceiThe material properties cache to use.

Definition at line 2262 of file XFEM.C.

Referenced by cutMeshWithEFA(), and healMesh().

2266 {
2267  // Restore the element material properties
2268  mooseAssert(cached_cei.count(elem_from) > 0, "XFEM: Unable to find cached material properties.");
2269  Xfem::CutElemInfo & cei = cached_cei[elem_from];
2270 
2271  // Load element material properties from cached properties
2273  cei._elem_material_properties,
2274  _material_data[0]->getMaterialPropertyStorageForXFEM({}));
2275 
2276  // Check if any of the element side need material properties
2277  bool need_boundary_materials = false;
2278  for (unsigned int side = 0; side < elem->n_sides(); ++side)
2279  {
2280  std::vector<boundary_id_type> elem_boundary_ids;
2281  _mesh->get_boundary_info().boundary_ids(elem, side, elem_boundary_ids);
2282  for (auto bdid : elem_boundary_ids)
2284  need_boundary_materials = true;
2285  }
2286 
2287  // Load boundary material properties from cached properties
2288  if (need_boundary_materials)
2290  elem,
2291  cei._bnd_material_properties,
2292  _bnd_material_data[0]->getMaterialPropertyStorageForXFEM({}));
2293 }
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
FEProblemBase * _fe_problem
std::vector< MaterialData *> _bnd_material_data
std::vector< MaterialData *> _material_data
void loadMaterialPropertiesForElementHelper(const Elem *elem, const Xfem::CachedMaterialProperties &cached_props, MaterialPropertyStorage &storage) const
Load the material properties.
Definition: XFEM.C:2238
MeshBase * _mesh
Information about a cut element.
Definition: XFEM.h:57

◆ loadMaterialPropertiesForElementHelper()

void XFEM::loadMaterialPropertiesForElementHelper ( const Elem *  elem,
const Xfem::CachedMaterialProperties cached_props,
MaterialPropertyStorage storage 
) const
private

Load the material properties.

Parameters
props_deserializedThe material properties
props_serializedThe serialized material properties

This does very dirty things and writes back to MOOSE's stateful properties. It should not do this in the future.

Definition at line 2238 of file XFEM.C.

Referenced by loadMaterialPropertiesForElement().

2241 {
2242  if (!storage.hasStatefulProperties())
2243  return;
2244 
2245  for (const auto state : storage.statefulIndexRange())
2246  {
2247  const auto & serialized_props = cached_props[state - 1];
2248  for (const auto & [side, serialized_side_props] : serialized_props)
2249  {
2250  std::istringstream iss;
2251  iss.str(serialized_side_props);
2252  iss.clear();
2253 
2254  // This is very dirty. We should not write to MOOSE's stateful properties.
2255  // Please remove me :(
2256  dataLoad(iss, storage.setProps(elem, side, state), nullptr);
2257  }
2258  }
2259 }
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
bool hasStatefulProperties() const
void dataLoad(std::istream &stream, FaceCenteredMapFunctor< T, Map > &m, void *context)
libMesh::IntRange< unsigned int > statefulIndexRange() const

◆ markCutEdgesByGeometry()

bool XFEM::markCutEdgesByGeometry ( )

Definition at line 399 of file XFEM.C.

Referenced by markCuts().

400 {
401  bool marked_edges = false;
402  bool marked_nodes = false;
403 
404  for (const auto & gme : _geom_marked_elems_2d)
405  {
406  for (const auto & gmei : gme.second)
407  {
408  EFAElement2D * EFAElem = getEFAElem2D(gme.first);
409 
410  for (unsigned int i = 0; i < gmei._elem_cut_edges.size(); ++i) // mark element edges
411  {
412  if (!EFAElem->isEdgePhantom(
413  gmei._elem_cut_edges[i]._host_side_id)) // must not be phantom edge
414  {
415  _efa_mesh.addElemEdgeIntersection(gme.first->id(),
416  gmei._elem_cut_edges[i]._host_side_id,
417  gmei._elem_cut_edges[i]._distance);
418  marked_edges = true;
419  }
420  }
421 
422  for (unsigned int i = 0; i < gmei._elem_cut_nodes.size(); ++i) // mark element edges
423  {
424  _efa_mesh.addElemNodeIntersection(gme.first->id(), gmei._elem_cut_nodes[i]._host_id);
425  marked_nodes = true;
426  }
427 
428  for (unsigned int i = 0; i < gmei._frag_cut_edges.size();
429  ++i) // MUST DO THIS AFTER MARKING ELEMENT EDGES
430  {
431  if (!EFAElem->getFragment(0)->isSecondaryInteriorEdge(
432  gmei._frag_cut_edges[i]._host_side_id))
433  {
434  if (_efa_mesh.addFragEdgeIntersection(gme.first->id(),
435  gmei._frag_cut_edges[i]._host_side_id,
436  gmei._frag_cut_edges[i]._distance))
437  {
438  marked_edges = true;
439  if (!isElemAtCrackTip(gme.first))
440  _has_secondary_cut = true;
441  }
442  }
443  }
444  }
445  }
446 
447  return marked_edges || marked_nodes;
448 }
void addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
bool isSecondaryInteriorEdge(unsigned int edge_id) const
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
bool isEdgePhantom(unsigned int edge_id) const
bool _has_secondary_cut
Definition: XFEM.h:327
EFAFragment2D * getFragment(unsigned int frag_id) const
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo2D > > _geom_marked_elems_2d
Data structure for storing information about all 2D elements to be cut by geometry.
Definition: XFEM.h:351
bool isElemAtCrackTip(const Elem *elem) const
Definition: XFEM.C:1707
EFAElement2D * getEFAElem2D(const Elem *elem)
Get the EFAElement2D object for a specified libMesh element.
Definition: XFEM.C:1753

◆ markCutEdgesByState()

bool XFEM::markCutEdgesByState ( Real  time)

Definition at line 592 of file XFEM.C.

Referenced by markCuts().

593 {
594  bool marked_edges = false;
595  for (std::map<const Elem *, RealVectorValue>::iterator pmeit = _state_marked_elems.begin();
596  pmeit != _state_marked_elems.end();
597  ++pmeit)
598  {
599  const Elem * elem = pmeit->first;
600  RealVectorValue normal = pmeit->second;
601  EFAElement2D * CEMElem = getEFAElem2D(elem);
602 
603  Real volfrac_elem = getPhysicalVolumeFraction(elem);
604  if (volfrac_elem < 0.25)
605  continue;
606 
607  // continue if elem is already cut twice - IMPORTANT
608  if (CEMElem->isFinalCut())
609  continue;
610 
611  // find the first cut edge
612  unsigned int nsides = CEMElem->numEdges();
613  unsigned int orig_cut_side_id = std::numeric_limits<unsigned int>::max();
614  Real orig_cut_distance = -1.0;
615  EFANode * orig_node = nullptr;
616  EFAEdge * orig_edge = nullptr;
617 
618  // crack tip origin coordinates and direction
619  Point crack_tip_origin(0, 0, 0);
620  Point crack_tip_direction(0, 0, 0);
621 
622  if (isElemAtCrackTip(elem)) // crack tip element's crack intiation
623  {
624  orig_cut_side_id = CEMElem->getTipEdgeID();
625  if (orig_cut_side_id < nsides) // valid crack-tip edge found
626  {
627  orig_edge = CEMElem->getEdge(orig_cut_side_id);
628  orig_node = CEMElem->getTipEmbeddedNode();
629  }
630  else
631  mooseError("element ", elem->id(), " has no valid crack-tip edge");
632 
633  // obtain the crack tip origin coordinates and direction.
634  std::map<const Elem *, std::vector<Point>>::iterator ecodm =
636  if (ecodm != _elem_crack_origin_direction_map.end())
637  {
638  crack_tip_origin = (ecodm->second)[0];
639  crack_tip_direction = (ecodm->second)[1];
640  }
641  else
642  mooseError("element ", elem->id(), " cannot find its crack tip origin and direction.");
643  }
644  else
645  {
646  std::map<const Elem *, unsigned int>::iterator mit1;
647  mit1 = _state_marked_elem_sides.find(elem);
648  std::set<const Elem *>::iterator mit2;
649  mit2 = _state_marked_frags.find(elem);
650 
651  if (mit1 != _state_marked_elem_sides.end()) // specified boundary crack initiation
652  {
653  orig_cut_side_id = mit1->second;
654  if (!CEMElem->isEdgePhantom(orig_cut_side_id) &&
655  !CEMElem->getEdge(orig_cut_side_id)->hasIntersection())
656  {
657  orig_cut_distance = 0.5;
658  _efa_mesh.addElemEdgeIntersection(elem->id(), orig_cut_side_id, orig_cut_distance);
659  orig_edge = CEMElem->getEdge(orig_cut_side_id);
660  orig_node = orig_edge->getEmbeddedNode(0);
661  // get a virtual crack tip direction
662  Point elem_center(0.0, 0.0, 0.0);
663  Point edge_center;
664  for (unsigned int i = 0; i < nsides; ++i)
665  {
666  elem_center += getEFANodeCoords(CEMElem->getEdge(i)->getNode(0), CEMElem, elem);
667  elem_center += getEFANodeCoords(CEMElem->getEdge(i)->getNode(1), CEMElem, elem);
668  }
669  elem_center /= nsides * 2.0;
670  edge_center = getEFANodeCoords(orig_edge->getNode(0), CEMElem, elem) +
671  getEFANodeCoords(orig_edge->getNode(1), CEMElem, elem);
672  edge_center /= 2.0;
673  crack_tip_origin = edge_center;
674  crack_tip_direction = elem_center - edge_center;
675  crack_tip_direction /= pow(crack_tip_direction.norm_sq(), 0.5);
676  }
677  else
678  continue; // skip this elem if specified boundary edge is phantom
679  }
680  else if (mit2 != _state_marked_frags.end()) // cut-surface secondary crack initiation
681  {
682  if (CEMElem->numFragments() != 1)
683  mooseError("element ",
684  elem->id(),
685  " flagged for a secondary crack, but has ",
686  CEMElem->numFragments(),
687  " fragments");
688  std::vector<unsigned int> interior_edge_id = CEMElem->getFragment(0)->getInteriorEdgeID();
689  if (interior_edge_id.size() == 1)
690  orig_cut_side_id = interior_edge_id[0];
691  else
692  continue; // skip this elem if more than one interior edges found (i.e. elem's been cut
693  // twice)
694  orig_cut_distance = 0.5;
695  _efa_mesh.addFragEdgeIntersection(elem->id(), orig_cut_side_id, orig_cut_distance);
696  orig_edge = CEMElem->getFragmentEdge(0, orig_cut_side_id);
697  orig_node = orig_edge->getEmbeddedNode(0); // must be an interior embedded node
698  Point elem_center(0.0, 0.0, 0.0);
699  Point edge_center;
700  unsigned int nsides_frag = CEMElem->getFragment(0)->numEdges();
701  for (unsigned int i = 0; i < nsides_frag; ++i)
702  {
703  elem_center +=
704  getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(0), CEMElem, elem);
705  elem_center +=
706  getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(1), CEMElem, elem);
707  }
708  elem_center /= nsides_frag * 2.0;
709  edge_center = getEFANodeCoords(orig_edge->getNode(0), CEMElem, elem) +
710  getEFANodeCoords(orig_edge->getNode(1), CEMElem, elem);
711  edge_center /= 2.0;
712  crack_tip_origin = edge_center;
713  crack_tip_direction = elem_center - edge_center;
714  crack_tip_direction /= pow(crack_tip_direction.norm_sq(), 0.5);
715  }
716  else
717  mooseError("element ",
718  elem->id(),
719  " flagged for state-based growth, but has no edge intersections");
720  }
721 
722  Point cut_origin(0.0, 0.0, 0.0);
723  if (orig_node)
724  cut_origin = getEFANodeCoords(orig_node, CEMElem, elem); // cutting plane origin's coords
725  else
726  mooseError("element ", elem->id(), " does not have valid orig_node");
727 
728  // loop through element edges to add possible second cut points
729  std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
730  Point edge1(0.0, 0.0, 0.0);
731  Point edge2(0.0, 0.0, 0.0);
732  Point cut_edge_point(0.0, 0.0, 0.0);
733  bool find_compatible_direction = false;
734  unsigned int edge_id_keep = 0;
735  Real distance_keep = 0.0;
736  Point normal_keep(0.0, 0.0, 0.0);
737  Real distance = 0.0;
738  bool edge_cut = false;
739 
740  for (unsigned int i = 0; i < nsides; ++i)
741  {
742  if (!orig_edge->isPartialOverlap(*CEMElem->getEdge(i)))
743  {
744  edge_ends[0] = getEFANodeCoords(CEMElem->getEdge(i)->getNode(0), CEMElem, elem);
745  edge_ends[1] = getEFANodeCoords(CEMElem->getEdge(i)->getNode(1), CEMElem, elem);
747  crack_tip_origin, normal, edge_ends[0], edge_ends[1], distance) &&
748  (!CEMElem->isEdgePhantom(i))))
749  {
750  cut_edge_point = distance * edge_ends[1] + (1.0 - distance) * edge_ends[0];
751  distance_keep = distance;
752  edge_id_keep = i;
753  normal_keep = normal;
754  edge_cut = true;
755  break;
756  }
757  }
758  }
759 
760  Point between_two_cuts = (cut_edge_point - crack_tip_origin);
761  between_two_cuts /= pow(between_two_cuts.norm_sq(), 0.5);
762  Real angle_between_two_cuts = between_two_cuts * crack_tip_direction;
763 
764  if (angle_between_two_cuts > std::cos(45.0 / 180.0 * 3.14159)) // original cut direction is good
765  find_compatible_direction = true;
766 
767  if (!find_compatible_direction && edge_cut)
769  CEMElem,
770  orig_edge,
771  normal,
772  crack_tip_origin,
773  crack_tip_direction,
774  distance_keep,
775  edge_id_keep,
776  normal_keep);
777 
778  if (edge_cut)
779  {
781  _efa_mesh.addElemEdgeIntersection(elem->id(), edge_id_keep, distance_keep);
782  else
783  {
784  Point growth_direction(0.0, 0.0, 0.0);
785 
786  growth_direction(0) = -normal_keep(1);
787  growth_direction(1) = normal_keep(0);
788 
789  if (growth_direction * crack_tip_direction < 1.0e-10)
790  growth_direction *= (-1.0);
791 
792  Real x0 = crack_tip_origin(0);
793  Real y0 = crack_tip_origin(1);
794  Real x1 = x0 + _crack_growth_increment * growth_direction(0);
795  Real y1 = y0 + _crack_growth_increment * growth_direction(1);
796 
797  XFEMCrackGrowthIncrement2DCut geometric_cut(x0, y0, x1, y1, time * 0.9, time * 0.9);
798 
799  for (const auto & elem : _mesh->element_ptr_range())
800  {
801  std::vector<CutEdgeForCrackGrowthIncr> elem_cut_edges;
802  EFAElement2D * CEMElem = getEFAElem2D(elem);
803 
804  // continue if elem has been already cut twice - IMPORTANT
805  if (CEMElem->isFinalCut())
806  continue;
807 
808  // mark cut edges for the element and its fragment
809  geometric_cut.cutElementByCrackGrowthIncrement(elem, elem_cut_edges, time);
810 
811  for (unsigned int i = 0; i < elem_cut_edges.size(); ++i) // mark element edges
812  {
813  if (!CEMElem->isEdgePhantom(
814  elem_cut_edges[i]._host_side_id)) // must not be phantom edge
815  {
817  elem->id(), elem_cut_edges[i]._host_side_id, elem_cut_edges[i]._distance);
818  }
819  }
820  }
821  }
822  }
823  // loop though framgent boundary edges to add possible second cut points
824  // N.B. must do this after marking element edges
825  if (CEMElem->numFragments() > 0 && !edge_cut)
826  {
827  for (unsigned int i = 0; i < CEMElem->getFragment(0)->numEdges(); ++i)
828  {
829  if (!orig_edge->isPartialOverlap(*CEMElem->getFragmentEdge(0, i)))
830  {
831  edge_ends[0] =
832  getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(0), CEMElem, elem);
833  edge_ends[1] =
834  getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(1), CEMElem, elem);
836  crack_tip_origin, normal, edge_ends[0], edge_ends[1], distance) &&
837  (!CEMElem->getFragment(0)->isSecondaryInteriorEdge(i)))
838  {
839  if (_efa_mesh.addFragEdgeIntersection(elem->id(), edge_id_keep, distance_keep))
840  if (!isElemAtCrackTip(elem))
841  _has_secondary_cut = true;
842  break;
843  }
844  }
845  }
846  }
847 
848  marked_edges = true;
849 
850  } // loop over all state_marked_elems
851 
852  return marked_edges;
853 }
void correctCrackExtensionDirection(const Elem *elem, EFAElement2D *CEMElem, EFAEdge *orig_edge, Point normal, Point crack_tip_origin, Point crack_tip_direction, Real &distance_keep, unsigned int &edge_id_keep, Point &normal_keep)
Definition: XFEM.C:451
bool _use_crack_growth_increment
Definition: XFEM.h:331
EFANode * getEmbeddedNode(unsigned int index) const
Definition: EFAEdge.C:332
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
Real _crack_growth_increment
Definition: XFEM.h:332
bool isSecondaryInteriorEdge(unsigned int edge_id) const
void mooseError(Args &&... args)
bool isPartialOverlap(const EFAEdge &other) const
Definition: EFAEdge.C:59
PetscInt nsides
unsigned int getTipEdgeID() const
unsigned int numEdges() const
EFAEdge * getEdge(unsigned int edge_id) const
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
bool hasIntersection() const
Definition: EFAEdge.C:200
std::vector< unsigned int > getInteriorEdgeID() const
unsigned int numEdges() const
bool isEdgePhantom(unsigned int edge_id) const
virtual unsigned int numFragments() const
Definition: EFAElement2D.C:207
Real distance(const Point &p)
bool _has_secondary_cut
Definition: XFEM.h:327
bool initCutIntersectionEdge(Point cut_origin, RealVectorValue cut_normal, Point &edge_p1, Point &edge_p2, Real &dist)
Definition: XFEM.C:905
EFAFragment2D * getFragment(unsigned int frag_id) const
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
virtual bool isFinalCut() const
Definition: EFAElement2D.C:796
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
Definition: XFEM.h:342
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
std::set< const Elem * > _state_marked_frags
Definition: XFEM.h:347
EFANode * getTipEmbeddedNode() const
MeshBase * _mesh
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool isElemAtCrackTip(const Elem *elem) const
Definition: XFEM.C:1707
Real getPhysicalVolumeFraction(const Elem *elem) const
Get the volume fraction of an element that is physical.
Definition: XFEM.C:1635
std::map< const Elem *, unsigned int > _state_marked_elem_sides
Definition: XFEM.h:348
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:181
Point getEFANodeCoords(EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
Definition: XFEM.C:1603
std::map< const Elem *, RealVectorValue > _state_marked_elems
Definition: XFEM.h:346
EFAElement2D * getEFAElem2D(const Elem *elem)
Get the EFAElement2D object for a specified libMesh element.
Definition: XFEM.C:1753
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const

◆ markCutFacesByGeometry()

bool XFEM::markCutFacesByGeometry ( )

Definition at line 856 of file XFEM.C.

Referenced by markCuts().

857 {
858  bool marked_faces = false;
859 
860  for (const auto & gme : _geom_marked_elems_3d)
861  {
862  for (const auto & gmei : gme.second)
863  {
864  EFAElement3D * EFAElem = getEFAElem3D(gme.first);
865 
866  for (unsigned int i = 0; i < gmei._elem_cut_faces.size(); ++i) // mark element faces
867  {
868  if (!EFAElem->isFacePhantom(gmei._elem_cut_faces[i]._face_id)) // must not be phantom face
869  {
870  _efa_mesh.addElemFaceIntersection(gme.first->id(),
871  gmei._elem_cut_faces[i]._face_id,
872  gmei._elem_cut_faces[i]._face_edge,
873  gmei._elem_cut_faces[i]._position);
874  marked_faces = true;
875  }
876  }
877 
878  for (unsigned int i = 0; i < gmei._frag_cut_faces.size();
879  ++i) // MUST DO THIS AFTER MARKING ELEMENT EDGES
880  {
881  if (!EFAElem->getFragment(0)->isThirdInteriorFace(gmei._frag_cut_faces[i]._face_id))
882  {
883  _efa_mesh.addFragFaceIntersection(gme.first->id(),
884  gmei._frag_cut_faces[i]._face_id,
885  gmei._frag_cut_faces[i]._face_edge,
886  gmei._frag_cut_faces[i]._position);
887  marked_faces = true;
888  }
889  }
890  }
891  }
892 
893  return marked_faces;
894 }
EFAFragment3D * getFragment(unsigned int frag_id) const
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo3D > > _geom_marked_elems_3d
Data structure for storing information about all 3D elements to be cut by geometry.
Definition: XFEM.h:354
bool isFacePhantom(unsigned int face_id) const
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
void addElemFaceIntersection(unsigned int elemid, unsigned int faceid, const std::vector< unsigned int > &edgeid, const std::vector< double > &position)
bool isThirdInteriorFace(unsigned int face_id) const
void addFragFaceIntersection(unsigned int ElemID, unsigned int FragFaceID, const std::vector< unsigned int > &FragFaceEdgeID, const std::vector< double > &position)
EFAElement3D * getEFAElem3D(const Elem *elem)
Get the EFAElement3D object for a specified libMesh element.
Definition: XFEM.C:1765

◆ markCutFacesByState()

bool XFEM::markCutFacesByState ( )

Definition at line 897 of file XFEM.C.

Referenced by markCuts().

898 {
899  bool marked_faces = false;
900  // TODO: need to finish this for 3D problems
901  return marked_faces;
902 }

◆ markCuts()

bool XFEM::markCuts ( Real  time)

Definition at line 382 of file XFEM.C.

Referenced by update().

383 {
384  bool marked_sides = false;
385  if (_mesh->mesh_dimension() == 2)
386  {
387  marked_sides = markCutEdgesByGeometry();
388  marked_sides |= markCutEdgesByState(time);
389  }
390  else if (_mesh->mesh_dimension() == 3)
391  {
392  marked_sides = markCutFacesByGeometry();
393  marked_sides |= markCutFacesByState();
394  }
395  return marked_sides;
396 }
bool markCutEdgesByState(Real time)
Definition: XFEM.C:592
bool markCutEdgesByGeometry()
Definition: XFEM.C:399
MeshBase * _mesh
bool markCutFacesByGeometry()
Definition: XFEM.C:856
bool markCutFacesByState()
Definition: XFEM.C:897

◆ pickFirstPhysicalNode()

const Node * XFEM::pickFirstPhysicalNode ( const Elem *  e,
const Elem *  e0 
) const
private

Return the first node in the provided element that is found to be in the physical domain.

Parameters
eConstant pointer to the child element
e0Constant pointer to the parent element whose nodes will be querried
Returns
A constant pointer to the node

Definition at line 2309 of file XFEM.C.

Referenced by getCutSubdomainID().

2310 {
2311  for (auto i : e0->node_index_range())
2312  if (isPointInsidePhysicalDomain(e, e0->node_ref(i)))
2313  return e0->node_ptr(i);
2314  mooseError("cannot find a physical node in the current element");
2315  return nullptr;
2316 }
void mooseError(Args &&... args)
bool isPointInsidePhysicalDomain(const Elem *elem, const Point &point) const
Return true if the point is inside the element physical domain Note: if this element is not cut...
Definition: XFEM.C:1655

◆ setCrackGrowthMethod()

void XFEM::setCrackGrowthMethod ( bool  use_crack_growth_increment,
Real  crack_growth_increment 
)

Definition at line 1837 of file XFEM.C.

1838 {
1839  _use_crack_growth_increment = use_crack_growth_increment;
1840  _crack_growth_increment = crack_growth_increment;
1841 }
bool _use_crack_growth_increment
Definition: XFEM.h:331
Real _crack_growth_increment
Definition: XFEM.h:332

◆ setDebugOutputLevel()

void XFEM::setDebugOutputLevel ( unsigned int  debug_output_level)

Controls amount of debugging information output.

Parameters
debug_output_levelHow much information to output (see description of _debug_output_level)

Definition at line 1844 of file XFEM.C.

1845 {
1846  _debug_output_level = debug_output_level;
1847 }
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
Definition: XFEM.h:369

◆ setMinWeightMultiplier()

void XFEM::setMinWeightMultiplier ( Real  min_weight_multiplier)

Controls the minimum average weight multiplier for each element.

Parameters
min_weight_multiplierThe minimum average weight multiplier applied by XFEM to the standard quadrature weights

Definition at line 1850 of file XFEM.C.

1851 {
1852  _min_weight_multiplier = min_weight_multiplier;
1853 }
Real _min_weight_multiplier
The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partia...
Definition: XFEM.h:373

◆ setSolution()

void XFEM::setSolution ( SystemBase sys,
const std::map< unique_id_type, std::vector< Real >> &  stored_solution,
NumericVector< Number > &  current_solution,
NumericVector< Number > &  old_solution,
NumericVector< Number > &  older_solution 
)
private

Set the solution for all locally-owned nodes/elements that have stored values.

Parameters
sysSystem for which the solution is set
stored_solutionData structure that the stored solution is obtained from
current_solutionCurrent solution vector that will be set
old_solutionOld solution vector that will be set
older_solutionOlder solution vector that will be set

Definition at line 2061 of file XFEM.C.

Referenced by initSolution().

2066 {
2067  for (auto & node : _mesh->local_node_ptr_range())
2068  {
2069  auto mit = stored_solution.find(node->unique_id());
2070  if (mit != stored_solution.end())
2071  {
2072  const std::vector<Real> & stored_node_solution = mit->second;
2073  std::vector<dof_id_type> stored_solution_dofs = getNodeSolutionDofs(node, sys);
2074  setSolutionForDOFs(stored_node_solution,
2075  stored_solution_dofs,
2076  current_solution,
2077  old_solution,
2078  older_solution);
2079  }
2080  }
2081 
2082  for (auto & elem : as_range(_mesh->local_elements_begin(), _mesh->local_elements_end()))
2083  {
2084  auto mit = stored_solution.find(elem->unique_id());
2085  if (mit != stored_solution.end())
2086  {
2087  const std::vector<Real> & stored_elem_solution = mit->second;
2088  std::vector<dof_id_type> stored_solution_dofs = getElementSolutionDofs(elem, sys);
2089  setSolutionForDOFs(stored_elem_solution,
2090  stored_solution_dofs,
2091  current_solution,
2092  old_solution,
2093  older_solution);
2094  }
2095  }
2096 }
void setSolutionForDOFs(const std::vector< Real > &stored_solution, const std::vector< dof_id_type > &stored_solution_dofs, NumericVector< Number > &current_solution, NumericVector< Number > &old_solution, NumericVector< Number > &older_solution)
Set the solution for a set of DOFs.
Definition: XFEM.C:2099
std::vector< dof_id_type > getNodeSolutionDofs(const Node *node, SystemBase &sys) const
Get a vector of the dof indices for all components of all variables associated with a node...
Definition: XFEM.C:2148
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
MeshBase * _mesh
std::vector< dof_id_type > getElementSolutionDofs(const Elem *elem, SystemBase &sys) const
Get a vector of the dof indices for all components of all variables associated with an element...
Definition: XFEM.C:2122

◆ setSolutionForDOFs()

void XFEM::setSolutionForDOFs ( const std::vector< Real > &  stored_solution,
const std::vector< dof_id_type > &  stored_solution_dofs,
NumericVector< Number > &  current_solution,
NumericVector< Number > &  old_solution,
NumericVector< Number > &  older_solution 
)
private

Set the solution for a set of DOFs.

Parameters
stored_solutionStored solution values to set the solution to
stored_solution_dofsDof indices for the entries in stored_solution
current_solutionCurrent solution vector that will be set
old_solutionOld solution vector that will be set
older_solutionOlder solution vector that will be set

Definition at line 2099 of file XFEM.C.

Referenced by setSolution().

2104 {
2105  // Solution vector is stored first for current, then old and older solutions.
2106  // These are the offsets to the beginning of the old and older solutions in the vector.
2107  const auto old_solution_offset = stored_solution_dofs.size();
2108  const auto older_solution_offset = old_solution_offset * 2;
2109 
2110  for (std::size_t i = 0; i < stored_solution_dofs.size(); ++i)
2111  {
2112  current_solution.set(stored_solution_dofs[i], stored_solution[i]);
2113  if (_fe_problem->isTransient())
2114  {
2115  old_solution.set(stored_solution_dofs[i], stored_solution[old_solution_offset + i]);
2116  older_solution.set(stored_solution_dofs[i], stored_solution[older_solution_offset + i]);
2117  }
2118  }
2119 }
FEProblemBase * _fe_problem
virtual void set(const numeric_index_type i, const Number value)=0
virtual bool isTransient() const override

◆ setXFEMQRule()

void XFEM::setXFEMQRule ( std::string &  xfem_qrule)

Definition at line 1826 of file XFEM.C.

1827 {
1828  if (xfem_qrule == "volfrac")
1830  else if (xfem_qrule == "moment_fitting")
1832  else if (xfem_qrule == "direct")
1834 }
Xfem::XFEM_QRULE _XFEM_qrule
Definition: XFEM.h:329

◆ storeCrackTipOriginAndDirection()

void XFEM::storeCrackTipOriginAndDirection ( )

Definition at line 187 of file XFEM.C.

Referenced by update().

188 {
190  std::set<EFAElement *> CrackTipElements = _efa_mesh.getCrackTipElements();
191  std::set<EFAElement *>::iterator sit;
192  for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
193  {
194  if (_mesh->mesh_dimension() == 2)
195  {
196  EFAElement2D * CEMElem = dynamic_cast<EFAElement2D *>(*sit);
197  EFANode * tip_node = CEMElem->getTipEmbeddedNode();
198  unsigned int cts_id = CEMElem->getCrackTipSplitElementID();
199 
200  Point origin(0, 0, 0);
201  Point direction(0, 0, 0);
202 
203  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
204  it = _cut_elem_map.find(_mesh->elem_ptr(cts_id)->unique_id());
205  if (it != _cut_elem_map.end())
206  {
207  const XFEMCutElem * xfce = it->second;
208  const EFAElement * EFAelem = xfce->getEFAElement();
209  if (EFAelem->isPartial()) // exclude the full crack tip elements
210  {
211  xfce->getCrackTipOriginAndDirection(tip_node->id(), origin, direction);
212  }
213  }
214 
215  std::vector<Point> tip_data;
216  tip_data.push_back(origin);
217  tip_data.push_back(direction);
218  const Elem * elem = _mesh->elem_ptr((*sit)->id());
220  std::pair<const Elem *, std::vector<Point>>(elem, tip_data));
221  }
222  }
223 }
unsigned int getCrackTipSplitElementID() const
Definition: EFAElement2D.C:599
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
Definition: XFEM.h:336
virtual bool isPartial() const =0
ElementFragmentAlgorithm _efa_mesh
Definition: XFEM.h:362
virtual const EFAElement * getEFAElement() const =0
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
Definition: XFEM.h:342
EFANode * getTipEmbeddedNode() const
MeshBase * _mesh
const std::set< EFAElement * > & getCrackTipElements()
unsigned int id() const
Definition: EFANode.C:36
virtual void getCrackTipOriginAndDirection(unsigned tip_id, Point &origin, Point &direction) const =0

◆ storeMaterialPropertiesForElement()

void XFEM::storeMaterialPropertiesForElement ( const Elem *  parent_elem,
const Elem *  child_elem 
)
private

Helper function to store the material properties of a healed element.

Parameters
parent_elemThe parent element
elem1The first child element
elem2The second child element

Definition at line 2210 of file XFEM.C.

Referenced by healMesh().

2211 {
2212  // Set the parent element so that it is consistent post-healing
2213  _geom_cut_elems[child_elem]._parent_elem = parent_elem;
2214 
2215  // Locally store the element material properties
2217  _material_data[0]->getMaterialPropertyStorageForXFEM({}));
2218 
2219  // Locally store the boundary material properties
2220  // First check if any of the side need material properties
2221  bool need_boundary_materials = false;
2222  for (unsigned int side = 0; side < child_elem->n_sides(); ++side)
2223  {
2224  std::vector<boundary_id_type> elem_boundary_ids;
2225  _mesh->get_boundary_info().boundary_ids(child_elem, side, elem_boundary_ids);
2226  for (auto bdid : elem_boundary_ids)
2228  need_boundary_materials = true;
2229  }
2230 
2231  // If boundary material properties are needed for this element, then store them.
2232  if (need_boundary_materials)
2234  child_elem, _bnd_material_data[0]->getMaterialPropertyStorageForXFEM({}));
2235 }
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
FEProblemBase * _fe_problem
std::vector< MaterialData *> _bnd_material_data
std::vector< MaterialData *> _material_data
void storeMaterialPropertiesForElementHelper(const Elem *elem, MaterialPropertyStorage &storage)
Definition: XFEM.C:2192
MeshBase * _mesh
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK...
Definition: XFEM.h:397

◆ storeMaterialPropertiesForElementHelper()

void XFEM::storeMaterialPropertiesForElementHelper ( const Elem *  elem,
MaterialPropertyStorage storage 
)
private

Definition at line 2192 of file XFEM.C.

Referenced by storeMaterialPropertiesForElement().

2193 {
2194  for (const auto state : storage.statefulIndexRange())
2195  {
2196  const auto & elem_props = storage.props(state).at(elem);
2197  auto & serialized_props = _geom_cut_elems[elem]._elem_material_properties[state - 1];
2198  serialized_props.clear();
2199  for (const auto & side_props_pair : elem_props)
2200  {
2201  const auto side = side_props_pair.first;
2202  std::ostringstream oss;
2203  dataStore(oss, storage.setProps(elem, side, state), nullptr);
2204  serialized_props[side].assign(oss.str());
2205  }
2206  }
2207 }
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
void dataStore(std::ostream &stream, FaceCenteredMapFunctor< T, Map > &m, void *context)
const PropsType & props(const unsigned int state=0) const
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK...
Definition: XFEM.h:397
libMesh::IntRange< unsigned int > statefulIndexRange() const

◆ storeSolutionForElement()

void XFEM::storeSolutionForElement ( const Elem *  elem_to_store_to,
const Elem *  elem_to_store_from,
SystemBase sys,
std::map< unique_id_type, std::vector< Real >> &  stored_solution,
const NumericVector< Number > &  current_solution,
const NumericVector< Number > &  old_solution,
const NumericVector< Number > &  older_solution 
)
private

Store the solution in stored_solution for a given element.

Parameters
elem_to_store_toElement for which the solution will be stored
elem_to_store_fromElement from which the solution to be stored is obtained
sysSystem from which the solution is stored
stored_solutionData structure that the stored solution is saved to
current_solutionCurrent solution vector that the solution is obtained from
old_solutionOld solution vector that the solution is obtained from
older_solutionOlder solution vector that the solution is obtained from

Definition at line 2027 of file XFEM.C.

Referenced by cutMeshWithEFA().

2034 {
2035  std::vector<dof_id_type> stored_solution_dofs = getElementSolutionDofs(elem_to_store_from, sys);
2036  std::vector<Real> stored_solution_scratch;
2037  // Size for current solution, as well as for old, and older solution only for transient case
2038  std::size_t stored_solution_size =
2039  (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
2040  stored_solution_scratch.reserve(stored_solution_size);
2041 
2042  // Store in the order defined in stored_solution_dofs first for the current, then for old and
2043  // older if applicable
2044  for (auto dof : stored_solution_dofs)
2045  stored_solution_scratch.push_back(current_solution(dof));
2046 
2047  if (_fe_problem->isTransient())
2048  {
2049  for (auto dof : stored_solution_dofs)
2050  stored_solution_scratch.push_back(old_solution(dof));
2051 
2052  for (auto dof : stored_solution_dofs)
2053  stored_solution_scratch.push_back(older_solution(dof));
2054  }
2055 
2056  if (stored_solution_scratch.size() > 0)
2057  stored_solution[elem_to_store_to->unique_id()] = stored_solution_scratch;
2058 }
FEProblemBase * _fe_problem
std::vector< dof_id_type > getElementSolutionDofs(const Elem *elem, SystemBase &sys) const
Get a vector of the dof indices for all components of all variables associated with an element...
Definition: XFEM.C:2122
virtual bool isTransient() const override

◆ storeSolutionForNode()

void XFEM::storeSolutionForNode ( const Node *  node_to_store_to,
const Node *  node_to_store_from,
SystemBase sys,
std::map< unique_id_type, std::vector< Real >> &  stored_solution,
const NumericVector< Number > &  current_solution,
const NumericVector< Number > &  old_solution,
const NumericVector< Number > &  older_solution 
)
private

Store the solution in stored_solution for a given node.

Parameters
node_to_store_toNode for which the solution will be stored
node_to_store_fromNode from which the solution to be stored is obtained
sysSystem from which the solution is stored
stored_solutionData structure that the stored solution is saved to
current_solutionCurrent solution vector that the solution is obtained from
old_solutionOld solution vector that the solution is obtained from
older_solutionOlder solution vector that the solution is obtained from

Definition at line 1993 of file XFEM.C.

Referenced by cutMeshWithEFA().

2000 {
2001  std::vector<dof_id_type> stored_solution_dofs = getNodeSolutionDofs(node_to_store_from, sys);
2002  std::vector<Real> stored_solution_scratch;
2003  // Size for current solution, as well as for old, and older solution only for transient case
2004  std::size_t stored_solution_size =
2005  (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
2006  stored_solution_scratch.reserve(stored_solution_size);
2007 
2008  // Store in the order defined in stored_solution_dofs first for the current, then for old and
2009  // older if applicable
2010  for (auto dof : stored_solution_dofs)
2011  stored_solution_scratch.push_back(current_solution(dof));
2012 
2013  if (_fe_problem->isTransient())
2014  {
2015  for (auto dof : stored_solution_dofs)
2016  stored_solution_scratch.push_back(old_solution(dof));
2017 
2018  for (auto dof : stored_solution_dofs)
2019  stored_solution_scratch.push_back(older_solution(dof));
2020  }
2021 
2022  if (stored_solution_scratch.size() > 0)
2023  stored_solution[node_to_store_to->unique_id()] = stored_solution_scratch;
2024 }
std::vector< dof_id_type > getNodeSolutionDofs(const Node *node, SystemBase &sys) const
Get a vector of the dof indices for all components of all variables associated with a node...
Definition: XFEM.C:2148
FEProblemBase * _fe_problem
virtual bool isTransient() const override

◆ update()

bool XFEM::update ( Real  time,
const std::vector< std::shared_ptr< NonlinearSystemBase >> &  nl,
AuxiliarySystem aux 
)
overridevirtual

Implements XFEMInterface.

Definition at line 263 of file XFEM.C.

266 {
268  mooseError("Use of XFEM with distributed mesh is not yet supported");
269 
270  for (const auto & elem : _mesh->active_element_ptr_range())
271  if (elem->level() > 0)
272  mooseError("XFEM does not currently support mesh adaptivity or adaptively refined meshes");
273 
274  bool mesh_changed = false;
275 
276  buildEFAMesh();
277 
279 
281 
282  if (markCuts(time))
283  mesh_changed = cutMeshWithEFA(nl, aux);
284 
285  if (mesh_changed)
286  {
287  buildEFAMesh();
289  }
290 
291  if (mesh_changed)
292  {
293  _mesh->allow_renumbering(false);
294  _mesh->skip_partitioning(true);
295  _mesh->prepare_for_use();
296 
297  if (_displaced_mesh)
298  {
299  _displaced_mesh->allow_renumbering(false);
300  _displaced_mesh->skip_partitioning(true);
301  _displaced_mesh->prepare_for_use();
302  }
303  }
304 
307 
308  return mesh_changed;
309 }
void mooseError(Args &&... args)
const ExecFlagType EXEC_XFEM_MARK
Exec flag used to execute MooseObjects while elements are being marked for cutting by XFEM...
bool cutMeshWithEFA(const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux)
Definition: XFEM.C:1108
void clearGeomMarkedElems()
Clear out the list of elements to be marked for cutting.
Definition: XFEM.C:180
FEProblemBase * _fe_problem
virtual void execute(const ExecFlagType &exec_type)
void storeCrackTipOriginAndDirection()
Definition: XFEM.C:187
bool markCuts(Real time)
Definition: XFEM.C:382
MeshBase * _mesh
MooseMesh * _moose_mesh
MeshBase * _displaced_mesh
void clearStateMarkedElems()
Definition: XFEM.C:152
void buildEFAMesh()
Definition: XFEM.C:343
virtual bool isDistributedMesh() const

◆ updateHeal()

bool XFEM::updateHeal ( )
overridevirtual

Implements XFEMInterface.

Definition at line 226 of file XFEM.C.

227 {
228  bool mesh_changed = false;
229 
230  mesh_changed = healMesh();
231 
232  if (mesh_changed)
233  buildEFAMesh();
234 
235  if (mesh_changed)
236  {
237  _mesh->update_parallel_id_counts();
238  MeshCommunication().make_elems_parallel_consistent(*_mesh);
239  MeshCommunication().make_nodes_parallel_consistent(*_mesh);
240  // _mesh->find_neighbors();
241  // _mesh->contract();
242  _mesh->allow_renumbering(false);
243  _mesh->skip_partitioning(true);
244  _mesh->prepare_for_use();
245 
246  if (_displaced_mesh)
247  {
248  _displaced_mesh->update_parallel_id_counts();
249  MeshCommunication().make_elems_parallel_consistent(*_displaced_mesh);
250  MeshCommunication().make_nodes_parallel_consistent(*_displaced_mesh);
251  _displaced_mesh->allow_renumbering(false);
252  _displaced_mesh->skip_partitioning(true);
253  _displaced_mesh->prepare_for_use();
254  }
255  }
256 
257  _geom_marker_id_elems.clear();
258 
259  return mesh_changed;
260 }
bool healMesh()
Potentially heal the mesh by merging some of the pairs of partial elements cut by XFEM back into sing...
Definition: XFEM.C:924
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
Definition: XFEM.h:357
MeshBase * _mesh
MeshBase * _displaced_mesh
void buildEFAMesh()
Definition: XFEM.C:343

Member Data Documentation

◆ _cached_aux_solution

std::map<unique_id_type, std::vector<Real> > XFEM::_cached_aux_solution
private

Data structure to store the auxiliary solution for nodes/elements affected by XFEM For each node/element, this is stored as a vector that contains all components of all applicable variables in an order defined by getElementSolutionDofs() or getNodeSolutionDofs().

This vector first contains the current solution in that order, followed by the old and older solutions, also in that same order.

Definition at line 391 of file XFEM.h.

Referenced by cutMeshWithEFA(), and initSolution().

◆ _cached_solution

std::map<unique_id_type, std::vector<Real> > XFEM::_cached_solution
private

Data structure to store the nonlinear solution for nodes/elements affected by XFEM For each node/element, this is stored as a vector that contains all components of all applicable variables in an order defined by getElementSolutionDofs() or getNodeSolutionDofs().

This vector first contains the current solution in that order, followed by the old and older solutions, also in that same order.

Definition at line 382 of file XFEM.h.

Referenced by cutMeshWithEFA(), and initSolution().

◆ _crack_growth_increment

Real XFEM::_crack_growth_increment
private

Definition at line 332 of file XFEM.h.

Referenced by markCutEdgesByState(), and setCrackGrowthMethod().

◆ _crack_tip_elems

std::set<const Elem *> XFEM::_crack_tip_elems
private

Definition at line 337 of file XFEM.h.

Referenced by cutMeshWithEFA(), healMesh(), and isElemAtCrackTip().

◆ _crack_tip_elems_to_be_healed

std::set<const Elem *> XFEM::_crack_tip_elems_to_be_healed
private

Definition at line 338 of file XFEM.h.

Referenced by cutMeshWithEFA(), and healMesh().

◆ _cut_elem_map

std::map<unique_id_type, XFEMCutElem *> XFEM::_cut_elem_map
private

◆ _debug_output_level

unsigned int XFEM::_debug_output_level
private

Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mesh 3: Full dump of element fragment algorithm mesh.

Definition at line 369 of file XFEM.h.

Referenced by cutMeshWithEFA(), healMesh(), and setDebugOutputLevel().

◆ _efa_mesh

ElementFragmentAlgorithm XFEM::_efa_mesh
private

◆ _elem_crack_origin_direction_map

std::map<const Elem *, std::vector<Point> > XFEM::_elem_crack_origin_direction_map
private

◆ _geom_cut_elems

std::unordered_map<const Elem *, Xfem::CutElemInfo> XFEM::_geom_cut_elems
private

All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK.

This data structure is updated everytime a new cut element is created.

Definition at line 397 of file XFEM.h.

Referenced by cutMeshWithEFA(), healMesh(), storeMaterialPropertiesForElement(), and storeMaterialPropertiesForElementHelper().

◆ _geom_marked_elems_2d

std::map<const Elem *, std::vector<Xfem::GeomMarkedElemInfo2D> > XFEM::_geom_marked_elems_2d
private

Data structure for storing information about all 2D elements to be cut by geometry.

Definition at line 351 of file XFEM.h.

Referenced by addGeomMarkedElem2D(), clearGeomMarkedElems(), and markCutEdgesByGeometry().

◆ _geom_marked_elems_3d

std::map<const Elem *, std::vector<Xfem::GeomMarkedElemInfo3D> > XFEM::_geom_marked_elems_3d
private

Data structure for storing information about all 3D elements to be cut by geometry.

Definition at line 354 of file XFEM.h.

Referenced by addGeomMarkedElem3D(), clearGeomMarkedElems(), and markCutFacesByGeometry().

◆ _geom_marker_id_elems

std::map<unsigned int, std::set<unsigned int> > XFEM::_geom_marker_id_elems
private

Data structure for storing the elements cut by specific geometric cutters.

Definition at line 357 of file XFEM.h.

Referenced by addGeomMarkedElem2D(), addGeomMarkedElem3D(), cutMeshWithEFA(), getGeometricCutForElem(), and updateHeal().

◆ _geom_marker_id_map

std::map<const GeometricCutUserObject *, unsigned int> XFEM::_geom_marker_id_map
private

Data structure for storing the GeommetricCutUserObjects and their corresponding id.

Definition at line 360 of file XFEM.h.

Referenced by addGeometricCut(), and getGeometricCutID().

◆ _geometric_cuts

std::vector<const GeometricCutUserObject *> XFEM::_geometric_cuts
private

Definition at line 334 of file XFEM.h.

Referenced by addGeometricCut(), cutMeshWithEFA(), getGeometricCutForElem(), and healMesh().

◆ _has_secondary_cut

bool XFEM::_has_secondary_cut
private

Definition at line 327 of file XFEM.h.

Referenced by has_secondary_cut(), markCutEdgesByGeometry(), markCutEdgesByState(), and XFEM().

◆ _min_weight_multiplier

Real XFEM::_min_weight_multiplier
private

The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partial elements.

Definition at line 373 of file XFEM.h.

Referenced by getXFEMWeights(), and setMinWeightMultiplier().

◆ _old_geom_cut_elems

std::unordered_map<const Elem *, Xfem::CutElemInfo> XFEM::_old_geom_cut_elems
private

All geometrically cut elements and their CutElemInfo before the current execution of XFEM_MARK.

Definition at line 403 of file XFEM.h.

Referenced by cutMeshWithEFA().

◆ _sibling_displaced_elems

std::map<unsigned int, ElementPairLocator::ElementPairList> XFEM::_sibling_displaced_elems
private

Definition at line 340 of file XFEM.h.

Referenced by cutMeshWithEFA(), getXFEMDisplacedCutElemPairs(), and healMesh().

◆ _sibling_elems

std::map<unsigned int, ElementPairLocator::ElementPairList> XFEM::_sibling_elems
private

Definition at line 339 of file XFEM.h.

Referenced by cutMeshWithEFA(), getXFEMCutElemPairs(), and healMesh().

◆ _state_marked_elem_sides

std::map<const Elem *, unsigned int> XFEM::_state_marked_elem_sides
private

Definition at line 348 of file XFEM.h.

Referenced by addStateMarkedElem(), clearStateMarkedElems(), and markCutEdgesByState().

◆ _state_marked_elems

std::map<const Elem *, RealVectorValue> XFEM::_state_marked_elems
private

Definition at line 346 of file XFEM.h.

Referenced by addStateMarkedElem(), clearStateMarkedElems(), and markCutEdgesByState().

◆ _state_marked_frags

std::set<const Elem *> XFEM::_state_marked_frags
private

Definition at line 347 of file XFEM.h.

Referenced by addStateMarkedFrag(), clearStateMarkedElems(), and markCutEdgesByState().

◆ _use_crack_growth_increment

bool XFEM::_use_crack_growth_increment
private

Definition at line 331 of file XFEM.h.

Referenced by markCutEdgesByState(), and setCrackGrowthMethod().

◆ _XFEM_qrule

Xfem::XFEM_QRULE XFEM::_XFEM_qrule
private

Definition at line 329 of file XFEM.h.

Referenced by getXFEMQRule(), and setXFEMQRule().


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