14 #include "libmesh/string_to_enum.h" 17 #include "libmesh/face_tri3.h" 18 #include "libmesh/edge_edge2.h" 19 #include "libmesh/serial_mesh.h" 20 #include "libmesh/plane.h" 21 #include "libmesh/mesh_tools.h" 32 "Mesh file for the XFEM geometric cut; currently only the xda type is supported");
33 MooseEnum growthDirection(
"MAX_HOOP_STRESS FUNCTION",
"FUNCTION");
35 "growth_dir_method", growthDirection,
"choose from FUNCTION, MAX_HOOP_STRESS");
36 MooseEnum growthRate(
"FATIGUE FUNCTION",
"FUNCTION");
37 params.
addParam<
MooseEnum>(
"growth_rate_method", growthRate,
"choose from FUNCTION, FATIGUE");
38 params.
addParam<FunctionName>(
"growth_direction_x",
39 "Function defining x-component of crack growth direction");
40 params.
addParam<FunctionName>(
"growth_direction_y",
41 "Function defining y-component of crack growth direction");
42 params.
addParam<FunctionName>(
"growth_direction_z",
43 "Function defining z-component of crack growth direction");
45 params.
addParam<FunctionName>(
"growth_rate",
"Function defining crack growth rate");
47 "size_control", 0,
"Criterion for refining elements while growing the crack");
48 params.
addParam<
unsigned int>(
"n_step_growth", 0,
"Number of steps for crack growth");
49 params.
addParam<std::vector<dof_id_type>>(
"crack_front_nodes",
50 "Set of nodes to define crack front");
59 _mesh(_subproblem.
mesh()),
62 _n_step_growth(getParam<unsigned
int>(
"n_step_growth")),
63 _is_mesh_modified(false),
64 _func_x(parameters.isParamValid(
"growth_direction_x") ? &getFunction(
"growth_direction_x")
66 _func_y(parameters.isParamValid(
"growth_direction_y") ? &getFunction(
"growth_direction_y")
68 _func_z(parameters.isParamValid(
"growth_direction_z") ? &getFunction(
"growth_direction_z")
70 _func_v(parameters.isParamValid(
"growth_rate") ? &getFunction(
"growth_rate") : nullptr)
83 mooseError(
"function is not specified for the function method that defines growth direction");
86 mooseError(
"function is not specified for the function method that defines growth rate");
89 mooseError(
"function with a variable is not specified for the fatigue method that defines " 105 mooseError(
"'crack_front_nodes' is not specified to use crack growth criteria!");
108 MeshFileName xfem_cut_mesh_file = getParam<MeshFileName>(
"mesh_file");
113 for (
const auto & cut_elem :
_cut_mesh->element_ptr_range())
116 mooseError(
"The input cut mesh should include tri elements only!");
118 mooseError(
"The input cut mesh should have 2D elements only!");
186 std::vector<Xfem::CutEdge> & ,
187 std::vector<Xfem::CutNode> & )
const 189 mooseError(
"invalid method for 3D mesh cutting");
195 std::vector<Xfem::CutFace> & cut_faces)
const 200 bool elem_cut =
false;
202 if (elem->dim() != _elem_dim)
203 mooseError(
"The structural mesh to be cut by a surface mesh must be 3D!");
205 for (
unsigned int i = 0; i < elem->n_sides(); ++i)
208 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
209 if (curr_side->dim() != 2)
210 mooseError(
"In cutElementByGeometry dimension of side must be 2, but it is ",
212 unsigned int n_edges = curr_side->n_sides();
214 std::vector<unsigned int> cut_edges;
215 std::vector<Real> cut_pos;
217 for (
unsigned int j = 0;
j < n_edges;
j++)
220 std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(
j);
221 if (curr_edge->type() !=
EDGE2)
222 mooseError(
"In cutElementByGeometry face edge must be EDGE2, but type is: ",
224 " base element type is: ",
226 const Node * node1 = curr_edge->node_ptr(0);
227 const Node * node2 = curr_edge->node_ptr(1);
229 for (
const auto & cut_elem : _cut_mesh->element_ptr_range())
231 std::vector<Point> vertices;
233 for (
auto & node : cut_elem->node_ref_range())
235 Point & this_point = node;
236 vertices.push_back(this_point);
242 cut_edges.push_back(
j);
249 if (cut_edges.size() == 2)
258 cut_faces.push_back(mycut);
266 std::vector<Xfem::CutEdge> & )
const 268 mooseError(
"invalid method for 3D mesh cutting");
274 std::vector<Xfem::CutFace> & )
const 277 mooseError(
"cutFragmentByGeometry not yet implemented for 3D mesh cutting");
284 const std::vector<Point> & vertices,
287 bool has_intersection =
false;
289 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
290 Point point = vertices[0];
291 Point normal = elem_plane.unit_normal(point);
293 std::array<Real, 3> plane_point = {{point(0), point(1), point(2)}};
294 std::array<Real, 3> planenormal = {{normal(0), normal(1), normal(2)}};
295 std::array<Real, 3> edge_point1 = {{p1(0), p1(1), p1(2)}};
296 std::array<Real, 3> edge_point2 = {{p2(0), p2(1), p2(2)}};
297 std::array<Real, 3> cut_point = {{0.0, 0.0, 0.0}};
300 &plane_point[0], &planenormal[0], &edge_point1[0], &edge_point2[0], &cut_point[0]) == 1)
302 Point temp_p(cut_point[0], cut_point[1], cut_point[2]);
306 has_intersection =
true;
309 return has_intersection;
315 const std::vector<Point> & vertices,
318 bool has_intersection =
false;
320 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
321 Point point = vertices[0];
322 Point normal = elem_plane.unit_normal(point);
324 std::array<Real, 3> plane_point = {{point(0), point(1), point(2)}};
325 std::array<Real, 3> planenormal = {{normal(0), normal(1), normal(2)}};
326 std::array<Real, 3> p_begin = {{p1(0), p1(1), p1(2)}};
327 std::array<Real, 3> p_end = {{p2(0), p2(1), p2(2)}};
328 std::array<Real, 3> cut_point = {{0.0, 0.0, 0.0}};
331 &plane_point[0], &planenormal[0], &p_begin[0], &p_end[0], &cut_point[0]) == 1)
333 Point p(cut_point[0], cut_point[1], cut_point[2]);
334 Real dotp = ((p - p1) * (p2 - p1)) / ((p2 - p1) * (p2 - p1));
338 has_intersection =
true;
341 return has_intersection;
347 Real dotp1 = (p1 - p) * (p2 - p1);
348 Real dotp2 = (p2 - p) * (p2 - p1);
349 return (dotp1 * dotp2 <= 0.0);
355 const Point & p)
const 359 return len_p1_p / full_len;
364 const Point & p)
const 366 unsigned int n_node = vertices.size();
368 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
369 Point normal = elem_plane.unit_normal(vertices[0]);
372 unsigned int counter = 0;
374 for (
unsigned int i = 0; i < n_node; ++i)
376 unsigned int iplus1 = (i < n_node - 1 ? i + 1 : 0);
377 Point middle2p = p - 0.5 * (vertices[i] + vertices[iplus1]);
378 const Point side_tang = vertices[iplus1] - vertices[i];
379 Point side_norm = side_tang.cross(normal);
382 if (middle2p * side_norm <= 0.0)
385 if (counter == n_node)
393 auto boundary_node_ids = MeshTools::find_boundary_nodes(*
_cut_mesh);
394 for (
auto it = boundary_node_ids.cbegin(); it != boundary_node_ids.cend(); it++)
397 std::vector<dof_id_type> neighbors;
407 std::vector<dof_id_type> corner_elem_id;
408 unsigned int counter = 0;
413 for (
const auto & cut_elem :
_cut_mesh->element_ptr_range())
417 node_id[i] = cut_elem->node_ptr(i)->id();
421 if (is_node_on_boundary[0] && is_node_on_boundary[1] && is_node_on_boundary[2])
425 corner_elem_id.push_back(counter);
433 if (is_node_on_boundary[i] && is_node_on_boundary[(i + 1 <= 2) ? i + 1 : 0])
436 dof_id_type node2 = node_id[(i + 1 <= 2) ? i + 1 : 0];
438 std::swap(node1, node2);
443 std::swap(node1, node2);
456 for (
unsigned int i = 0; i < corner_elem_id.size(); ++i)
458 auto elem_it =
_cut_mesh->elements_begin();
462 Elem * cut_elem = *elem_it;
466 bool is_edge_inside = 0;
469 dof_id_type node2 = cut_elem->node_ptr((
j + 1 <= 2) ?
j + 1 : 0)->id();
471 std::swap(node1, node2);
473 unsigned int counter = 0;
474 for (
const auto & cut_elem2 :
_cut_mesh->element_ptr_range())
476 if (counter != corner_elem_id[i])
481 dof_id_type node4 = cut_elem2->node_ptr((
k + 1 <= 2) ?
k + 1 : 0)->id();
483 std::swap(node3, node4);
485 if (node1 == node3 && node2 == node4)
495 if (is_edge_inside == 0)
501 std::swap(node1, node2);
512 if ((*it)._id1 == node1 && (*it)._id2 == node2)
533 "_boundary_map does not have this key");
535 "_boundary_map does not have this key");
544 if (it->second.size() != 2)
546 "Boundary nodes in the cutter mesh must have exactly two neighbors; this one has: ",
560 "_boundary_map does not have this key");
571 else if (node4 == node1)
578 mooseError(
"Discontinuity in cutter boundary");
586 mooseAssert(n1 !=
nullptr,
"Node is NULL");
588 mooseAssert(n2 !=
nullptr,
"Node is NULL");
598 mooseAssert(
_boundary.size() >= 2,
"Boundary should have at least two nodes");
600 for (
unsigned int i =
_boundary.size() - 1; i >= 1; --i)
610 std::array<Real, 3> x1;
611 std::array<Real, 3> x2;
614 mooseAssert(n1 !=
nullptr,
"Node is NULL");
617 mooseAssert(n2 !=
nullptr,
"Node is NULL");
620 for (
unsigned int j = 0;
j < 3; ++
j)
626 for (
unsigned int j = 0;
j < n; ++
j)
629 for (
unsigned int k = 0;
k < 3; ++
k)
630 x(
k) = x2[
k] - (x2[
k] - x1[
k]) * (
j + 1) / (n + 1);
632 Node * this_node = Node::build(
x,
_cut_mesh->n_nodes()).release();
636 auto it = new_boundary_order.begin();
637 new_boundary_order.insert(it + i,
id);
643 mooseAssert(
_boundary.size() > 0,
"Boundary should not have zero size");
654 pl->enable_out_of_mesh_mode();
656 unsigned int n_boundary =
_boundary.size();
660 for (
unsigned int j = 0;
j < n_boundary; ++
j)
663 mooseAssert(this_node,
"Node is NULL");
664 Point & this_point = *this_node;
666 const Elem * elem = (*pl)(this_point);
674 if (n_inactive_boundary == n_boundary)
678 if (n_inactive_boundary == 0)
682 for (
unsigned int i = 0; i < n_inactive_boundary - 1; ++i)
686 std::vector<dof_id_type> temp;
697 std::vector<dof_id_type> temp;
711 "crack-front-definition using the cutter mesh only supports one active crack front " 718 std::vector<Point> temp;
723 for (
unsigned int j = 0;
j < 3; ++
j)
738 for (
unsigned int j = i1;
j < i2; ++
j)
741 mooseAssert(this_node,
"Node is NULL");
742 Point & this_point = *this_node;
755 mooseAssert(k1.size() == k2.size(),
"KI and KII VPPs should have the same size");
757 "the number of crack front nodes in the self-similar method should equal to the " 758 "size of VPP defined at the crack front");
760 "the number of crack front nodes should be the same in _crack_front_points and " 761 "_active_boundary[0]");
767 for (
unsigned int j = i1;
j < i2; ++
j)
770 Real theta = 2 * std::atan((k1[ind] - std::sqrt(k1[ind] * k1[ind] + k2[ind] * k2[ind])) /
776 dir_cfc(0) = std::cos(theta);
777 dir_cfc(1) = std::sin(theta);
785 mooseError(
"This growth_dir_method is not pre-defined!");
789 for (
unsigned int j = 0;
j < 3; ++
j)
804 Real length = std::sqrt(pt * pt);
821 std::vector<dof_id_type> temp;
831 for (
unsigned int j = i1;
j < i2; ++
j)
834 mooseAssert(this_node,
"Node is NULL");
835 Point & this_point = *this_node;
841 for (
unsigned int k = 0;
k < 3; ++
k)
844 x(
k) = this_point(
k) + dir(
k) * velo;
851 unsigned long int dn = (
unsigned long int)
_func_v->
value(0, Point(0, 0, 0));
853 _n.push_back(
_n.size() == 0 ? dn : dn +
_n[
_n.size() - 1]);
857 for (
unsigned int k = 0;
k < 3; ++
k)
858 x(
k) = this_point(
k) + dir(
k) * growth_size;
861 mooseError(
"This growth_rate_method is not pre-defined!");
863 this_node = Node::build(
x,
_cut_mesh->n_nodes()).release();
897 for (
unsigned int i = 0; i <
_front.size(); ++i)
899 if (
_front[i].size() >= 2)
901 std::vector<Point> pint1;
902 std::vector<Point> pint2;
903 std::vector<Real> length1;
904 std::vector<Real> length2;
907 Node * this_node =
_cut_mesh->node_ptr(node_id);
908 mooseAssert(this_node,
"Node is NULL");
909 Point & p2 = *this_node;
911 if (
_front[i].size() >= 4)
916 this_node =
_cut_mesh->node_ptr(node_id);
917 mooseAssert(this_node,
"Node is NULL");
918 Point & p1 = *this_node;
920 node_id =
_front[i].back();
921 this_node =
_cut_mesh->node_ptr(node_id);
922 mooseAssert(this_node,
"Node is NULL");
923 Point & p4 = *this_node;
925 if (
_front[i].size() >= 4)
930 this_node =
_cut_mesh->node_ptr(node_id);
931 mooseAssert(this_node,
"Node is NULL");
932 Point & p3 = *this_node;
938 pl->enable_out_of_mesh_mode();
939 const Elem * elem = (*pl)(p1);
946 for (
const auto & belem : range)
949 std::vector<Point> vertices;
952 std::unique_ptr<const Elem> curr_side = elem->side_ptr(belem->_side);
953 for (
unsigned int j = 0;
j < curr_side->n_nodes(); ++
j)
955 const Node * node = curr_side->node_ptr(
j);
956 const Point & this_point = *node;
957 vertices.push_back(this_point);
963 length1.push_back((pt - p1) * (pt - p1));
968 length2.push_back((pt - p3) * (pt - p3));
972 if (length1.size() != 0 && do_inter1)
974 auto it1 = std::min_element(length1.begin(), length1.end());
975 Point inter1 = pint1[std::distance(length1.begin(), it1)];
978 Node * this_node = Node::build(inter1,
_cut_mesh->n_nodes()).release();
981 mooseAssert(
_cut_mesh->n_nodes() - 1 > 0,
"The cut mesh should have at least one element.");
982 unsigned int n =
_cut_mesh->n_nodes() - 1;
984 auto it =
_front[i].begin();
991 if (length2.size() != 0 && do_inter2)
993 auto it2 = std::min_element(length2.begin(), length2.end());
994 Point inter2 = pint2[std::distance(length2.begin(), it2)];
997 Node * this_node = Node::build(inter2,
_cut_mesh->n_nodes()).release();
1002 auto it =
_front[i].begin();
1003 unsigned int m =
_front[i].size();
1004 _front[i].insert(it + m, n);
1016 std::vector<std::vector<dof_id_type>> new_front(
_front.begin(),
_front.end());
1018 for (
unsigned int ifront = 0; ifront <
_front.size(); ++ifront)
1020 unsigned int i1 =
_front[ifront].size() - 1;
1022 i1 =
_front[ifront].size();
1024 for (
unsigned int i = i1; i >= 1; --i)
1026 unsigned int i2 = i;
1028 i2 = (i <=
_front[ifront].size() - 1 ? i : 0);
1037 std::array<Real, 3> x1;
1038 std::array<Real, 3> x2;
1040 Node * this_node =
_cut_mesh->node_ptr(node1);
1041 mooseAssert(this_node,
"Node is NULL");
1042 Point & p1 = *this_node;
1044 mooseAssert(this_node,
"Node is NULL");
1045 Point & p2 = *this_node;
1047 for (
unsigned int j = 0;
j < 3; ++
j)
1053 for (
unsigned int j = 0;
j < n; ++
j)
1056 for (
unsigned int k = 0;
k < 3; ++
k)
1057 x(
k) = x2[
k] - (x2[
k] - x1[
k]) * (
j + 1) / (n + 1);
1059 Node * this_node = Node::build(
x,
_cut_mesh->n_nodes()).release();
1064 auto it = new_front[ifront].begin();
1065 new_front[ifront].insert(it + i,
id);
1085 mooseError(
"the crack front and the tracked crack front definition must match in terms of " 1098 "_active_boundary and _front should have the same size!");
1107 for (
unsigned int k = 0;
k <
_front.size(); ++
k)
1110 unsigned int n2 =
_front[
k].size();
1112 unsigned int i1 = 0;
1113 unsigned int i2 = 0;
1116 while (!(i1 == n1 - 1 && i2 == n2 - 1))
1118 std::vector<dof_id_type> elem;
1123 if (i1 != n1 - 1 && i2 != n2 - 1)
1147 else if (i1 == n1 - 1)
1157 else if (i2 == n2 - 1)
1167 Elem * new_elem = Elem::build(
TRI3).release();
1171 mooseAssert(
_cut_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
1172 new_elem->set_node(i,
_cut_mesh->node_ptr(elem[i]));
1190 std::vector<dof_id_type> full_front;
1194 for (
unsigned int i = 0; i < size1; ++i)
1201 full_front.insert(full_front.end(),
_front[i].begin(),
_front[i].end());
1204 unsigned int pos1 = std::distance(
_boundary.begin(), it1);
1206 unsigned int pos2 = std::distance(
_boundary.begin(), it2);
1209 full_front.insert(full_front.end(),
_boundary.begin() + pos1,
_boundary.begin() + pos2 + 1);
1213 full_front.insert(full_front.end(),
_boundary.begin(),
_boundary.begin() + pos2 + 1);
1220 const std::vector<Point>
1223 std::vector<Point> crack_front_points(number_crack_front_points);
1227 mooseError(
"number_points_from_provider does not match the number of nodes given in " 1228 "crack_front_nodes");
1229 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
1232 Node * this_node =
_cut_mesh->node_ptr(
id);
1233 mooseAssert(this_node,
"Node is NULL");
1234 Point & this_point = *this_node;
1235 crack_front_points[i] = this_point;
1237 return crack_front_points;
1240 const std::vector<RealVectorValue>
1243 std::vector<RealVectorValue> crack_plane_normals(number_crack_front_points);
1246 std::unordered_map<dof_id_type, std::vector<dof_id_type>> node_to_elems_map;
1247 node_to_elems_map.clear();
1248 for (
const auto & elem :
_cut_mesh->element_ptr_range())
1249 for (
auto & node : elem->node_ref_range())
1250 node_to_elems_map[node.id()].push_back(elem->id());
1253 std::unordered_map<dof_id_type, RealVectorValue> elem_to_normal_map;
1254 elem_to_normal_map.clear();
1255 for (
const auto & elem :
_cut_mesh->element_ptr_range())
1257 Point & p1 = *elem->node_ptr(0);
1258 Point & p2 = *elem->node_ptr(1);
1259 Point & p3 = *elem->node_ptr(2);
1260 Plane elem_plane(p3, p2, p1);
1262 elem_to_normal_map[elem->id()] = normal;
1268 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
1271 std::vector<dof_id_type> elems = node_to_elems_map[id];
1272 unsigned int n_elem = elems.size();
1275 for (
unsigned int j = 0;
j <
n_elem; ++
j)
1276 normal_avr += elem_to_normal_map[elems[
j]];
1277 normal_avr = normal_avr /
n_elem;
1278 crack_plane_normals[i] = normal_avr;
1280 return crack_plane_normals;
1288 unsigned int ibnd = 0;
1292 std::vector<int> index(size_this_segment, -1);
1294 unsigned int i1 = n_inactive_nodes == 0 ? 0 : 1;
1295 unsigned int i2 = n_inactive_nodes == 0 ? size_this_segment : size_this_segment - 1;
1298 for (
unsigned int j = i1;
j < i2; ++
j)
void isCutterModified(const bool is_cutter_modified)
Set the value of _is_cutter_modified.
int _last_step_initialized
Time step information needed to advance a 3D crack only at the real beginning of a time step...
GrowthDirectionEnum
Enum to for crack growth direction.
CrackMeshCut3DUserObject: (1) reads in a mesh describing the crack surface, (2) uses the mesh to do i...
std::vector< unsigned long int > _dn
Fatigue life.
Real _size_control
Used for cutter mesh refinement and front advancement.
static InputParameters validParams()
Factory constructor, takes parameters so that all derived classes can be built using the same constru...
T & getUserObject(const std::string &name, unsigned int tid=0) const
void findBoundaryNodes()
Find boundary nodes of the cutter mesh This is a simple algorithm simply based on the added angle = 3...
std::vector< int > getFrontPointsIndex()
Get crack front points in the active segment -1 means inactive; positive is the point's index in the ...
void mooseError(Args &&... args)
const unsigned int _cut_elem_nnode
The cutter mesh has triangluar elements only.
void findActiveBoundaryNodes()
Find all active boundary nodes in the cutter mesh Find boundary nodes that will grow; nodes outside o...
unsigned int _n_step_growth
Number of steps to grow the mesh.
std::vector< unsigned long int > _n
bool findIntersection(const Point &p1, const Point &p2, const std::vector< Point > &vertices, Point &point) const
Find directional intersection along the positive extension of the vector from p1 to p2...
const GrowthDirectionEnum _growth_dir_method
The direction method for growing mesh at the front.
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point >> &frag_edges, std::vector< Xfem::CutEdge > &cut_edges) const override
void setSubCriticalGrowthSize(std::vector< Real > &growth_size)
Return growth size at the active boundary to the mesh cutter.
const Parallel::Communicator & _communicator
Real getRelativePosition(const Point &p1, const Point &p2, const Point &p) const
Get the relative position of p from p1.
std::vector< Real > _position
Fractional distance along the cut edges where the cut is located.
Real findDistance(dof_id_type node1, dof_id_type node2)
Find distance between two nodes.
std::map< dof_id_type, std::vector< dof_id_type > > _boundary_map
A map of boundary nodes and their neighbors.
Real distance(const Point &p)
void growFront()
Grow the cutter mesh.
void updateNumberOfCrackFrontPoints(const std::size_t num_points)
Change the number of crack front nodes.
Data structure defining a cut through a face.
const Real _const_intersection
Used to define intersection points.
void findBoundaryEdges()
Find boundary edges of the cutter mesh.
void triangulation()
Create tri3 elements between the new front and the old front.
bool isParamValid(const std::string &name) const
void refineFront()
Refine the mesh at the front.
Data structure defining a cut on an element edge.
std::vector< dof_id_type > _tracked_crack_front_points
Front nodes that are grown from the crack front definition defined in the input therefore, they are (1) in the same order as defined in the input and (2) the number of nodes does not change.
RealVectorValue rotateFromCrackFrontCoordsToGlobal(const RealVectorValue vector, const std::size_t point_index) const
Rotate a vector from crack front cartesian coordinate to global cartesian coordinate.
int plane_normal_line_exp_int_3d(double pp[3], double normal[3], double p1[3], double p2[3], double pint[3])
void sortFrontNodes()
Sort the front nodes.
Class used in fracture integrals to define geometric characteristics of the crack front...
std::vector< dof_id_type > _crack_front_points
updated crack front definition they are in the same order as defined in the input but the number of n...
Real getRelativePosition(const Point &p1, const Point &p2, const Point &p)
Get the relative position of p from p1 respect to the total length of the line segment.
void findFrontIntersection()
Find front-structure intersections.
const Function * _func_x
Parsed functions of front growth.
std::vector< std::vector< dof_id_type > > _front
New boundary after growth.
virtual void initialSetup() override
unsigned int _id1
ID of the first node on the edge.
const std::vector< double > x
registerMooseObject("XFEMApp", CrackMeshCut3DUserObject)
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
bool intersectWithEdge(const Point &p1, const Point &p2, const std::vector< Point > &vertices, Point &pint)
check if a line intersects with an element defined by vertices calculate the distance from a point to...
unsigned int _num_crack_front_points
Total number of crack front points in the mesh cutter.
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes) const override
bool _is_mesh_modified
Indicator that shows if the cutting mesh is modified or not in this calculation step.
CrackMeshCut3DUserObject(const InputParameters ¶meters)
bool _stop
Variables to help control the work flow.
const unsigned int _cut_elem_dim
std::vector< unsigned int > _inactive_boundary_pos
Inactive boundary.
std::string enum_to_string(const T e)
void joinBoundary()
Join active boundaries and inactive boundaries to be the new boundary.
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 ...
std::vector< Real > VectorPostprocessorValue
virtual bool intersectWithEdge(const Point &p1, const Point &p2, const std::vector< Point > &_vertices, Point &point) const
Check if a line intersects with an element.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void sortBoundaryNodes()
Sort boundary nodes to be in the right order along the boundary.
unsigned int _id2
ID of the second node on the edge.
FEProblemBase & _fe_problem
std::vector< std::vector< dof_id_type > > _active_boundary
Active boundary nodes where growth is allowed.
void mooseError(Args &&... args) const
unsigned int getNumberOfCrackFrontPoints() const
Return the total number of crack front points.
MooseMesh & _mesh
The structural mesh.
CrackFrontDefinition * _crack_front_definition
The crack front definition.
static InputParameters validParams()
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void normalizePoint(Point &p)
virtual std::unique_ptr< libMesh::PointLocatorBase > getPointLocator() const
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement *> * getBoundaryElementRange()
virtual void initialize() override
GrowthRateEnum
Enum to for crack growth rate.
virtual Real value(Real t, const Point &p) const
const GrowthRateEnum _growth_rate_method
The rate method for growing mesh at the front.
bool isInsideEdge(const Point &p1, const Point &p2, const Point &p) const
Check if point p is inside the edge p1-p2.
std::set< Xfem::CutEdge > _boundary_edges
Edges at the boundary.
std::vector< Real > _growth_size
Growth size for the active boundary in a subcritical simulation.
const VectorPostprocessorValue & getVectorPostprocessorValueByName(const VectorPostprocessorName &name, const std::string &vector_name) const
void refineBoundary()
If boundary nodes are too sparse, add nodes in between.
std::vector< std::vector< Point > > _active_direction
Growth direction for active boundaries.
static const std::string k
void ErrorVector unsigned int
void findActiveBoundaryDirection()
Find growth direction at each active node.
std::unique_ptr< MeshBase > _cut_mesh
The cutter mesh.
std::vector< unsigned int > _face_edge
IDs of all cut faces.
unsigned int _face_id
ID of the cut face.
bool isInsideCutPlane(const std::vector< Point > &_vertices, const Point &p) const
Check if point p is inside a plane.
std::vector< dof_id_type > _boundary
Boundary nodes of the cutter mesh.