17 #include "libmesh/edge_edge2.h" 18 #include "libmesh/serial_mesh.h" 19 #include "libmesh/mesh_tools.h" 25 params.
addParam<UserObjectName>(
"nucleate_uo",
"The MeshCutNucleation UO for nucleating cracks.");
26 params.
addParam<UserObjectName>(
"crack_front_definition",
27 "crackFrontDefinition",
28 "The CrackFrontDefinition user object name");
29 params.
addClassDescription(
"Creates a UserObject base class for a mesh cutter in 2D problems");
35 _mesh(_subproblem.
mesh()),
36 _nucleate_uo(isParamValid(
"nucleate_uo")
39 _is_mesh_modified(false)
41 _depend_uo.insert(getParam<UserObjectName>(
"crack_front_definition"));
44 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
46 if (cut_elem->n_nodes() != 2)
47 mooseError(
"The input cut mesh should include EDGE2 elements only!");
48 if (cut_elem->dim() != 1)
49 mooseError(
"The input cut mesh should have 1D elements (in a 2D space) only!");
59 const auto uo_name = getParam<UserObjectName>(
"crack_front_definition");
65 std::vector<Xfem::CutEdge> & cut_edges,
66 std::vector<Xfem::CutNode> & cut_nodes)
const 70 mooseAssert(elem->dim() == 2,
"Dimension of element to be cut must be 2");
72 bool elem_cut =
false;
74 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
76 unsigned int n_sides = elem->n_sides();
78 for (
unsigned int i = 0; i < n_sides; ++i)
80 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
82 mooseAssert(curr_side->type() ==
EDGE2,
"Element side type must be EDGE2.");
84 const Node * node1 = curr_side->node_ptr(0);
85 const Node * node2 = curr_side->node_ptr(1);
86 Real seg_int_frac = 0.0;
88 const std::pair<Point, Point> elem_endpoints(cut_elem->node_ref(0), cut_elem->node_ref(1));
96 mycut.
_id1 = node1->id();
97 mycut.
_id2 = node2->id();
100 cut_edges.push_back(mycut);
106 mycut.
_id = node1->id();
108 cut_nodes.push_back(mycut);
118 std::vector<Xfem::CutFace> & )
const 120 mooseError(
"Invalid method for 2D mesh cutting.");
126 std::vector<Xfem::CutEdge> & cut_edges)
const 128 bool cut_frag =
false;
130 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
132 const std::pair<Point, Point> elem_endpoints(cut_elem->node_ref(0), cut_elem->node_ref(1));
133 unsigned int n_sides = frag_edges.size();
134 for (
unsigned int i = 0; i < n_sides; ++i)
136 Real seg_int_frac = 0.0;
138 frag_edges[i][0], frag_edges[i][1], elem_endpoints, 1, seg_int_frac))
143 mycut.
_id2 = (i < (n_sides - 1) ? (i + 1) : 0);
146 cut_edges.push_back(mycut);
155 std::vector<Xfem::CutFace> & )
const 157 mooseError(
"Invalid method for 2D mesh fragment cutting.");
161 const std::vector<Point>
164 std::vector<Point> crack_front_points(number_crack_front_points);
168 mooseError(
"MeshCut2DFractureUserObject::getCrackFrontPoints: number_crack_front_points=" +
170 " does not match the number of nodes given in " 171 "_original_and_current_front_node_ids=" +
174 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
178 mooseAssert(this_node,
"Node is NULL");
179 Point & this_point = *this_node;
180 crack_front_points[i] = this_point;
182 return crack_front_points;
185 const std::vector<RealVectorValue>
189 mooseError(
"MeshCut2DFractureUserObject::getCrackPlaneNormals: number_crack_front_points=" +
191 " does not match the number of nodes given in " 192 "_original_and_current_front_node_ids=" +
194 ". This will happen if a crack front exits the boundary because the number of " 195 "points in the CrackFrontDefinition is never updated.");
197 std::vector<std::pair<dof_id_type, RealVectorValue>> crack_plane_normals;
198 for (
const auto & elem :
_cutter_mesh->element_ptr_range())
206 [&id0](
const std::pair<dof_id_type, dof_id_type> & element)
207 {
return element.second == id0; });
210 [&id1](
const std::pair<dof_id_type, dof_id_type> & element)
211 {
return element.second == id1; });
220 Point end_pt, connecting_pt;
222 end_pt = elem->node_ref(0);
223 connecting_pt = elem->node_ref(1);
226 Point fracture_dir = end_pt - connecting_pt;
231 normal_dir /= normal_dir.
norm();
232 crack_plane_normals.push_back(std::make_pair(
id, normal_dir));
237 Point end_pt, connecting_pt;
239 end_pt = elem->node_ref(1);
240 connecting_pt = elem->node_ref(0);
243 Point fracture_dir = end_pt - connecting_pt;
248 normal_dir /= normal_dir.
norm();
249 crack_plane_normals.push_back(std::make_pair(
id, normal_dir));
254 "Boundary nodes are attached to more than one element. This should not happen for a 1D " 256 "\n Number of _original_and_current_front_node_ids=" +
258 "\n Number of crack_plane_normals=" +
Moose::stringify(crack_plane_normals.size()));
261 std::sort(crack_plane_normals.begin(), crack_plane_normals.end());
262 std::vector<RealVectorValue> sorted_crack_plane_normals;
263 for (
auto & crack : crack_plane_normals)
264 sorted_crack_plane_normals.push_back(crack.second);
266 return sorted_crack_plane_normals;
273 pl->enable_out_of_mesh_mode();
274 std::unordered_set boundary_nodes = MeshTools::find_boundary_nodes(*
_cutter_mesh);
275 for (
const auto & node : boundary_nodes)
279 mooseAssert(this_node,
"Node is NULL");
280 Point & this_point = *this_node;
282 const Elem * elem = (*pl)(this_point);
298 auto direction_iter =
301 [¤t_front_node_id](
const std::pair<dof_id_type, Point> & element)
302 {
return element.first == current_front_node_id; });
306 Node * this_node =
_cutter_mesh->node_ptr(current_front_node_id);
307 mooseAssert(this_node,
"Node is NULL");
308 Point & this_point = *this_node;
310 Point new_node_offset = direction_iter->second;
311 Point
x = this_point + new_node_offset;
324 this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
329 std::vector<dof_id_type> elem;
330 elem.push_back(current_front_node_id);
331 elem.push_back(new_front_node_id);
332 Elem * new_elem = Elem::build(
EDGE2).release();
333 for (
unsigned int i = 0; i < new_elem->n_nodes(); ++i)
335 mooseAssert(
_cutter_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
353 std::map<unsigned int, std::pair<RealVectorValue, RealVectorValue>> nucleated_elems_map =
361 pl->enable_out_of_mesh_mode();
362 for (
const auto & elem_nodes : nucleated_elems_map)
364 std::pair<RealVectorValue, RealVectorValue> nodes = elem_nodes.second;
366 Node * node_0 = Node::build(nodes.first,
_cutter_mesh->n_nodes()).release();
369 Node * node_1 = Node::build(nodes.second,
_cutter_mesh->n_nodes()).release();
373 std::vector<dof_id_type> elem;
374 elem.push_back(node_id_0);
375 elem.push_back(node_id_1);
376 Elem * new_elem = Elem::build(
EDGE2).release();
377 for (
unsigned int i = 0; i < new_elem->n_nodes(); ++i)
379 mooseAssert(
_cutter_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
386 Point & point_0 = *node_0;
387 const Elem * crack_front_elem_0 = (*pl)(point_0);
388 if (crack_front_elem_0 != NULL)
391 Point & point_1 = *node_1;
392 const Elem * crack_front_elem_1 = (*pl)(point_1);
393 if (crack_front_elem_1 != NULL)
404 std::map<
unsigned int, std::pair<RealVectorValue, RealVectorValue>> & nucleated_elems_map,
405 const Real nucleationRadius)
408 for (
auto it1 = nucleated_elems_map.begin(); it1 != nucleated_elems_map.end(); ++it1)
410 std::pair<RealVectorValue, RealVectorValue> nodes = it1->second;
411 Point p2 = nodes.first;
412 Point p1 = nodes.second;
413 Point p = p1 + (p2 - p1) / 2;
414 for (
auto it2 = nucleated_elems_map.begin(); it2 != nucleated_elems_map.end();)
425 Point q = p1 + (p2 - p1) / 2;
427 if (pq.norm() <= nucleationRadius)
428 it2 = nucleated_elems_map.erase(it2);
437 std::map<
unsigned int, std::pair<RealVectorValue, RealVectorValue>> & nucleated_elems_map,
438 const Real nucleationRadius)
440 for (
auto it = nucleated_elems_map.begin(); it != nucleated_elems_map.end();)
442 std::pair<RealVectorValue, RealVectorValue> nodes = it->second;
443 Point p2 = nodes.first;
444 Point p1 = nodes.second;
445 Point p = p1 + (p2 - p1) / 2;
446 bool removeNucleatedElem =
false;
447 for (
const auto & cutter_elem :
450 const Node *
const * cutter_elem_nodes = cutter_elem->get_nodes();
451 Point m = *cutter_elem_nodes[1] - *cutter_elem_nodes[0];
452 Real t = m * (p - *cutter_elem_nodes[0]) / m.norm_sq();
453 Real d = std::numeric_limits<Real>::max();
456 Point
j = p - *cutter_elem_nodes[0];
461 Point
j = p - *cutter_elem_nodes[1];
466 Point
j = p - (*cutter_elem_nodes[0] + t * m);
469 if (
d <= nucleationRadius)
471 removeNucleatedElem =
true;
475 if (removeNucleatedElem)
476 it = nucleated_elems_map.erase(it);
Data structure defining a cut through a node.
auto norm() const -> decltype(std::norm(Real()))
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes) const override
T & getUserObject(const std::string &name, unsigned int tid=0) const
static InputParameters validParams()
void findOriginalCrackFrontNodes()
Find the original crack front nodes in the cutter mesh and use to populate _original_and_current_fron...
MeshCut2DUserObjectBase(const InputParameters ¶meters)
static InputParameters validParams()
unsigned int _host_id
Local ID of this node in the host element.
std::vector< std::pair< dof_id_type, dof_id_type > > _original_and_current_front_node_ids
This vector of pairs orders crack tips to make the order used in this class the same as those for the...
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point >> &frag_edges, std::vector< Xfem::CutEdge > &cut_edges) const override
Data structure defining a cut on an element edge.
Class used in fracture integrals to define geometric characteristics of the crack front...
Real getNucleationRadius() const
Provide getter to MeshCut2DUserObjectBase for member data set in input.
unsigned int _id1
ID of the first node on the edge.
const std::vector< double > x
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::string stringify(const T &t)
bool intersectSegmentWithCutLine(const Point &segment_point1, const Point &segment_point2, const std::pair< Point, Point > &cutting_line_points, const Real &cutting_line_fraction, Real &segment_intersection_fraction)
Determine whether a line segment is intersected by a cutting line, and compute the fraction along tha...
MooseMesh & _mesh
The FE solution mesh.
std::map< unsigned int, std::pair< RealVectorValue, RealVectorValue > > getNucleatedElemsMap() const
Provide getter to MeshCut2DUserObjectBase for a map of nucleated cracks.
void addNucleatedCracksToMesh()
Calls into MeshCutNucleation UO to add cracks.
const MeshCut2DNucleationBase * _nucleate_uo
2D UO for nucleating cracks
virtual void initialSetup() override final
std::set< std::string > _depend_uo
Real _distance
Fractional distance along the edge (from node 1 to 2) where the cut is located.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int _id2
ID of the second node on the edge.
FEProblemBase & _fe_problem
Simple base class for XFEM cutting objects that use a mesh to cut.
bool _is_mesh_modified
Indicator that shows if the cutting mesh is modified or not in this calculation step.
void mooseError(Args &&... args) const
unsigned int _host_side_id
Local ID of this side in the host element.
virtual const std::vector< Point > getCrackFrontPoints(unsigned int num_crack_front_points) const override
get a set of points along a crack front from a XFEM GeometricCutUserObject
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual std::unique_ptr< libMesh::PointLocatorBase > getPointLocator() const
void growFront()
grow the cutter mesh
void removeNucleatedCracksTooCloseToExistingCracks(std::map< unsigned int, std::pair< RealVectorValue, RealVectorValue >> &nucleated_elems_map, Real nucleationRadius)
Remove nucleated cracks that are too close to a pre-existing crack in the mesh.
std::unique_ptr< MeshBase > _cutter_mesh
The xfem cutter mesh.
void removeNucleatedCracksTooCloseToEachOther(std::map< unsigned int, std::pair< RealVectorValue, RealVectorValue >> &nucleated_elems_map, Real nucleationRadius)
Remove nucleated cracks that are too close too each other.
std::vector< std::pair< dof_id_type, Point > > _active_front_node_growth_vectors
contains the active node ids and their growth vectors
unsigned int _id
ID of the cut node.
virtual const std::vector< RealVectorValue > getCrackPlaneNormals(unsigned int num_crack_front_points) const override
get a set of normal vectors along a crack front from a XFEM GeometricCutUserObject CrackFrontDefiniti...
CrackFrontDefinition * _crack_front_definition
user object for communicating between solid_mechanics interaction integrals and xfem cutter mesh ...