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.");
167 const std::vector<Point>
170 std::vector<Point> crack_front_points(number_crack_front_points);
174 mooseError(
"Number of nodes in CrackFrontDefinition does not match the number of nodes in the " 175 "cutter_mesh.\nCrackFrontDefinition nodes = " +
179 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
183 mooseAssert(this_node,
"Node is NULL");
184 Point & this_point = *this_node;
185 crack_front_points[i] = this_point;
187 return crack_front_points;
190 const std::vector<RealVectorValue>
194 mooseError(
"MeshCut2DFractureUserObject::getCrackPlaneNormals: number_crack_front_points=" +
196 " does not match the number of nodes given in " 197 "_original_and_current_front_node_ids=" +
199 ". This will happen if a crack front exits the boundary because the number of " 200 "points in the CrackFrontDefinition is never updated.");
202 std::vector<std::pair<dof_id_type, RealVectorValue>> crack_plane_normals;
203 for (
const auto & elem :
_cutter_mesh->element_ptr_range())
211 [&id0](
const std::pair<dof_id_type, dof_id_type> & element)
212 {
return element.second == id0; });
215 [&id1](
const std::pair<dof_id_type, dof_id_type> & element)
216 {
return element.second == id1; });
225 Point end_pt, connecting_pt;
227 end_pt = elem->node_ref(0);
228 connecting_pt = elem->node_ref(1);
231 Point fracture_dir = end_pt - connecting_pt;
236 normal_dir /= normal_dir.
norm();
237 crack_plane_normals.push_back(std::make_pair(
id, normal_dir));
242 Point end_pt, connecting_pt;
244 end_pt = elem->node_ref(1);
245 connecting_pt = elem->node_ref(0);
248 Point fracture_dir = end_pt - connecting_pt;
253 normal_dir /= normal_dir.
norm();
254 crack_plane_normals.push_back(std::make_pair(
id, normal_dir));
259 "Boundary nodes are attached to more than one element. This should not happen for a 1D " 261 "\n Number of _original_and_current_front_node_ids=" +
263 "\n Number of crack_plane_normals=" +
Moose::stringify(crack_plane_normals.size()));
266 std::sort(crack_plane_normals.begin(), crack_plane_normals.end());
267 std::vector<RealVectorValue> sorted_crack_plane_normals;
268 for (
auto & crack : crack_plane_normals)
269 sorted_crack_plane_normals.push_back(crack.second);
271 return sorted_crack_plane_normals;
278 pl->enable_out_of_mesh_mode();
279 std::unordered_set boundary_nodes = MeshTools::find_boundary_nodes(*
_cutter_mesh);
280 for (
const auto & node : boundary_nodes)
284 mooseAssert(this_node,
"Node is NULL");
285 Point & this_point = *this_node;
287 const Elem * elem = (*pl)(this_point);
303 auto direction_iter =
306 [¤t_front_node_id](
const std::pair<dof_id_type, Point> & element)
307 {
return element.first == current_front_node_id; });
311 Node * this_node =
_cutter_mesh->node_ptr(current_front_node_id);
312 mooseAssert(this_node,
"Node is NULL");
313 Point & this_point = *this_node;
315 Point new_node_offset = direction_iter->second;
316 Point
x = this_point + new_node_offset;
329 this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
334 std::vector<dof_id_type> elem;
335 elem.push_back(current_front_node_id);
336 elem.push_back(new_front_node_id);
337 Elem * new_elem = Elem::build(
EDGE2).release();
338 for (
unsigned int i = 0; i < new_elem->n_nodes(); ++i)
340 mooseAssert(
_cutter_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
358 std::map<unsigned int, std::pair<RealVectorValue, RealVectorValue>> nucleated_elems_map =
366 pl->enable_out_of_mesh_mode();
367 for (
const auto & elem_nodes : nucleated_elems_map)
369 std::pair<RealVectorValue, RealVectorValue> nodes = elem_nodes.second;
371 Node * node_0 = Node::build(nodes.first,
_cutter_mesh->n_nodes()).release();
374 Node * node_1 = Node::build(nodes.second,
_cutter_mesh->n_nodes()).release();
378 std::vector<dof_id_type> elem;
379 elem.push_back(node_id_0);
380 elem.push_back(node_id_1);
381 Elem * new_elem = Elem::build(
EDGE2).release();
382 for (
unsigned int i = 0; i < new_elem->n_nodes(); ++i)
384 mooseAssert(
_cutter_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
391 Point & point_0 = *node_0;
392 const Elem * crack_front_elem_0 = (*pl)(point_0);
393 if (crack_front_elem_0 != NULL)
396 Point & point_1 = *node_1;
397 const Elem * crack_front_elem_1 = (*pl)(point_1);
398 if (crack_front_elem_1 != NULL)
409 std::map<
unsigned int, std::pair<RealVectorValue, RealVectorValue>> & nucleated_elems_map,
410 const Real nucleationRadius)
413 for (
auto it1 = nucleated_elems_map.begin(); it1 != nucleated_elems_map.end(); ++it1)
415 std::pair<RealVectorValue, RealVectorValue> nodes = it1->second;
416 Point p2 = nodes.first;
417 Point p1 = nodes.second;
418 Point
p = p1 + (p2 - p1) / 2;
419 for (
auto it2 = nucleated_elems_map.begin(); it2 != nucleated_elems_map.end();)
430 Point q = p1 + (p2 - p1) / 2;
432 if (pq.norm() <= nucleationRadius)
433 it2 = nucleated_elems_map.erase(it2);
442 std::map<
unsigned int, std::pair<RealVectorValue, RealVectorValue>> & nucleated_elems_map,
443 const Real nucleationRadius)
445 for (
auto it = nucleated_elems_map.begin(); it != nucleated_elems_map.end();)
447 std::pair<RealVectorValue, RealVectorValue> nodes = it->second;
448 Point p2 = nodes.first;
449 Point p1 = nodes.second;
450 Point
p = p1 + (p2 - p1) / 2;
451 bool removeNucleatedElem =
false;
452 for (
const auto & cutter_elem :
455 const Node *
const * cutter_elem_nodes = cutter_elem->get_nodes();
456 Point m = *cutter_elem_nodes[1] - *cutter_elem_nodes[0];
457 Real t = m * (
p - *cutter_elem_nodes[0]) / m.norm_sq();
458 Real d = std::numeric_limits<Real>::max();
461 Point
j =
p - *cutter_elem_nodes[0];
466 Point
j =
p - *cutter_elem_nodes[1];
471 Point
j =
p - (*cutter_elem_nodes[0] + t * m);
474 if (
d <= nucleationRadius)
476 removeNucleatedElem =
true;
480 if (removeNucleatedElem)
481 it = nucleated_elems_map.erase(it);
Data structure defining a cut through a node.
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::set< std::string > _depend_uo
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.
FEProblemBase & _fe_problem
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
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.
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.
virtual unsigned int getNumberOfCrackFrontPoints() const override
Get the current number of crack front points.
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 ...