https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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.
 
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.
 
void clearGeomMarkedElems ()
 Clear out the list of elements to be marked for cutting.
 
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.
 
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.
 
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.
 
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.
 
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_QRULE & getXFEMQRule ()
 
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.
 
void setMinWeightMultiplier (Real min_weight_multiplier)
 Controls the minimum average weight multiplier for each element.
 
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::ElementPairList * getXFEMCutElemPairs (unsigned int interface_id)
 Get the list of cut element pairs corresponding to a given interface ID.
 
virtual const ElementPairLocator::ElementPairList * getXFEMDisplacedCutElemPairs (unsigned int interface_id)
 Get the list of cut element pairs on the displaced mesh corresponding to a given interface ID.
 
virtual unsigned int getGeometricCutID (const GeometricCutUserObject *gcu)
 Get the interface ID corresponding to a given GeometricCutUserObject.
 
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 ()
 
EFAElement2D * getEFAElem2D (const Elem *elem)
 Get the EFAElement2D object for a specified libMesh element.
 
EFAElement3D * getEFAElem3D (const Elem *elem)
 Get the EFAElement3D object for a specified libMesh element.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
const GeometricCutUserObject * getGeometricCutForElem (const Elem *elem) const
 Get the GeometricCutUserObject associated with an element.
 
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.
 
void loadMaterialPropertiesForElementHelper (const Elem *elem, const Xfem::CachedMaterialProperties &cached_props, MaterialPropertyStorage &storage) const
 Load the material properties.
 
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.
 
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.
 

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
 
int _state_marked_t_step
 The timestep index at which the state marks were added.
 
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.
 
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.
 
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
 Data structure for storing the elements cut by specific geometric cutters.
 
std::map< const GeometricCutUserObject *, unsigned int > _geom_marker_id_map
 Data structure for storing the GeommetricCutUserObjects and their corresponding id.
 
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.
 
Real _min_weight_multiplier
 The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partial elements.
 
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().
 
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().
 
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
 All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK.
 
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.
 

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),
39 _efa_mesh(Moose::out),
42{
43#ifndef LIBMESH_ENABLE_UNIQUE_ID
44 mooseError("MOOSE requires unique ids to be enabled in libmesh (configure with "
45 "--enable-unique-id) to use XFEM!");
46#endif
47 _has_secondary_cut = false;
48}
void mooseError(Args &&... args)
bool _has_secondary_cut
Definition XFEM.h:327
ElementFragmentAlgorithm _efa_mesh
Definition XFEM.h:367
int _state_marked_t_step
The timestep index at which the state marks were added.
Definition XFEM.h:353
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
Definition XFEM.h:374
Real _min_weight_multiplier
The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partia...
Definition XFEM.h:378

◆ ~XFEM()

XFEM::~XFEM ( )

Definition at line 50 of file XFEM.C.

51{
52 for (std::map<unique_id_type, XFEMCutElem *>::iterator cemit = _cut_elem_map.begin();
53 cemit != _cut_elem_map.end();
54 ++cemit)
55 delete cemit->second;
56}
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 59 of file XFEM.C.

60{
61 _geometric_cuts.push_back(geometric_cut);
62
63 geometric_cut->setInterfaceID(_geometric_cuts.size() - 1);
64
65 _geom_marker_id_map[geometric_cut] = _geometric_cuts.size() - 1;
66}
void setInterfaceID(unsigned int interface_id)
Set the interface ID for this cutting object.
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:365

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

165{
166 Elem * elem = _mesh->elem_ptr(elem_id);
167 _geom_marked_elems_2d[elem].push_back(geom_info);
168 _geom_marker_id_elems[interface_id].insert(elem_id);
169}
MeshBase * _mesh
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:362
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:356

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

175{
176 Elem * elem = _mesh->elem_ptr(elem_id);
177 _geom_marked_elems_3d[elem].push_back(geom_info);
178 _geom_marker_id_elems[interface_id].insert(elem_id);
179}
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:359

◆ addStateMarkedElem() [1/2]

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

Definition at line 115 of file XFEM.C.

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

Referenced by addStateMarkedElem(), and addStateMarkedFrag().

◆ addStateMarkedElem() [2/2]

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

Definition at line 127 of file XFEM.C.

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

◆ addStateMarkedFrag()

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

Definition at line 140 of file XFEM.C.

141{
142 addStateMarkedElem(elem_id, normal);
143 Elem * elem = _mesh->elem_ptr(elem_id);
144 std::set<const Elem *>::iterator mit;
145 mit = _state_marked_frags.find(elem);
146 if (mit != _state_marked_frags.end())
148 " ERROR: element ", elem->id(), " already marked for fragment-secondary crack initiation.");
149
150 _state_marked_frags.insert(elem);
151}
std::set< const Elem * > _state_marked_frags
Definition XFEM.h:347

◆ buildEFAMesh()

void XFEM::buildEFAMesh ( )

Definition at line 348 of file XFEM.C.

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

Referenced by update(), and updateHeal().

◆ clearGeomMarkedElems()

void XFEM::clearGeomMarkedElems ( )

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

Called after cutting is done.

Definition at line 182 of file XFEM.C.

183{
184 _geom_marked_elems_2d.clear();
185 _geom_marked_elems_3d.clear();
186}

Referenced by update().

◆ clearStateMarkedElems()

void XFEM::clearStateMarkedElems ( )

Definition at line 154 of file XFEM.C.

155{
156 _state_marked_elems.clear();
157 _state_marked_frags.clear();
159}

Referenced by update().

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

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

Referenced by markCutEdgesByState().

◆ cutMeshWithEFA()

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

Definition at line 1113 of file XFEM.C.

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

Referenced by update().

◆ getCrackTipOrigin()

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

Definition at line 69 of file XFEM.C.

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

◆ getCrackTipOriginMap()

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

Definition at line 311 of file XFEM.h.

312 {
314 }

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

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

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

2304{
2305 if (!parent_elem)
2306 parent_elem = cut_elem;
2307 // Pick any node from the parent element that is inside the physical domain and return its
2308 // CutSubdomainID.
2309 const Node * node = pickFirstPhysicalNode(cut_elem, parent_elem);
2310 return gcuo->getCutSubdomainID(node);
2311}
virtual CutSubdomainID getCutSubdomainID(const Node *) const
Get CutSubdomainID telling which side the node belongs to relative to the cut.
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:2314

Referenced by cutMeshWithEFA().

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

1759{
1760 EFAElement * EFAelem = _efa_mesh.getElemByID(elem->id());
1761 EFAElement2D * EFAelem2D = dynamic_cast<EFAElement2D *>(EFAelem);
1762
1763 if (!EFAelem2D)
1764 mooseError("EFAelem is not of EFAelement2D type");
1765
1766 return EFAelem2D;
1767}

Referenced by markCutEdgesByGeometry(), and markCutEdgesByState().

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

1771{
1772 EFAElement * EFAelem = _efa_mesh.getElemByID(elem->id());
1773 EFAElement3D * EFAelem3D = dynamic_cast<EFAElement3D *>(EFAelem);
1774
1775 if (!EFAelem3D)
1776 mooseError("EFAelem is not of EFAelement3D type");
1777
1778 return EFAelem3D;
1779}

Referenced by markCutFacesByGeometry().

◆ getEFANodeCoords()

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

Definition at line 1608 of file XFEM.C.

1612{
1613 Point node_coor(0.0, 0.0, 0.0);
1614 std::vector<EFANode *> master_nodes;
1615 std::vector<Point> master_points;
1616 std::vector<double> master_weights;
1617
1618 CEMElem->getMasterInfo(CEMnode, master_nodes, master_weights);
1619 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1620 {
1621 if (master_nodes[i]->category() == EFANode::N_CATEGORY_PERMANENT)
1622 {
1623 unsigned int local_node_id = CEMElem->getLocalNodeIndex(master_nodes[i]);
1624 const Node * node = elem->node_ptr(local_node_id);
1625 if (displaced_mesh)
1626 node = displaced_mesh->node_ptr(node->id());
1627 Point node_p((*node)(0), (*node)(1), (*node)(2));
1628 master_points.push_back(node_p);
1629 }
1630 else
1631 mooseError("master nodes must be permanent");
1632 }
1633 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1634 node_coor += master_weights[i] * master_points[i];
1635
1636 return node_coor;
1637}
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
@ N_CATEGORY_PERMANENT
Definition EFANode.h:19

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

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

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

Referenced by setSolution(), and storeSolutionForElement().

◆ getFragmentEdges()

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

Definition at line 1782 of file XFEM.C.

1785{
1786 // N.B. CEMElem here has global EFAnode
1787 frag_edges.clear();
1788 if (CEMElem->numFragments() > 0)
1789 {
1790 if (CEMElem->numFragments() > 1)
1791 mooseError("element ", elem->id(), " has more than one fragment at this point");
1792 for (unsigned int i = 0; i < CEMElem->getFragment(0)->numEdges(); ++i)
1793 {
1794 std::vector<Point> p_line(2, Point(0.0, 0.0, 0.0));
1795 p_line[0] = getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(0), CEMElem, elem);
1796 p_line[1] = getEFANodeCoords(CEMElem->getFragmentEdge(0, i)->getNode(1), CEMElem, elem);
1797 frag_edges.push_back(p_line);
1798 }
1799 }
1800}
virtual unsigned int numFragments() const
EFAFragment2D * getFragment(unsigned int frag_id) const
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const

◆ getFragmentFaces() [1/2]

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

Definition at line 1803 of file XFEM.C.

1806{
1807 // N.B. CEMElem here has global EFAnode
1808 frag_faces.clear();
1809 if (CEMElem->numFragments() > 0)
1810 {
1811 if (CEMElem->numFragments() > 1)
1812 mooseError("element ", elem->id(), " has more than one fragment at this point");
1813 for (unsigned int i = 0; i < CEMElem->getFragment(0)->numFaces(); ++i)
1814 {
1815 unsigned int num_face_nodes = CEMElem->getFragmentFace(0, i)->numNodes();
1816 std::vector<Point> p_line(num_face_nodes, Point(0.0, 0.0, 0.0));
1817 for (unsigned int j = 0; j < num_face_nodes; ++j)
1818 p_line[j] = getEFANodeCoords(CEMElem->getFragmentFace(0, i)->getNode(j), CEMElem, elem);
1819 frag_faces.push_back(p_line);
1820 }
1821 }
1822}
EFAFace * getFragmentFace(unsigned int frag_id, unsigned int face_id) const
virtual unsigned int numFragments() const
EFAFragment3D * getFragment(unsigned int frag_id) const
unsigned int numNodes() const
Definition EFAFace.C:87
EFANode * getNode(unsigned int node_id) const
Definition EFAFace.C:99

◆ getFragmentFaces() [2/2]

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

Definition at line 1741 of file XFEM.C.

1744{
1745 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1746 it = _cut_elem_map.find(elem->unique_id());
1747 if (it != _cut_elem_map.end())
1748 {
1749 const XFEMCutElem * xfce = it->second;
1750 if (displaced_mesh)
1751 xfce->getFragmentFaces(frag_faces, _displaced_mesh);
1752 else
1753 xfce->getFragmentFaces(frag_faces);
1754 }
1755}
virtual void getFragmentFaces(std::vector< std::vector< Point > > &frag_faces, MeshBase *displaced_mesh=nullptr) const =0

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

2186{
2187 for (auto gcmit : _geom_marker_id_elems)
2188 {
2189 std::set<unsigned int> elems = gcmit.second;
2190 if (elems.find(elem->id()) != elems.end())
2191 return _geometric_cuts[gcmit.first];
2192 }
2193 return nullptr;
2194}

Referenced by cutMeshWithEFA().

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

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

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

Referenced by setSolution(), and storeSolutionForNode().

◆ getPhysicalVolumeFraction()

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

Get the volume fraction of an element that is physical.

Definition at line 1640 of file XFEM.C.

1641{
1642 Real phys_volfrac = 1.0;
1643 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1644 it = _cut_elem_map.find(elem->unique_id());
1645 if (it != _cut_elem_map.end())
1646 {
1647 XFEMCutElem * xfce = it->second;
1648 const EFAElement * EFAelem = xfce->getEFAElement();
1649 if (EFAelem->isPartial())
1650 { // exclude the full crack tip elements
1652 phys_volfrac = xfce->getPhysicalVolumeFraction();
1653 }
1654 }
1655
1656 return phys_volfrac;
1657}
Real getPhysicalVolumeFraction() const
Returns the volume fraction of the element fragment.
Definition XFEMCutElem.C:51
virtual void computePhysicalVolumeFraction()=0
Computes the volume fraction of the element fragment.

Referenced by markCutEdgesByState().

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

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

◆ getXFEMFaceWeights()

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

Definition at line 1890 of file XFEM.C.

1895{
1896 bool have_weights = false;
1897 XFEMCutElem * xfce = nullptr;
1898 if (isElemCut(elem, xfce))
1899 {
1900 mooseAssert(xfce != nullptr, "Must have valid XFEMCutElem object here");
1901 xfce->getFaceWeightMultipliers(weights, qrule, getXFEMQRule(), q_points, side);
1902 have_weights = true;
1903 }
1904 return have_weights;
1905}
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
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
Definition XFEM.C:1718
Xfem::XFEM_QRULE & getXFEMQRule()
Definition XFEM.C:1825

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

1913{
1914 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1915 it = _cut_elem_map.find(elem->unique_id());
1916 if (it != _cut_elem_map.end())
1917 {
1918 const XFEMCutElem * xfce = it->second;
1919 if (displaced_mesh)
1920 xfce->getIntersectionInfo(plane_id, normal, intersectionPoints, _displaced_mesh);
1921 else
1922 xfce->getIntersectionInfo(plane_id, normal, intersectionPoints);
1923 }
1924}
virtual void getIntersectionInfo(unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, MeshBase *displaced_mesh=nullptr) const =0

◆ getXFEMQRule()

Xfem::XFEM_QRULE & XFEM::getXFEMQRule ( )

Definition at line 1825 of file XFEM.C.

1826{
1827 return _XFEM_qrule;
1828}
Xfem::XFEM_QRULE _XFEM_qrule
Definition XFEM.h:329

Referenced by getXFEMFaceWeights(), and getXFEMWeights().

◆ getXFEMqRuleOnLine()

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

Definition at line 1927 of file XFEM.C.

1930{
1931 Point p1 = intersection_points[0];
1932 Point p2 = intersection_points[1];
1933
1934 // number of quadrature points
1935 std::size_t num_qpoints = 2;
1936
1937 // quadrature coordinates
1938 Real xi0 = -std::sqrt(1.0 / 3.0);
1939 Real xi1 = std::sqrt(1.0 / 3.0);
1940
1941 quad_wts.resize(num_qpoints);
1942 quad_pts.resize(num_qpoints);
1943
1944 Real integ_jacobian = pow((p1 - p2).norm_sq(), 0.5) * 0.5;
1945
1946 quad_wts[0] = 1.0 * integ_jacobian;
1947 quad_wts[1] = 1.0 * integ_jacobian;
1948
1949 quad_pts[0] = (1.0 - xi0) / 2.0 * p1 + (1.0 + xi0) / 2.0 * p2;
1950 quad_pts[1] = (1.0 - xi1) / 2.0 * p1 + (1.0 + xi1) / 2.0 * p2;
1951}
auto norm_sq(const T &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 1954 of file XFEM.C.

1957{
1958 std::size_t nnd_pe = intersection_points.size();
1959 Point xcrd(0.0, 0.0, 0.0);
1960 for (std::size_t i = 0; i < nnd_pe; ++i)
1961 xcrd += intersection_points[i];
1962 xcrd /= nnd_pe;
1963
1964 quad_pts.resize(nnd_pe);
1965 quad_wts.resize(nnd_pe);
1966
1967 Real jac = 0.0;
1968
1969 for (std::size_t j = 0; j < nnd_pe; ++j) // loop all sub-tris
1970 {
1971 std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
1972 std::vector<Point> subtrig_points(3, Point(0.0, 0.0, 0.0)); // sub-trig nodal coords
1973
1974 int jplus1 = j < nnd_pe - 1 ? j + 1 : 0;
1975 subtrig_points[0] = xcrd;
1976 subtrig_points[1] = intersection_points[j];
1977 subtrig_points[2] = intersection_points[jplus1];
1978
1979 std::vector<std::vector<Real>> sg2;
1980 Xfem::stdQuadr2D(3, 1, sg2); // get sg2
1981 for (std::size_t l = 0; l < sg2.size(); ++l) // loop all int pts on a sub-trig
1982 {
1983 Xfem::shapeFunc2D(3, sg2[l], subtrig_points, shape, jac, true); // Get shape
1984 std::vector<Real> tsg_line(3, 0.0);
1985 for (std::size_t k = 0; k < 3; ++k) // loop sub-trig nodes
1986 {
1987 tsg_line[0] += shape[k][2] * subtrig_points[k](0);
1988 tsg_line[1] += shape[k][2] * subtrig_points[k](1);
1989 tsg_line[2] += shape[k][2] * subtrig_points[k](2);
1990 }
1991 quad_pts[j + l] = Point(tsg_line[0], tsg_line[1], tsg_line[2]);
1992 quad_wts[j + l] = sg2[l][3] * jac;
1993 }
1994 }
1995}
void stdQuadr2D(unsigned int nen, unsigned int iord, std::vector< std::vector< Real > > &sg2)
Definition XFEMFuncs.C:94
void shapeFunc2D(unsigned int nen, std::vector< Real > &ss, std::vector< Point > &xl, std::vector< std::vector< Real > > &shp, Real &xsj, bool natl_flg)

◆ getXFEMWeights()

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

Definition at line 1861 of file XFEM.C.

1865{
1866 bool have_weights = false;
1867 XFEMCutElem * xfce = nullptr;
1868 if (isElemCut(elem, xfce))
1869 {
1870 mooseAssert(xfce != nullptr, "Must have valid XFEMCutElem object here");
1871 xfce->getWeightMultipliers(weights, qrule, getXFEMQRule(), q_points);
1872 have_weights = true;
1873
1874 Real ave_weight_multiplier = 0;
1875 for (unsigned int i = 0; i < weights.size(); ++i)
1876 ave_weight_multiplier += weights[i];
1877 ave_weight_multiplier /= weights.size();
1878
1879 if (ave_weight_multiplier < _min_weight_multiplier)
1880 {
1881 const Real amount_to_add = _min_weight_multiplier - ave_weight_multiplier;
1882 for (unsigned int i = 0; i < weights.size(); ++i)
1883 weights[i] += amount_to_add;
1884 }
1885 }
1886 return have_weights;
1887}
unsigned int size() const
void getWeightMultipliers(MooseArray< Real > &weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points)
Definition XFEMCutElem.C:63

◆ has_secondary_cut()

bool XFEM::has_secondary_cut ( )
inline

Definition at line 290 of file XFEM.h.

290{ return _has_secondary_cut; }

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

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

Referenced by updateHeal().

◆ initCutIntersectionEdge()

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

Definition at line 910 of file XFEM.C.

912{
913 dist = 0.0;
914 bool does_intersect = false;
915 Point origin2p1 = edge_p1 - cut_origin;
916 Real plane2p1 = cut_normal(0) * origin2p1(0) + cut_normal(1) * origin2p1(1);
917 Point origin2p2 = edge_p2 - cut_origin;
918 Real plane2p2 = cut_normal(0) * origin2p2(0) + cut_normal(1) * origin2p2(1);
919
920 if (plane2p1 * plane2p2 < 0.0)
921 {
922 dist = -plane2p1 / (plane2p2 - plane2p1);
923 does_intersect = true;
924 }
925 return does_intersect;
926}

Referenced by correctCrackExtensionDirection(), and markCutEdgesByState().

◆ initSolution()

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

Implements XFEMInterface.

Definition at line 317 of file XFEM.C.

319{
320 if (nls.size() != 1)
321 mooseError("XFEM does not currently support multiple nonlinear systems");
322
323 nls[0]->serializeSolution();
324 aux.serializeSolution();
325 NumericVector<Number> & current_solution = *nls[0]->system().current_local_solution;
326 NumericVector<Number> & old_solution = nls[0]->solutionOld();
327 NumericVector<Number> & older_solution = nls[0]->solutionOlder();
328 NumericVector<Number> & current_aux_solution = *aux.system().current_local_solution;
329 NumericVector<Number> & old_aux_solution = aux.solutionOld();
330 NumericVector<Number> & older_aux_solution = aux.solutionOlder();
331
332 setSolution(*nls[0], _cached_solution, current_solution, old_solution, older_solution);
334 aux, _cached_aux_solution, current_aux_solution, old_aux_solution, older_aux_solution);
335
336 current_solution.close();
337 old_solution.close();
338 older_solution.close();
339 current_aux_solution.close();
340 old_aux_solution.close();
341 older_aux_solution.close();
342
343 _cached_solution.clear();
344 _cached_aux_solution.clear();
345}
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:2066

◆ isElemAtCrackTip()

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

Definition at line 1712 of file XFEM.C.

1713{
1714 return (_crack_tip_elems.find(elem) != _crack_tip_elems.end());
1715}

Referenced by markCutEdgesByGeometry(), and markCutEdgesByState().

◆ isElemCut() [1/2]

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

Definition at line 1734 of file XFEM.C.

1735{
1736 XFEMCutElem * xfce;
1737 return isElemCut(elem, xfce);
1738}

◆ isElemCut() [2/2]

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

Definition at line 1718 of file XFEM.C.

1719{
1720 const auto it = _cut_elem_map.find(elem->unique_id());
1721 if (it != _cut_elem_map.end())
1722 {
1723 xfce = it->second;
1724 const EFAElement * EFAelem = xfce->getEFAElement();
1725 if (EFAelem->isPartial()) // exclude the full crack tip elements
1726 return true;
1727 }
1728
1729 xfce = nullptr;
1730 return false;
1731}

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

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

1661{
1662 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1663 it = _cut_elem_map.find(elem->unique_id());
1664 if (it != _cut_elem_map.end())
1665 {
1666 XFEMCutElem * xfce = it->second;
1667
1668 if (xfce->isPointPhysical(point))
1669 return true;
1670 }
1671 else
1672 return true;
1673
1674 return false;
1675}

Referenced by pickFirstPhysicalNode().

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

2271{
2272 // Restore the element material properties
2273 mooseAssert(cached_cei.count(elem_from) > 0, "XFEM: Unable to find cached material properties.");
2274 Xfem::CutElemInfo & cei = cached_cei[elem_from];
2275
2276 // Load element material properties from cached properties
2279 _material_data[0]->getMaterialPropertyStorageForXFEM({}));
2280
2281 // Check if any of the element side need material properties
2282 bool need_boundary_materials = false;
2283 for (unsigned int side = 0; side < elem->n_sides(); ++side)
2284 {
2285 std::vector<boundary_id_type> elem_boundary_ids;
2286 _mesh->get_boundary_info().boundary_ids(elem, side, elem_boundary_ids);
2287 for (auto bdid : elem_boundary_ids)
2288 if (_fe_problem->needBoundaryMaterialOnSide(bdid, 0))
2289 need_boundary_materials = true;
2290 }
2291
2292 // Load boundary material properties from cached properties
2293 if (need_boundary_materials)
2295 elem,
2297 _bnd_material_data[0]->getMaterialPropertyStorageForXFEM({}));
2298}
void loadMaterialPropertiesForElementHelper(const Elem *elem, const Xfem::CachedMaterialProperties &cached_props, MaterialPropertyStorage &storage) const
Load the material properties.
Definition XFEM.C:2243
CachedMaterialProperties _elem_material_properties
Definition XFEM.h:62
CachedMaterialProperties _bnd_material_properties
Definition XFEM.h:63

Referenced by cutMeshWithEFA(), and healMesh().

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

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

Referenced by loadMaterialPropertiesForElement().

◆ markCutEdgesByGeometry()

bool XFEM::markCutEdgesByGeometry ( )

Definition at line 404 of file XFEM.C.

405{
406 bool marked_edges = false;
407 bool marked_nodes = false;
408
409 for (const auto & gme : _geom_marked_elems_2d)
410 {
411 for (const auto & gmei : gme.second)
412 {
413 EFAElement2D * EFAElem = getEFAElem2D(gme.first);
414
415 for (unsigned int i = 0; i < gmei._elem_cut_edges.size(); ++i) // mark element edges
416 {
417 if (!EFAElem->isEdgePhantom(
418 gmei._elem_cut_edges[i]._host_side_id)) // must not be phantom edge
419 {
420 _efa_mesh.addElemEdgeIntersection(gme.first->id(),
421 gmei._elem_cut_edges[i]._host_side_id,
422 gmei._elem_cut_edges[i]._distance);
423 marked_edges = true;
424 }
425 }
426
427 for (unsigned int i = 0; i < gmei._elem_cut_nodes.size(); ++i) // mark element edges
428 {
429 _efa_mesh.addElemNodeIntersection(gme.first->id(), gmei._elem_cut_nodes[i]._host_id);
430 marked_nodes = true;
431 }
432
433 for (unsigned int i = 0; i < gmei._frag_cut_edges.size();
434 ++i) // MUST DO THIS AFTER MARKING ELEMENT EDGES
435 {
436 if (!EFAElem->getFragment(0)->isSecondaryInteriorEdge(
437 gmei._frag_cut_edges[i]._host_side_id))
438 {
439 if (_efa_mesh.addFragEdgeIntersection(gme.first->id(),
440 gmei._frag_cut_edges[i]._host_side_id,
441 gmei._frag_cut_edges[i]._distance))
442 {
443 marked_edges = true;
444 if (!isElemAtCrackTip(gme.first))
445 _has_secondary_cut = true;
446 }
447 }
448 }
449 }
450 }
451
452 return marked_edges || marked_nodes;
453}
bool isSecondaryInteriorEdge(unsigned int edge_id) const
void addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
EFAElement2D * getEFAElem2D(const Elem *elem)
Get the EFAElement2D object for a specified libMesh element.
Definition XFEM.C:1758
bool isElemAtCrackTip(const Elem *elem) const
Definition XFEM.C:1712

Referenced by markCuts().

◆ markCutEdgesByState()

bool XFEM::markCutEdgesByState ( Real  time)

Definition at line 597 of file XFEM.C.

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

Referenced by markCuts().

◆ markCutFacesByGeometry()

bool XFEM::markCutFacesByGeometry ( )

Definition at line 861 of file XFEM.C.

862{
863 bool marked_faces = false;
864
865 for (const auto & gme : _geom_marked_elems_3d)
866 {
867 for (const auto & gmei : gme.second)
868 {
869 EFAElement3D * EFAElem = getEFAElem3D(gme.first);
870
871 for (unsigned int i = 0; i < gmei._elem_cut_faces.size(); ++i) // mark element faces
872 {
873 if (!EFAElem->isFacePhantom(gmei._elem_cut_faces[i]._face_id)) // must not be phantom face
874 {
875 _efa_mesh.addElemFaceIntersection(gme.first->id(),
876 gmei._elem_cut_faces[i]._face_id,
877 gmei._elem_cut_faces[i]._face_edge,
878 gmei._elem_cut_faces[i]._position);
879 marked_faces = true;
880 }
881 }
882
883 for (unsigned int i = 0; i < gmei._frag_cut_faces.size();
884 ++i) // MUST DO THIS AFTER MARKING ELEMENT EDGES
885 {
886 if (!EFAElem->getFragment(0)->isThirdInteriorFace(gmei._frag_cut_faces[i]._face_id))
887 {
888 _efa_mesh.addFragFaceIntersection(gme.first->id(),
889 gmei._frag_cut_faces[i]._face_id,
890 gmei._frag_cut_faces[i]._face_edge,
891 gmei._frag_cut_faces[i]._position);
892 marked_faces = true;
893 }
894 }
895 }
896 }
897
898 return marked_faces;
899}
bool isFacePhantom(unsigned int face_id) const
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)
void addElemFaceIntersection(unsigned int elemid, unsigned int faceid, const std::vector< unsigned int > &edgeid, const std::vector< double > &position)
EFAElement3D * getEFAElem3D(const Elem *elem)
Get the EFAElement3D object for a specified libMesh element.
Definition XFEM.C:1770

Referenced by markCuts().

◆ markCutFacesByState()

bool XFEM::markCutFacesByState ( )

Definition at line 902 of file XFEM.C.

903{
904 bool marked_faces = false;
905 // TODO: need to finish this for 3D problems
906 return marked_faces;
907}

Referenced by markCuts().

◆ markCuts()

bool XFEM::markCuts ( Real  time)

Definition at line 387 of file XFEM.C.

388{
389 bool marked_sides = false;
390 if (_mesh->mesh_dimension() == 2)
391 {
392 marked_sides = markCutEdgesByGeometry();
393 marked_sides |= markCutEdgesByState(time);
394 }
395 else if (_mesh->mesh_dimension() == 3)
396 {
397 marked_sides = markCutFacesByGeometry();
398 marked_sides |= markCutFacesByState();
399 }
400 return marked_sides;
401}
bool markCutFacesByState()
Definition XFEM.C:902
bool markCutFacesByGeometry()
Definition XFEM.C:861
bool markCutEdgesByGeometry()
Definition XFEM.C:404
bool markCutEdgesByState(Real time)
Definition XFEM.C:597

Referenced by update().

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

2315{
2316 for (auto i : e0->node_index_range())
2317 if (isPointInsidePhysicalDomain(e, e0->node_ref(i)))
2318 return e0->node_ptr(i);
2319 mooseError("cannot find a physical node in the current element");
2320 return nullptr;
2321}
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:1660

Referenced by getCutSubdomainID().

◆ setCrackGrowthMethod()

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

Definition at line 1842 of file XFEM.C.

1843{
1844 _use_crack_growth_increment = use_crack_growth_increment;
1845 _crack_growth_increment = crack_growth_increment;
1846}

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

1850{
1851 _debug_output_level = debug_output_level;
1852}

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

1856{
1857 _min_weight_multiplier = min_weight_multiplier;
1858}

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

2071{
2072 for (auto & node : _mesh->local_node_ptr_range())
2073 {
2074 auto mit = stored_solution.find(node->unique_id());
2075 if (mit != stored_solution.end())
2076 {
2077 const std::vector<Real> & stored_node_solution = mit->second;
2078 std::vector<dof_id_type> stored_solution_dofs = getNodeSolutionDofs(node, sys);
2079 setSolutionForDOFs(stored_node_solution,
2080 stored_solution_dofs,
2081 current_solution,
2082 old_solution,
2083 older_solution);
2084 }
2085 }
2086
2087 for (auto & elem : as_range(_mesh->local_elements_begin(), _mesh->local_elements_end()))
2088 {
2089 auto mit = stored_solution.find(elem->unique_id());
2090 if (mit != stored_solution.end())
2091 {
2092 const std::vector<Real> & stored_elem_solution = mit->second;
2093 std::vector<dof_id_type> stored_solution_dofs = getElementSolutionDofs(elem, sys);
2094 setSolutionForDOFs(stored_elem_solution,
2095 stored_solution_dofs,
2096 current_solution,
2097 old_solution,
2098 older_solution);
2099 }
2100 }
2101}
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:2104
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:2153
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:2127
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)

Referenced by initSolution().

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

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

Referenced by setSolution().

◆ setXFEMQRule()

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

Definition at line 1831 of file XFEM.C.

1832{
1833 if (xfem_qrule == "volfrac")
1835 else if (xfem_qrule == "moment_fitting")
1837 else if (xfem_qrule == "direct")
1839}
@ DIRECT
Definition XFEM.h:41
@ VOLFRAC
Definition XFEM.h:39
@ MOMENT_FITTING
Definition XFEM.h:40

◆ storeCrackTipOriginAndDirection()

void XFEM::storeCrackTipOriginAndDirection ( )

Definition at line 189 of file XFEM.C.

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

Referenced by update().

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

2216{
2217 // Set the parent element so that it is consistent post-healing
2218 _geom_cut_elems[child_elem]._parent_elem = parent_elem;
2219
2220 // Locally store the element material properties
2222 _material_data[0]->getMaterialPropertyStorageForXFEM({}));
2223
2224 // Locally store the boundary material properties
2225 // First check if any of the side need material properties
2226 bool need_boundary_materials = false;
2227 for (unsigned int side = 0; side < child_elem->n_sides(); ++side)
2228 {
2229 std::vector<boundary_id_type> elem_boundary_ids;
2230 _mesh->get_boundary_info().boundary_ids(child_elem, side, elem_boundary_ids);
2231 for (auto bdid : elem_boundary_ids)
2232 if (_fe_problem->needBoundaryMaterialOnSide(bdid, 0))
2233 need_boundary_materials = true;
2234 }
2235
2236 // If boundary material properties are needed for this element, then store them.
2237 if (need_boundary_materials)
2239 child_elem, _bnd_material_data[0]->getMaterialPropertyStorageForXFEM({}));
2240}
void storeMaterialPropertiesForElementHelper(const Elem *elem, MaterialPropertyStorage &storage)
Definition XFEM.C:2197

Referenced by healMesh().

◆ storeMaterialPropertiesForElementHelper()

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

Definition at line 2197 of file XFEM.C.

2198{
2199 for (const auto state : storage.statefulIndexRange())
2200 {
2201 const auto & elem_props = storage.props(state).at(elem);
2202 auto & serialized_props = _geom_cut_elems[elem]._elem_material_properties[state - 1];
2203 serialized_props.clear();
2204 for (const auto & side_props_pair : elem_props)
2205 {
2206 const auto side = side_props_pair.first;
2207 std::ostringstream oss;
2208 dataStore(oss, storage.setProps(elem, side, state), nullptr);
2209 serialized_props[side].assign(oss.str());
2210 }
2211 }
2212}
void dataStore(std::ostream &stream, LineSegment &l, void *context)
const PropsType & props(const unsigned int state=0) const

Referenced by storeMaterialPropertiesForElement().

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

2039{
2040 std::vector<dof_id_type> stored_solution_dofs = getElementSolutionDofs(elem_to_store_from, sys);
2041 std::vector<Real> stored_solution_scratch;
2042 // Size for current solution, as well as for old, and older solution only for transient case
2043 std::size_t stored_solution_size =
2044 (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
2045 stored_solution_scratch.reserve(stored_solution_size);
2046
2047 // Store in the order defined in stored_solution_dofs first for the current, then for old and
2048 // older if applicable
2049 for (auto dof : stored_solution_dofs)
2050 stored_solution_scratch.push_back(current_solution(dof));
2051
2052 if (_fe_problem->isTransient())
2053 {
2054 for (auto dof : stored_solution_dofs)
2055 stored_solution_scratch.push_back(old_solution(dof));
2056
2057 for (auto dof : stored_solution_dofs)
2058 stored_solution_scratch.push_back(older_solution(dof));
2059 }
2060
2061 if (stored_solution_scratch.size() > 0)
2062 stored_solution[elem_to_store_to->unique_id()] = stored_solution_scratch;
2063}

Referenced by cutMeshWithEFA().

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

2005{
2006 std::vector<dof_id_type> stored_solution_dofs = getNodeSolutionDofs(node_to_store_from, sys);
2007 std::vector<Real> stored_solution_scratch;
2008 // Size for current solution, as well as for old, and older solution only for transient case
2009 std::size_t stored_solution_size =
2010 (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
2011 stored_solution_scratch.reserve(stored_solution_size);
2012
2013 // Store in the order defined in stored_solution_dofs first for the current, then for old and
2014 // older if applicable
2015 for (auto dof : stored_solution_dofs)
2016 stored_solution_scratch.push_back(current_solution(dof));
2017
2018 if (_fe_problem->isTransient())
2019 {
2020 for (auto dof : stored_solution_dofs)
2021 stored_solution_scratch.push_back(old_solution(dof));
2022
2023 for (auto dof : stored_solution_dofs)
2024 stored_solution_scratch.push_back(older_solution(dof));
2025 }
2026
2027 if (stored_solution_scratch.size() > 0)
2028 stored_solution[node_to_store_to->unique_id()] = stored_solution_scratch;
2029}

Referenced by cutMeshWithEFA().

◆ update()

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

Implements XFEMInterface.

Definition at line 265 of file XFEM.C.

268{
270 mooseError("Use of XFEM with distributed mesh is not yet supported");
271
272 for (const auto & elem : _mesh->active_element_ptr_range())
273 if (elem->level() > 0)
274 mooseError("XFEM does not currently support mesh adaptivity or adaptively refined meshes");
275
276 bool mesh_changed = false;
277
280
281 buildEFAMesh();
282
284
286
287 if (markCuts(time))
288 mesh_changed = cutMeshWithEFA(nl, aux);
289
290 if (mesh_changed)
291 {
292 buildEFAMesh();
294 }
295
296 if (mesh_changed)
297 {
298 _mesh->allow_renumbering(false);
299 _mesh->skip_partitioning(true);
300 _mesh->prepare_for_use();
301
302 if (_displaced_mesh)
303 {
304 _displaced_mesh->allow_renumbering(false);
305 _displaced_mesh->skip_partitioning(true);
306 _displaced_mesh->prepare_for_use();
307 }
308 }
309
312
313 return mesh_changed;
314}
const ExecFlagType EXEC_XFEM_MARK
Exec flag used to execute MooseObjects while elements are being marked for cutting by XFEM.
virtual void execute(const ExecFlagType &exec_type)
virtual bool isDistributedMesh() const
void storeCrackTipOriginAndDirection()
Definition XFEM.C:189
bool cutMeshWithEFA(const std::vector< std::shared_ptr< NonlinearSystemBase > > &nl, AuxiliarySystem &aux)
Definition XFEM.C:1113
bool markCuts(Real time)
Definition XFEM.C:387
void clearGeomMarkedElems()
Clear out the list of elements to be marked for cutting.
Definition XFEM.C:182
void buildEFAMesh()
Definition XFEM.C:348
void clearStateMarkedElems()
Definition XFEM.C:154

◆ updateHeal()

bool XFEM::updateHeal ( )
overridevirtual

Implements XFEMInterface.

Definition at line 228 of file XFEM.C.

229{
230 bool mesh_changed = false;
231
232 mesh_changed = healMesh();
233
234 if (mesh_changed)
235 buildEFAMesh();
236
237 if (mesh_changed)
238 {
239 _mesh->update_parallel_id_counts();
242 // _mesh->find_neighbors();
243 // _mesh->contract();
244 _mesh->allow_renumbering(false);
245 _mesh->skip_partitioning(true);
246 _mesh->prepare_for_use();
247
248 if (_displaced_mesh)
249 {
250 _displaced_mesh->update_parallel_id_counts();
253 _displaced_mesh->allow_renumbering(false);
254 _displaced_mesh->skip_partitioning(true);
255 _displaced_mesh->prepare_for_use();
256 }
257 }
258
259 _geom_marker_id_elems.clear();
260
261 return mesh_changed;
262}
bool healMesh()
Potentially heal the mesh by merging some of the pairs of partial elements cut by XFEM back into sing...
Definition XFEM.C:929
void make_elems_parallel_consistent(MeshBase &)
void make_nodes_parallel_consistent(MeshBase &)

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 396 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 387 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 374 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 402 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 356 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 359 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 362 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 365 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 378 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 408 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(), markCutEdgesByState(), and update().

◆ _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().

◆ _state_marked_t_step

int XFEM::_state_marked_t_step
private

The timestep index at which the state marks were added.

Marks added at the end of a timestep are meant for the next one, so marks from the current timestep can only come from an attempt that was later rejected (e.g. by –test-restep) and must not cut the mesh.

Definition at line 353 of file XFEM.h.

Referenced by addStateMarkedElem(), and update().

◆ _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: