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 339 of file XFEM.C.

Referenced by update(), and updateHeal().

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

Referenced by markCutEdgesByState().

456 {
457  std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
458  Point edge1(0.0, 0.0, 0.0);
459  Point edge2(0.0, 0.0, 0.0);
460  Point left_angle(0.0, 0.0, 0.0);
461  Point right_angle(0.0, 0.0, 0.0);
462  Point left_angle_normal(0.0, 0.0, 0.0);
463  Point right_angle_normal(0.0, 0.0, 0.0);
464  Point crack_direction_normal(0.0, 0.0, 0.0);
465  Point edge1_to_tip(0.0, 0.0, 0.0);
466  Point edge2_to_tip(0.0, 0.0, 0.0);
467  Point edge1_to_tip_normal(0.0, 0.0, 0.0);
468  Point edge2_to_tip_normal(0.0, 0.0, 0.0);
469 
470  Real cos_45 = std::cos(45.0 / 180.0 * 3.14159);
471  Real sin_45 = std::sin(45.0 / 180.0 * 3.14159);
472 
473  left_angle(0) = cos_45 * crack_tip_direction(0) - sin_45 * crack_tip_direction(1);
474  left_angle(1) = sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
475 
476  right_angle(0) = cos_45 * crack_tip_direction(0) + sin_45 * crack_tip_direction(1);
477  right_angle(1) = -sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
478 
479  left_angle_normal(0) = -left_angle(1);
480  left_angle_normal(1) = left_angle(0);
481 
482  right_angle_normal(0) = -right_angle(1);
483  right_angle_normal(1) = right_angle(0);
484 
485  crack_direction_normal(0) = -crack_tip_direction(1);
486  crack_direction_normal(1) = crack_tip_direction(0);
487 
488  Real angle_min = 0.0;
489  Real distance = 0.0;
490  unsigned int nsides = CEMElem->numEdges();
491 
492  for (unsigned int i = 0; i < nsides; ++i)
493  {
494  if (!orig_edge->isPartialOverlap(*CEMElem->getEdge(i)))
495  {
496  edge_ends[0] = getEFANodeCoords(CEMElem->getEdge(i)->getNode(0), CEMElem, elem);
497  edge_ends[1] = getEFANodeCoords(CEMElem->getEdge(i)->getNode(1), CEMElem, elem);
498 
499  edge1_to_tip = (edge_ends[0] * 0.95 + edge_ends[1] * 0.05) - crack_tip_origin;
500  edge2_to_tip = (edge_ends[0] * 0.05 + edge_ends[1] * 0.95) - crack_tip_origin;
501 
502  edge1_to_tip /= pow(edge1_to_tip.norm_sq(), 0.5);
503  edge2_to_tip /= pow(edge2_to_tip.norm_sq(), 0.5);
504 
505  edge1_to_tip_normal(0) = -edge1_to_tip(1);
506  edge1_to_tip_normal(1) = edge1_to_tip(0);
507 
508  edge2_to_tip_normal(0) = -edge2_to_tip(1);
509  edge2_to_tip_normal(1) = edge2_to_tip(0);
510 
511  Real angle_edge1_normal = edge1_to_tip_normal * normal;
512  Real angle_edge2_normal = edge2_to_tip_normal * normal;
513 
514  if (std::abs(angle_edge1_normal) > std::abs(angle_min) &&
515  (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
516  {
517  edge_id_keep = i;
518  distance_keep = 0.05;
519  normal_keep = edge1_to_tip_normal;
520  angle_min = angle_edge1_normal;
521  }
522  else if (std::abs(angle_edge2_normal) > std::abs(angle_min) &&
523  (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
524  {
525  edge_id_keep = i;
526  distance_keep = 0.95;
527  normal_keep = edge2_to_tip_normal;
528  angle_min = angle_edge2_normal;
529  }
530 
532  crack_tip_origin, left_angle_normal, edge_ends[0], edge_ends[1], distance) &&
533  (!CEMElem->isEdgePhantom(i)))
534  {
535  if (std::abs(left_angle_normal * normal) > std::abs(angle_min) &&
536  (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
537  {
538  edge_id_keep = i;
539  distance_keep = distance;
540  normal_keep = left_angle_normal;
541  angle_min = left_angle_normal * normal;
542  }
543  }
544  else if (initCutIntersectionEdge(
545  crack_tip_origin, right_angle_normal, edge_ends[0], edge_ends[1], distance) &&
546  (!CEMElem->isEdgePhantom(i)))
547  {
548  if (std::abs(right_angle_normal * normal) > std::abs(angle_min) &&
549  (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
550  {
551  edge_id_keep = i;
552  distance_keep = distance;
553  normal_keep = right_angle_normal;
554  angle_min = right_angle_normal * normal;
555  }
556  }
557  else if (initCutIntersectionEdge(crack_tip_origin,
558  crack_direction_normal,
559  edge_ends[0],
560  edge_ends[1],
561  distance) &&
562  (!CEMElem->isEdgePhantom(i)))
563  {
564  if (std::abs(crack_direction_normal * normal) > std::abs(angle_min) &&
565  (crack_tip_direction * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
566  {
567  edge_id_keep = i;
568  distance_keep = distance;
569  normal_keep = crack_direction_normal;
570  angle_min = crack_direction_normal * normal;
571  }
572  }
573  }
574  }
575 
576  // avoid small volume fraction cut
577  if ((distance_keep - 0.05) < 0.0)
578  {
579  distance_keep = 0.05;
580  }
581  else if ((distance_keep - 0.95) > 0.0)
582  {
583  distance_keep = 0.95;
584  }
585 }
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:901
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:1599

◆ cutMeshWithEFA()

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

Definition at line 1104 of file XFEM.C.

Referenced by update().

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

1672 {
1673  Real comp = 0.0;
1674  Point planedata(0.0, 0.0, 0.0);
1675  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1676  it = _cut_elem_map.find(elem->unique_id());
1677  if (it != _cut_elem_map.end())
1678  {
1679  const XFEMCutElem * xfce = it->second;
1680  const EFAElement * EFAelem = xfce->getEFAElement();
1681  if (EFAelem->isPartial()) // exclude the full crack tip elements
1682  {
1683  if ((unsigned int)quantity < 3)
1684  {
1685  unsigned int index = (unsigned int)quantity;
1686  planedata = xfce->getCutPlaneOrigin(plane_id, _displaced_mesh);
1687  comp = planedata(index);
1688  }
1689  else if ((unsigned int)quantity < 6)
1690  {
1691  unsigned int index = (unsigned int)quantity - 3;
1692  planedata = xfce->getCutPlaneNormal(plane_id, _displaced_mesh);
1693  comp = planedata(index);
1694  }
1695  else
1696  mooseError("In get_cut_plane index out of range");
1697  }
1698  }
1699  return comp;
1700 }
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 2292 of file XFEM.C.

Referenced by cutMeshWithEFA().

2295 {
2296  if (!parent_elem)
2297  parent_elem = cut_elem;
2298  // Pick any node from the parent element that is inside the physical domain and return its
2299  // CutSubdomainID.
2300  const Node * node = pickFirstPhysicalNode(cut_elem, parent_elem);
2301  return gcuo->getCutSubdomainID(node);
2302 }
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:2305
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 1749 of file XFEM.C.

Referenced by markCutEdgesByGeometry(), and markCutEdgesByState().

1750 {
1751  EFAElement * EFAelem = _efa_mesh.getElemByID(elem->id());
1752  EFAElement2D * EFAelem2D = dynamic_cast<EFAElement2D *>(EFAelem);
1753 
1754  if (!EFAelem2D)
1755  mooseError("EFAelem is not of EFAelement2D type");
1756 
1757  return EFAelem2D;
1758 }
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 1761 of file XFEM.C.

Referenced by markCutFacesByGeometry().

1762 {
1763  EFAElement * EFAelem = _efa_mesh.getElemByID(elem->id());
1764  EFAElement3D * EFAelem3D = dynamic_cast<EFAElement3D *>(EFAelem);
1765 
1766  if (!EFAelem3D)
1767  mooseError("EFAelem is not of EFAelement3D type");
1768 
1769  return EFAelem3D;
1770 }
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 1599 of file XFEM.C.

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

1603 {
1604  Point node_coor(0.0, 0.0, 0.0);
1605  std::vector<EFANode *> master_nodes;
1606  std::vector<Point> master_points;
1607  std::vector<double> master_weights;
1608 
1609  CEMElem->getMasterInfo(CEMnode, master_nodes, master_weights);
1610  for (std::size_t i = 0; i < master_nodes.size(); ++i)
1611  {
1612  if (master_nodes[i]->category() == EFANode::N_CATEGORY_PERMANENT)
1613  {
1614  unsigned int local_node_id = CEMElem->getLocalNodeIndex(master_nodes[i]);
1615  const Node * node = elem->node_ptr(local_node_id);
1616  if (displaced_mesh)
1617  node = displaced_mesh->node_ptr(node->id());
1618  Point node_p((*node)(0), (*node)(1), (*node)(2));
1619  master_points.push_back(node_p);
1620  }
1621  else
1622  mooseError("master nodes must be permanent");
1623  }
1624  for (std::size_t i = 0; i < master_nodes.size(); ++i)
1625  node_coor += master_weights[i] * master_points[i];
1626 
1627  return node_coor;
1628 }
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 2118 of file XFEM.C.

Referenced by setSolution(), and storeSolutionForElement().

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

1776 {
1777  // N.B. CEMElem here has global EFAnode
1778  frag_edges.clear();
1779  if (CEMElem->numFragments() > 0)
1780  {
1781  if (CEMElem->numFragments() > 1)
1782  mooseError("element ", elem->id(), " has more than one fragment at this point");
1783  for (unsigned int i = 0; i < CEMElem->getFragment(0)->numEdges(); ++i)
1784  {
1785  std::vector<Point> p_line(2, Point(0.0, 0.0, 0.0));
1786  p_line[0] = getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(0), CEMElem, elem);
1787  p_line[1] = getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(1), CEMElem, elem);
1788  frag_edges.push_back(p_line);
1789  }
1790  }
1791 }
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:1599
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 1732 of file XFEM.C.

1735 {
1736  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1737  it = _cut_elem_map.find(elem->unique_id());
1738  if (it != _cut_elem_map.end())
1739  {
1740  const XFEMCutElem * xfce = it->second;
1741  if (displaced_mesh)
1742  xfce->getFragmentFaces(frag_faces, _displaced_mesh);
1743  else
1744  xfce->getFragmentFaces(frag_faces);
1745  }
1746 }
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 1794 of file XFEM.C.

1797 {
1798  // N.B. CEMElem here has global EFAnode
1799  frag_faces.clear();
1800  if (CEMElem->numFragments() > 0)
1801  {
1802  if (CEMElem->numFragments() > 1)
1803  mooseError("element ", elem->id(), " has more than one fragment at this point");
1804  for (unsigned int i = 0; i < CEMElem->getFragment(0)->numFaces(); ++i)
1805  {
1806  unsigned int num_face_nodes = CEMElem->getFragmentFace(0, i)->numNodes();
1807  std::vector<Point> p_line(num_face_nodes, Point(0.0, 0.0, 0.0));
1808  for (unsigned int j = 0; j < num_face_nodes; ++j)
1809  p_line[j] = getEFANodeCoords(CEMElem->getFragmentFace(0, i)->getNode(j), CEMElem, elem);
1810  frag_faces.push_back(p_line);
1811  }
1812  }
1813 }
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:1599
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 2176 of file XFEM.C.

Referenced by cutMeshWithEFA().

2177 {
2178  for (auto gcmit : _geom_marker_id_elems)
2179  {
2180  std::set<unsigned int> elems = gcmit.second;
2181  if (elems.find(elem->id()) != elems.end())
2182  return _geometric_cuts[gcmit.first];
2183  }
2184  return nullptr;
2185 }
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 2144 of file XFEM.C.

Referenced by setSolution(), and storeSolutionForNode().

2145 {
2146  const std::set<SubdomainID> & sids = _moose_mesh->getNodeBlockIds(*node);
2147  const std::vector<MooseVariableFEBase *> & vars = sys.getVariables(0);
2148  std::vector<dof_id_type> solution_dofs;
2149  solution_dofs.reserve(vars.size()); // just an approximation
2150  for (auto var : vars)
2151  {
2152  if (var->isNodal())
2153  {
2154  const std::set<SubdomainID> & var_subdomains = sys.getSubdomainsForVar(var->number());
2155  std::set<SubdomainID> intersect;
2156  set_intersection(var_subdomains.begin(),
2157  var_subdomains.end(),
2158  sids.begin(),
2159  sids.end(),
2160  std::inserter(intersect, intersect.begin()));
2161  if (var_subdomains.empty() || !intersect.empty())
2162  {
2163  unsigned int n_comp = node->n_comp(sys.number(), var->number());
2164  for (unsigned int icomp = 0; icomp < n_comp; ++icomp)
2165  {
2166  dof_id_type node_dof = node->dof_number(sys.number(), var->number(), icomp);
2167  solution_dofs.push_back(node_dof);
2168  }
2169  }
2170  }
2171  }
2172  return solution_dofs;
2173 }
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 1631 of file XFEM.C.

Referenced by markCutEdgesByState().

1632 {
1633  Real phys_volfrac = 1.0;
1634  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1635  it = _cut_elem_map.find(elem->unique_id());
1636  if (it != _cut_elem_map.end())
1637  {
1638  XFEMCutElem * xfce = it->second;
1639  const EFAElement * EFAelem = xfce->getEFAElement();
1640  if (EFAelem->isPartial())
1641  { // exclude the full crack tip elements
1643  phys_volfrac = xfce->getPhysicalVolumeFraction();
1644  }
1645  }
1646 
1647  return phys_volfrac;
1648 }
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 1881 of file XFEM.C.

1886 {
1887  bool have_weights = false;
1888  XFEMCutElem * xfce = nullptr;
1889  if (isElemCut(elem, xfce))
1890  {
1891  mooseAssert(xfce != nullptr, "Must have valid XFEMCutElem object here");
1892  xfce->getFaceWeightMultipliers(weights, qrule, getXFEMQRule(), q_points, side);
1893  have_weights = true;
1894  }
1895  return have_weights;
1896 }
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:1816
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition: XFEM.C:1709

◆ 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 1899 of file XFEM.C.

1904 {
1905  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1906  it = _cut_elem_map.find(elem->unique_id());
1907  if (it != _cut_elem_map.end())
1908  {
1909  const XFEMCutElem * xfce = it->second;
1910  if (displaced_mesh)
1911  xfce->getIntersectionInfo(plane_id, normal, intersectionPoints, _displaced_mesh);
1912  else
1913  xfce->getIntersectionInfo(plane_id, normal, intersectionPoints);
1914  }
1915 }
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 1816 of file XFEM.C.

Referenced by getXFEMFaceWeights(), and getXFEMWeights().

1817 {
1818  return _XFEM_qrule;
1819 }
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 1918 of file XFEM.C.

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

◆ getXFEMqRuleOnSurface()

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

Definition at line 1945 of file XFEM.C.

1948 {
1949  std::size_t nnd_pe = intersection_points.size();
1950  Point xcrd(0.0, 0.0, 0.0);
1951  for (std::size_t i = 0; i < nnd_pe; ++i)
1952  xcrd += intersection_points[i];
1953  xcrd /= nnd_pe;
1954 
1955  quad_pts.resize(nnd_pe);
1956  quad_wts.resize(nnd_pe);
1957 
1958  Real jac = 0.0;
1959 
1960  for (std::size_t j = 0; j < nnd_pe; ++j) // loop all sub-tris
1961  {
1962  std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
1963  std::vector<Point> subtrig_points(3, Point(0.0, 0.0, 0.0)); // sub-trig nodal coords
1964 
1965  int jplus1 = j < nnd_pe - 1 ? j + 1 : 0;
1966  subtrig_points[0] = xcrd;
1967  subtrig_points[1] = intersection_points[j];
1968  subtrig_points[2] = intersection_points[jplus1];
1969 
1970  std::vector<std::vector<Real>> sg2;
1971  Xfem::stdQuadr2D(3, 1, sg2); // get sg2
1972  for (std::size_t l = 0; l < sg2.size(); ++l) // loop all int pts on a sub-trig
1973  {
1974  Xfem::shapeFunc2D(3, sg2[l], subtrig_points, shape, jac, true); // Get shape
1975  std::vector<Real> tsg_line(3, 0.0);
1976  for (std::size_t k = 0; k < 3; ++k) // loop sub-trig nodes
1977  {
1978  tsg_line[0] += shape[k][2] * subtrig_points[k](0);
1979  tsg_line[1] += shape[k][2] * subtrig_points[k](1);
1980  tsg_line[2] += shape[k][2] * subtrig_points[k](2);
1981  }
1982  quad_pts[j + l] = Point(tsg_line[0], tsg_line[1], tsg_line[2]);
1983  quad_wts[j + l] = sg2[l][3] * jac;
1984  }
1985  }
1986 }
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:130

◆ getXFEMWeights()

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

Definition at line 1852 of file XFEM.C.

1856 {
1857  bool have_weights = false;
1858  XFEMCutElem * xfce = nullptr;
1859  if (isElemCut(elem, xfce))
1860  {
1861  mooseAssert(xfce != nullptr, "Must have valid XFEMCutElem object here");
1862  xfce->getWeightMultipliers(weights, qrule, getXFEMQRule(), q_points);
1863  have_weights = true;
1864 
1865  Real ave_weight_multiplier = 0;
1866  for (unsigned int i = 0; i < weights.size(); ++i)
1867  ave_weight_multiplier += weights[i];
1868  ave_weight_multiplier /= weights.size();
1869 
1870  if (ave_weight_multiplier < _min_weight_multiplier)
1871  {
1872  const Real amount_to_add = _min_weight_multiplier - ave_weight_multiplier;
1873  for (unsigned int i = 0; i < weights.size(); ++i)
1874  weights[i] += amount_to_add;
1875  }
1876  }
1877  return have_weights;
1878 }
unsigned int size() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Xfem::XFEM_QRULE & getXFEMQRule()
Definition: XFEM.C:1816
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition: XFEM.C:1709
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 920 of file XFEM.C.

Referenced by updateHeal().

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

Referenced by correctCrackExtensionDirection(), and markCutEdgesByState().

903 {
904  dist = 0.0;
905  bool does_intersect = false;
906  Point origin2p1 = edge_p1 - cut_origin;
907  Real plane2p1 = cut_normal(0) * origin2p1(0) + cut_normal(1) * origin2p1(1);
908  Point origin2p2 = edge_p2 - cut_origin;
909  Real plane2p2 = cut_normal(0) * origin2p2(0) + cut_normal(1) * origin2p2(1);
910 
911  if (plane2p1 * plane2p2 < 0.0)
912  {
913  dist = -plane2p1 / (plane2p2 - plane2p1);
914  does_intersect = true;
915  }
916  return does_intersect;
917 }
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 308 of file XFEM.C.

310 {
311  if (nls.size() != 1)
312  mooseError("XFEM does not currently support multiple nonlinear systems");
313 
314  nls[0]->serializeSolution();
315  aux.serializeSolution();
316  NumericVector<Number> & current_solution = *nls[0]->system().current_local_solution;
317  NumericVector<Number> & old_solution = nls[0]->solutionOld();
318  NumericVector<Number> & older_solution = nls[0]->solutionOlder();
319  NumericVector<Number> & current_aux_solution = *aux.system().current_local_solution;
320  NumericVector<Number> & old_aux_solution = aux.solutionOld();
321  NumericVector<Number> & older_aux_solution = aux.solutionOlder();
322 
323  setSolution(*nls[0], _cached_solution, current_solution, old_solution, older_solution);
324  setSolution(
325  aux, _cached_aux_solution, current_aux_solution, old_aux_solution, older_aux_solution);
326 
327  current_solution.close();
328  old_solution.close();
329  older_solution.close();
330  current_aux_solution.close();
331  old_aux_solution.close();
332  older_aux_solution.close();
333 
334  _cached_solution.clear();
335  _cached_aux_solution.clear();
336 }
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:2057
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 1703 of file XFEM.C.

Referenced by markCutEdgesByGeometry(), and markCutEdgesByState().

1704 {
1705  return (_crack_tip_elems.find(elem) != _crack_tip_elems.end());
1706 }
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 1709 of file XFEM.C.

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

1710 {
1711  const auto it = _cut_elem_map.find(elem->unique_id());
1712  if (it != _cut_elem_map.end())
1713  {
1714  xfce = it->second;
1715  const EFAElement * EFAelem = xfce->getEFAElement();
1716  if (EFAelem->isPartial()) // exclude the full crack tip elements
1717  return true;
1718  }
1719 
1720  xfce = nullptr;
1721  return false;
1722 }
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 1725 of file XFEM.C.

1726 {
1727  XFEMCutElem * xfce;
1728  return isElemCut(elem, xfce);
1729 }
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition: XFEM.C:1709

◆ 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 1651 of file XFEM.C.

Referenced by pickFirstPhysicalNode().

1652 {
1653  std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1654  it = _cut_elem_map.find(elem->unique_id());
1655  if (it != _cut_elem_map.end())
1656  {
1657  XFEMCutElem * xfce = it->second;
1658 
1659  if (xfce->isPointPhysical(point))
1660  return true;
1661  }
1662  else
1663  return true;
1664 
1665  return false;
1666 }
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 2258 of file XFEM.C.

Referenced by cutMeshWithEFA(), and healMesh().

2262 {
2263  // Restore the element material properties
2264  mooseAssert(cached_cei.count(elem_from) > 0, "XFEM: Unable to find cached material properties.");
2265  Xfem::CutElemInfo & cei = cached_cei[elem_from];
2266 
2267  // Load element material properties from cached properties
2269  cei._elem_material_properties,
2270  _material_data[0]->getMaterialPropertyStorageForXFEM({}));
2271 
2272  // Check if any of the element side need material properties
2273  bool need_boundary_materials = false;
2274  for (unsigned int side = 0; side < elem->n_sides(); ++side)
2275  {
2276  std::vector<boundary_id_type> elem_boundary_ids;
2277  _mesh->get_boundary_info().boundary_ids(elem, side, elem_boundary_ids);
2278  for (auto bdid : elem_boundary_ids)
2280  need_boundary_materials = true;
2281  }
2282 
2283  // Load boundary material properties from cached properties
2284  if (need_boundary_materials)
2286  elem,
2287  cei._bnd_material_properties,
2288  _bnd_material_data[0]->getMaterialPropertyStorageForXFEM({}));
2289 }
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:2234
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 2234 of file XFEM.C.

Referenced by loadMaterialPropertiesForElement().

2237 {
2238  if (!storage.hasStatefulProperties())
2239  return;
2240 
2241  for (const auto state : storage.statefulIndexRange())
2242  {
2243  const auto & serialized_props = cached_props[state - 1];
2244  for (const auto & [side, serialized_side_props] : serialized_props)
2245  {
2246  std::istringstream iss;
2247  iss.str(serialized_side_props);
2248  iss.clear();
2249 
2250  // This is very dirty. We should not write to MOOSE's stateful properties.
2251  // Please remove me :(
2252  dataLoad(iss, storage.setProps(elem, side, state), nullptr);
2253  }
2254  }
2255 }
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 395 of file XFEM.C.

Referenced by markCuts().

396 {
397  bool marked_edges = false;
398  bool marked_nodes = false;
399 
400  for (const auto & gme : _geom_marked_elems_2d)
401  {
402  for (const auto & gmei : gme.second)
403  {
404  EFAElement2D * EFAElem = getEFAElem2D(gme.first);
405 
406  for (unsigned int i = 0; i < gmei._elem_cut_edges.size(); ++i) // mark element edges
407  {
408  if (!EFAElem->isEdgePhantom(
409  gmei._elem_cut_edges[i]._host_side_id)) // must not be phantom edge
410  {
411  _efa_mesh.addElemEdgeIntersection(gme.first->id(),
412  gmei._elem_cut_edges[i]._host_side_id,
413  gmei._elem_cut_edges[i]._distance);
414  marked_edges = true;
415  }
416  }
417 
418  for (unsigned int i = 0; i < gmei._elem_cut_nodes.size(); ++i) // mark element edges
419  {
420  _efa_mesh.addElemNodeIntersection(gme.first->id(), gmei._elem_cut_nodes[i]._host_id);
421  marked_nodes = true;
422  }
423 
424  for (unsigned int i = 0; i < gmei._frag_cut_edges.size();
425  ++i) // MUST DO THIS AFTER MARKING ELEMENT EDGES
426  {
427  if (!EFAElem->getFragment(0)->isSecondaryInteriorEdge(
428  gmei._frag_cut_edges[i]._host_side_id))
429  {
430  if (_efa_mesh.addFragEdgeIntersection(gme.first->id(),
431  gmei._frag_cut_edges[i]._host_side_id,
432  gmei._frag_cut_edges[i]._distance))
433  {
434  marked_edges = true;
435  if (!isElemAtCrackTip(gme.first))
436  _has_secondary_cut = true;
437  }
438  }
439  }
440  }
441  }
442 
443  return marked_edges || marked_nodes;
444 }
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:1703
EFAElement2D * getEFAElem2D(const Elem *elem)
Get the EFAElement2D object for a specified libMesh element.
Definition: XFEM.C:1749

◆ markCutEdgesByState()

bool XFEM::markCutEdgesByState ( Real  time)

Definition at line 588 of file XFEM.C.

Referenced by markCuts().

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

◆ markCutFacesByGeometry()

bool XFEM::markCutFacesByGeometry ( )

Definition at line 852 of file XFEM.C.

Referenced by markCuts().

853 {
854  bool marked_faces = false;
855 
856  for (const auto & gme : _geom_marked_elems_3d)
857  {
858  for (const auto & gmei : gme.second)
859  {
860  EFAElement3D * EFAElem = getEFAElem3D(gme.first);
861 
862  for (unsigned int i = 0; i < gmei._elem_cut_faces.size(); ++i) // mark element faces
863  {
864  if (!EFAElem->isFacePhantom(gmei._elem_cut_faces[i]._face_id)) // must not be phantom face
865  {
866  _efa_mesh.addElemFaceIntersection(gme.first->id(),
867  gmei._elem_cut_faces[i]._face_id,
868  gmei._elem_cut_faces[i]._face_edge,
869  gmei._elem_cut_faces[i]._position);
870  marked_faces = true;
871  }
872  }
873 
874  for (unsigned int i = 0; i < gmei._frag_cut_faces.size();
875  ++i) // MUST DO THIS AFTER MARKING ELEMENT EDGES
876  {
877  if (!EFAElem->getFragment(0)->isThirdInteriorFace(gmei._frag_cut_faces[i]._face_id))
878  {
879  _efa_mesh.addFragFaceIntersection(gme.first->id(),
880  gmei._frag_cut_faces[i]._face_id,
881  gmei._frag_cut_faces[i]._face_edge,
882  gmei._frag_cut_faces[i]._position);
883  marked_faces = true;
884  }
885  }
886  }
887  }
888 
889  return marked_faces;
890 }
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:1761

◆ markCutFacesByState()

bool XFEM::markCutFacesByState ( )

Definition at line 893 of file XFEM.C.

Referenced by markCuts().

894 {
895  bool marked_faces = false;
896  // TODO: need to finish this for 3D problems
897  return marked_faces;
898 }

◆ markCuts()

bool XFEM::markCuts ( Real  time)

Definition at line 378 of file XFEM.C.

Referenced by update().

379 {
380  bool marked_sides = false;
381  if (_mesh->mesh_dimension() == 2)
382  {
383  marked_sides = markCutEdgesByGeometry();
384  marked_sides |= markCutEdgesByState(time);
385  }
386  else if (_mesh->mesh_dimension() == 3)
387  {
388  marked_sides = markCutFacesByGeometry();
389  marked_sides |= markCutFacesByState();
390  }
391  return marked_sides;
392 }
bool markCutEdgesByState(Real time)
Definition: XFEM.C:588
bool markCutEdgesByGeometry()
Definition: XFEM.C:395
MeshBase * _mesh
bool markCutFacesByGeometry()
Definition: XFEM.C:852
bool markCutFacesByState()
Definition: XFEM.C:893

◆ 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 2305 of file XFEM.C.

Referenced by getCutSubdomainID().

2306 {
2307  for (auto i : e0->node_index_range())
2308  if (isPointInsidePhysicalDomain(e, e0->node_ref(i)))
2309  return e0->node_ptr(i);
2310  mooseError("cannot find a physical node in the current element");
2311  return nullptr;
2312 }
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:1651

◆ setCrackGrowthMethod()

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

Definition at line 1833 of file XFEM.C.

1834 {
1835  _use_crack_growth_increment = use_crack_growth_increment;
1836  _crack_growth_increment = crack_growth_increment;
1837 }
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 1840 of file XFEM.C.

1841 {
1842  _debug_output_level = debug_output_level;
1843 }
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 1846 of file XFEM.C.

1847 {
1848  _min_weight_multiplier = min_weight_multiplier;
1849 }
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 2057 of file XFEM.C.

Referenced by initSolution().

2062 {
2063  for (auto & node : _mesh->local_node_ptr_range())
2064  {
2065  auto mit = stored_solution.find(node->unique_id());
2066  if (mit != stored_solution.end())
2067  {
2068  const std::vector<Real> & stored_node_solution = mit->second;
2069  std::vector<dof_id_type> stored_solution_dofs = getNodeSolutionDofs(node, sys);
2070  setSolutionForDOFs(stored_node_solution,
2071  stored_solution_dofs,
2072  current_solution,
2073  old_solution,
2074  older_solution);
2075  }
2076  }
2077 
2078  for (auto & elem : as_range(_mesh->local_elements_begin(), _mesh->local_elements_end()))
2079  {
2080  auto mit = stored_solution.find(elem->unique_id());
2081  if (mit != stored_solution.end())
2082  {
2083  const std::vector<Real> & stored_elem_solution = mit->second;
2084  std::vector<dof_id_type> stored_solution_dofs = getElementSolutionDofs(elem, sys);
2085  setSolutionForDOFs(stored_elem_solution,
2086  stored_solution_dofs,
2087  current_solution,
2088  old_solution,
2089  older_solution);
2090  }
2091  }
2092 }
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:2095
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:2144
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:2118

◆ 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 2095 of file XFEM.C.

Referenced by setSolution().

2100 {
2101  // Solution vector is stored first for current, then old and older solutions.
2102  // These are the offsets to the beginning of the old and older solutions in the vector.
2103  const auto old_solution_offset = stored_solution_dofs.size();
2104  const auto older_solution_offset = old_solution_offset * 2;
2105 
2106  for (std::size_t i = 0; i < stored_solution_dofs.size(); ++i)
2107  {
2108  current_solution.set(stored_solution_dofs[i], stored_solution[i]);
2109  if (_fe_problem->isTransient())
2110  {
2111  old_solution.set(stored_solution_dofs[i], stored_solution[old_solution_offset + i]);
2112  older_solution.set(stored_solution_dofs[i], stored_solution[older_solution_offset + i]);
2113  }
2114  }
2115 }
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 1822 of file XFEM.C.

1823 {
1824  if (xfem_qrule == "volfrac")
1826  else if (xfem_qrule == "moment_fitting")
1828  else if (xfem_qrule == "direct")
1830 }
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 2206 of file XFEM.C.

Referenced by healMesh().

2207 {
2208  // Set the parent element so that it is consistent post-healing
2209  _geom_cut_elems[child_elem]._parent_elem = parent_elem;
2210 
2211  // Locally store the element material properties
2213  _material_data[0]->getMaterialPropertyStorageForXFEM({}));
2214 
2215  // Locally store the boundary material properties
2216  // First check if any of the side need material properties
2217  bool need_boundary_materials = false;
2218  for (unsigned int side = 0; side < child_elem->n_sides(); ++side)
2219  {
2220  std::vector<boundary_id_type> elem_boundary_ids;
2221  _mesh->get_boundary_info().boundary_ids(child_elem, side, elem_boundary_ids);
2222  for (auto bdid : elem_boundary_ids)
2224  need_boundary_materials = true;
2225  }
2226 
2227  // If boundary material properties are needed for this element, then store them.
2228  if (need_boundary_materials)
2230  child_elem, _bnd_material_data[0]->getMaterialPropertyStorageForXFEM({}));
2231 }
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:2188
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 2188 of file XFEM.C.

Referenced by storeMaterialPropertiesForElement().

2189 {
2190  for (const auto state : storage.statefulIndexRange())
2191  {
2192  const auto & elem_props = storage.props(state).at(elem);
2193  auto & serialized_props = _geom_cut_elems[elem]._elem_material_properties[state - 1];
2194  serialized_props.clear();
2195  for (const auto & side_props_pair : elem_props)
2196  {
2197  const auto side = side_props_pair.first;
2198  std::ostringstream oss;
2199  dataStore(oss, storage.setProps(elem, side, state), nullptr);
2200  serialized_props[side].assign(oss.str());
2201  }
2202  }
2203 }
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 2023 of file XFEM.C.

Referenced by cutMeshWithEFA().

2030 {
2031  std::vector<dof_id_type> stored_solution_dofs = getElementSolutionDofs(elem_to_store_from, sys);
2032  std::vector<Real> stored_solution_scratch;
2033  // Size for current solution, as well as for old, and older solution only for transient case
2034  std::size_t stored_solution_size =
2035  (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
2036  stored_solution_scratch.reserve(stored_solution_size);
2037 
2038  // Store in the order defined in stored_solution_dofs first for the current, then for old and
2039  // older if applicable
2040  for (auto dof : stored_solution_dofs)
2041  stored_solution_scratch.push_back(current_solution(dof));
2042 
2043  if (_fe_problem->isTransient())
2044  {
2045  for (auto dof : stored_solution_dofs)
2046  stored_solution_scratch.push_back(old_solution(dof));
2047 
2048  for (auto dof : stored_solution_dofs)
2049  stored_solution_scratch.push_back(older_solution(dof));
2050  }
2051 
2052  if (stored_solution_scratch.size() > 0)
2053  stored_solution[elem_to_store_to->unique_id()] = stored_solution_scratch;
2054 }
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:2118
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 1989 of file XFEM.C.

Referenced by cutMeshWithEFA().

1996 {
1997  std::vector<dof_id_type> stored_solution_dofs = getNodeSolutionDofs(node_to_store_from, sys);
1998  std::vector<Real> stored_solution_scratch;
1999  // Size for current solution, as well as for old, and older solution only for transient case
2000  std::size_t stored_solution_size =
2001  (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
2002  stored_solution_scratch.reserve(stored_solution_size);
2003 
2004  // Store in the order defined in stored_solution_dofs first for the current, then for old and
2005  // older if applicable
2006  for (auto dof : stored_solution_dofs)
2007  stored_solution_scratch.push_back(current_solution(dof));
2008 
2009  if (_fe_problem->isTransient())
2010  {
2011  for (auto dof : stored_solution_dofs)
2012  stored_solution_scratch.push_back(old_solution(dof));
2013 
2014  for (auto dof : stored_solution_dofs)
2015  stored_solution_scratch.push_back(older_solution(dof));
2016  }
2017 
2018  if (stored_solution_scratch.size() > 0)
2019  stored_solution[node_to_store_to->unique_id()] = stored_solution_scratch;
2020 }
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:2144
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  bool mesh_changed = false;
271 
272  buildEFAMesh();
273 
275 
277 
278  if (markCuts(time))
279  mesh_changed = cutMeshWithEFA(nl, aux);
280 
281  if (mesh_changed)
282  {
283  buildEFAMesh();
285  }
286 
287  if (mesh_changed)
288  {
289  _mesh->allow_renumbering(false);
290  _mesh->skip_partitioning(true);
291  _mesh->prepare_for_use();
292 
293  if (_displaced_mesh)
294  {
295  _displaced_mesh->allow_renumbering(false);
296  _displaced_mesh->skip_partitioning(true);
297  _displaced_mesh->prepare_for_use();
298  }
299  }
300 
303 
304  return mesh_changed;
305 }
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:1104
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:378
MeshBase * _mesh
MooseMesh * _moose_mesh
MeshBase * _displaced_mesh
void clearStateMarkedElems()
Definition: XFEM.C:152
void buildEFAMesh()
Definition: XFEM.C:339
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:920
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:339

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: