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" 30 MooseEnum growthDirection(
"MAX_HOOP_STRESS FUNCTION",
"FUNCTION");
32 "growth_dir_method", growthDirection,
"choose from FUNCTION, MAX_HOOP_STRESS");
33 MooseEnum growthRate(
"FATIGUE FUNCTION",
"FUNCTION");
34 params.
addParam<
MooseEnum>(
"growth_rate_method", growthRate,
"choose from FUNCTION, FATIGUE");
35 params.
addParam<FunctionName>(
"growth_direction_x",
36 "Function defining x-component of crack growth direction");
37 params.
addParam<FunctionName>(
"growth_direction_y",
38 "Function defining y-component of crack growth direction");
39 params.
addParam<FunctionName>(
"growth_direction_z",
40 "Function defining z-component of crack growth direction");
42 params.
addParam<FunctionName>(
"growth_rate",
"Function defining crack growth rate");
44 "size_control", 0,
"Criterion for refining elements while growing the crack");
45 params.
addParam<
unsigned int>(
"n_step_growth", 0,
"Number of steps for crack growth");
46 params.
addParam<std::vector<dof_id_type>>(
"crack_front_nodes",
47 "Set of nodes to define crack front");
56 _mesh(_subproblem.
mesh()),
59 _n_step_growth(getParam<unsigned
int>(
"n_step_growth")),
60 _is_mesh_modified(false),
61 _func_x(parameters.isParamValid(
"growth_direction_x") ? &getFunction(
"growth_direction_x")
63 _func_y(parameters.isParamValid(
"growth_direction_y") ? &getFunction(
"growth_direction_y")
65 _func_z(parameters.isParamValid(
"growth_direction_z") ? &getFunction(
"growth_direction_z")
67 _func_v(parameters.isParamValid(
"growth_rate") ? &getFunction(
"growth_rate") : nullptr)
80 mooseError(
"function is not specified for the function method that defines growth direction");
83 mooseError(
"function is not specified for the function method that defines growth rate");
86 mooseError(
"function with a variable is not specified for the fatigue method that defines " 102 mooseError(
"'crack_front_nodes' is not specified to use crack growth criteria!");
105 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
108 mooseError(
"The input cut mesh should include tri elements only!");
110 mooseError(
"The input cut mesh should have 2D elements only!");
178 std::vector<Xfem::CutEdge> & ,
179 std::vector<Xfem::CutNode> & )
const 181 mooseError(
"invalid method for 3D mesh cutting");
187 std::vector<Xfem::CutFace> & cut_faces)
const 192 bool elem_cut =
false;
194 if (elem->dim() != _elem_dim)
195 mooseError(
"The structural mesh to be cut by a surface mesh must be 3D!");
197 for (
unsigned int i = 0; i < elem->n_sides(); ++i)
200 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
201 if (curr_side->dim() != 2)
202 mooseError(
"In cutElementByGeometry dimension of side must be 2, but it is ",
204 unsigned int n_edges = curr_side->n_sides();
206 std::vector<unsigned int> cut_edges;
207 std::vector<Real> cut_pos;
209 for (
unsigned int j = 0;
j < n_edges;
j++)
212 std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(
j);
213 if (curr_edge->type() !=
EDGE2)
214 mooseError(
"In cutElementByGeometry face edge must be EDGE2, but type is: ",
216 " base element type is: ",
218 const Node * node1 = curr_edge->node_ptr(0);
219 const Node * node2 = curr_edge->node_ptr(1);
221 for (
const auto & cut_elem : _cutter_mesh->element_ptr_range())
223 std::vector<Point> vertices;
225 for (
auto & node : cut_elem->node_ref_range())
227 Point & this_point = node;
228 vertices.push_back(this_point);
234 cut_edges.push_back(
j);
241 if (cut_edges.size() == 2)
250 cut_faces.push_back(mycut);
258 std::vector<Xfem::CutEdge> & )
const 260 mooseError(
"invalid method for 3D mesh cutting");
266 std::vector<Xfem::CutFace> & )
const 269 mooseError(
"cutFragmentByGeometry not yet implemented for 3D mesh cutting");
276 const std::vector<Point> & vertices,
279 bool has_intersection =
false;
281 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
282 Point point = vertices[0];
283 Point normal = elem_plane.unit_normal(point);
285 std::array<Real, 3> plane_point = {{point(0), point(1), point(2)}};
286 std::array<Real, 3> planenormal = {{normal(0), normal(1), normal(2)}};
287 std::array<Real, 3> edge_point1 = {{p1(0), p1(1), p1(2)}};
288 std::array<Real, 3> edge_point2 = {{p2(0), p2(1), p2(2)}};
289 std::array<Real, 3> cut_point = {{0.0, 0.0, 0.0}};
292 &plane_point[0], &planenormal[0], &edge_point1[0], &edge_point2[0], &cut_point[0]) == 1)
294 Point temp_p(cut_point[0], cut_point[1], cut_point[2]);
298 has_intersection =
true;
301 return has_intersection;
307 const std::vector<Point> & vertices,
310 bool has_intersection =
false;
312 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
313 Point point = vertices[0];
314 Point normal = elem_plane.unit_normal(point);
316 std::array<Real, 3> plane_point = {{point(0), point(1), point(2)}};
317 std::array<Real, 3> planenormal = {{normal(0), normal(1), normal(2)}};
318 std::array<Real, 3> p_begin = {{p1(0), p1(1), p1(2)}};
319 std::array<Real, 3> p_end = {{p2(0), p2(1), p2(2)}};
320 std::array<Real, 3> cut_point = {{0.0, 0.0, 0.0}};
323 &plane_point[0], &planenormal[0], &p_begin[0], &p_end[0], &cut_point[0]) == 1)
325 Point p(cut_point[0], cut_point[1], cut_point[2]);
326 Real dotp = ((p - p1) * (p2 - p1)) / ((p2 - p1) * (p2 - p1));
330 has_intersection =
true;
333 return has_intersection;
339 Real dotp1 = (p1 - p) * (p2 - p1);
340 Real dotp2 = (p2 - p) * (p2 - p1);
341 return (dotp1 * dotp2 <= 0.0);
347 const Point & p)
const 351 return len_p1_p / full_len;
356 const Point & p)
const 358 unsigned int n_node = vertices.size();
360 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
361 Point normal = elem_plane.unit_normal(vertices[0]);
364 unsigned int counter = 0;
366 for (
unsigned int i = 0; i < n_node; ++i)
368 unsigned int iplus1 = (i < n_node - 1 ? i + 1 : 0);
369 Point middle2p = p - 0.5 * (vertices[i] + vertices[iplus1]);
370 const Point side_tang = vertices[iplus1] - vertices[i];
371 Point side_norm = side_tang.cross(normal);
374 if (middle2p * side_norm <= 0.0)
377 if (counter == n_node)
385 auto boundary_node_ids = MeshTools::find_boundary_nodes(*
_cutter_mesh);
386 for (
auto it = boundary_node_ids.cbegin(); it != boundary_node_ids.cend(); it++)
389 std::vector<dof_id_type> neighbors;
399 std::vector<dof_id_type> corner_elem_id;
400 unsigned int counter = 0;
405 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
409 node_id[i] = cut_elem->node_ptr(i)->id();
413 if (is_node_on_boundary[0] && is_node_on_boundary[1] && is_node_on_boundary[2])
417 corner_elem_id.push_back(counter);
425 if (is_node_on_boundary[i] && is_node_on_boundary[(i + 1 <= 2) ? i + 1 : 0])
428 dof_id_type node2 = node_id[(i + 1 <= 2) ? i + 1 : 0];
430 std::swap(node1, node2);
435 std::swap(node1, node2);
448 for (
unsigned int i = 0; i < corner_elem_id.size(); ++i)
454 Elem * cut_elem = *elem_it;
458 bool is_edge_inside = 0;
461 dof_id_type node2 = cut_elem->node_ptr((
j + 1 <= 2) ?
j + 1 : 0)->id();
463 std::swap(node1, node2);
465 unsigned int counter = 0;
466 for (
const auto & cut_elem2 :
_cutter_mesh->element_ptr_range())
468 if (counter != corner_elem_id[i])
473 dof_id_type node4 = cut_elem2->node_ptr((
k + 1 <= 2) ?
k + 1 : 0)->id();
475 std::swap(node3, node4);
477 if (node1 == node3 && node2 == node4)
487 if (is_edge_inside == 0)
493 std::swap(node1, node2);
504 if ((*it)._id1 == node1 && (*it)._id2 == node2)
525 "_boundary_map does not have this key");
527 "_boundary_map does not have this key");
536 if (it->second.size() != 2)
538 "Boundary nodes in the cutter mesh must have exactly two neighbors; this one has: ",
552 "_boundary_map does not have this key");
563 else if (node4 == node1)
570 mooseError(
"Discontinuity in cutter boundary");
578 mooseAssert(n1 !=
nullptr,
"Node is NULL");
580 mooseAssert(n2 !=
nullptr,
"Node is NULL");
590 mooseAssert(
_boundary.size() >= 2,
"Boundary should have at least two nodes");
592 for (
unsigned int i =
_boundary.size() - 1; i >= 1; --i)
602 std::array<Real, 3> x1;
603 std::array<Real, 3> x2;
606 mooseAssert(n1 !=
nullptr,
"Node is NULL");
609 mooseAssert(n2 !=
nullptr,
"Node is NULL");
612 for (
unsigned int j = 0;
j < 3; ++
j)
618 for (
unsigned int j = 0;
j < n; ++
j)
621 for (
unsigned int k = 0;
k < 3; ++
k)
622 x(
k) = x2[
k] - (x2[
k] - x1[
k]) * (
j + 1) / (n + 1);
624 Node * this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
628 auto it = new_boundary_order.begin();
629 new_boundary_order.insert(it + i,
id);
635 mooseAssert(
_boundary.size() > 0,
"Boundary should not have zero size");
646 pl->enable_out_of_mesh_mode();
648 unsigned int n_boundary =
_boundary.size();
652 for (
unsigned int j = 0;
j < n_boundary; ++
j)
655 mooseAssert(this_node,
"Node is NULL");
656 Point & this_point = *this_node;
658 const Elem * elem = (*pl)(this_point);
666 if (n_inactive_boundary == n_boundary)
670 if (n_inactive_boundary == 0)
674 for (
unsigned int i = 0; i < n_inactive_boundary - 1; ++i)
678 std::vector<dof_id_type> temp;
689 std::vector<dof_id_type> temp;
703 "crack-front-definition using the cutter mesh only supports one active crack front " 710 std::vector<Point> temp;
715 for (
unsigned int j = 0;
j < 3; ++
j)
730 for (
unsigned int j = i1;
j < i2; ++
j)
733 mooseAssert(this_node,
"Node is NULL");
734 Point & this_point = *this_node;
747 mooseAssert(k1.size() == k2.size(),
"KI and KII VPPs should have the same size");
749 "the number of crack front nodes in the self-similar method should equal to the " 750 "size of VPP defined at the crack front");
752 "the number of crack front nodes should be the same in _crack_front_points and " 753 "_active_boundary[0]");
759 for (
unsigned int j = i1;
j < i2; ++
j)
762 Real theta = 2 * std::atan((k1[ind] - std::sqrt(k1[ind] * k1[ind] + k2[ind] * k2[ind])) /
771 dir_cfc(0) = std::cos(theta);
772 dir_cfc(1) = std::sin(theta);
780 mooseError(
"This growth_dir_method is not pre-defined!");
784 for (
unsigned int j = 0;
j < 3; ++
j)
799 Real length = std::sqrt(pt * pt);
816 std::vector<dof_id_type> temp;
826 for (
unsigned int j = i1;
j < i2; ++
j)
829 mooseAssert(this_node,
"Node is NULL");
830 Point & this_point = *this_node;
836 for (
unsigned int k = 0;
k < 3; ++
k)
839 x(
k) = this_point(
k) + dir(
k) * velo;
846 unsigned long int dn = (
unsigned long int)
_func_v->
value(0, Point(0, 0, 0));
848 _n.push_back(
_n.size() == 0 ? dn : dn +
_n[
_n.size() - 1]);
852 for (
unsigned int k = 0;
k < 3; ++
k)
853 x(
k) = this_point(
k) + dir(
k) * growth_size;
856 mooseError(
"This growth_rate_method is not pre-defined!");
858 this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
892 for (
unsigned int i = 0; i <
_front.size(); ++i)
894 if (
_front[i].size() >= 2)
896 std::vector<Point> pint1;
897 std::vector<Point> pint2;
898 std::vector<Real> length1;
899 std::vector<Real> length2;
903 mooseAssert(this_node,
"Node is NULL");
904 Point & p2 = *this_node;
906 if (
_front[i].size() >= 4)
912 mooseAssert(this_node,
"Node is NULL");
913 Point & p1 = *this_node;
915 node_id =
_front[i].back();
917 mooseAssert(this_node,
"Node is NULL");
918 Point & p4 = *this_node;
920 if (
_front[i].size() >= 4)
926 mooseAssert(this_node,
"Node is NULL");
927 Point & p3 = *this_node;
933 pl->enable_out_of_mesh_mode();
934 const Elem * elem = (*pl)(p1);
941 for (
const auto & belem : range)
944 std::vector<Point> vertices;
947 std::unique_ptr<const Elem> curr_side = elem->side_ptr(belem->_side);
948 for (
unsigned int j = 0;
j < curr_side->n_nodes(); ++
j)
950 const Node * node = curr_side->node_ptr(
j);
951 const Point & this_point = *node;
952 vertices.push_back(this_point);
958 length1.push_back((pt - p1) * (pt - p1));
963 length2.push_back((pt - p3) * (pt - p3));
967 if (length1.size() != 0 && do_inter1)
969 auto it1 = std::min_element(length1.begin(), length1.end());
970 Point inter1 = pint1[std::distance(length1.begin(), it1)];
973 Node * this_node = Node::build(inter1,
_cutter_mesh->n_nodes()).release();
977 "The cut mesh should have at least one element.");
980 auto it =
_front[i].begin();
987 if (length2.size() != 0 && do_inter2)
989 auto it2 = std::min_element(length2.begin(), length2.end());
990 Point inter2 = pint2[std::distance(length2.begin(), it2)];
993 Node * this_node = Node::build(inter2,
_cutter_mesh->n_nodes()).release();
998 auto it =
_front[i].begin();
999 unsigned int m =
_front[i].size();
1000 _front[i].insert(it + m, n);
1012 std::vector<std::vector<dof_id_type>> new_front(
_front.begin(),
_front.end());
1014 for (
unsigned int ifront = 0; ifront <
_front.size(); ++ifront)
1016 unsigned int i1 =
_front[ifront].size() - 1;
1018 i1 =
_front[ifront].size();
1020 for (
unsigned int i = i1; i >= 1; --i)
1022 unsigned int i2 = i;
1024 i2 = (i <=
_front[ifront].size() - 1 ? i : 0);
1033 std::array<Real, 3> x1;
1034 std::array<Real, 3> x2;
1037 mooseAssert(this_node,
"Node is NULL");
1038 Point & p1 = *this_node;
1040 mooseAssert(this_node,
"Node is NULL");
1041 Point & p2 = *this_node;
1043 for (
unsigned int j = 0;
j < 3; ++
j)
1049 for (
unsigned int j = 0;
j < n; ++
j)
1052 for (
unsigned int k = 0;
k < 3; ++
k)
1053 x(
k) = x2[
k] - (x2[
k] - x1[
k]) * (
j + 1) / (n + 1);
1055 Node * this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
1060 auto it = new_front[ifront].begin();
1061 new_front[ifront].insert(it + i,
id);
1081 mooseError(
"the crack front and the tracked crack front definition must match in terms of " 1094 "_active_boundary and _front should have the same size!");
1103 for (
unsigned int k = 0;
k <
_front.size(); ++
k)
1106 unsigned int n2 =
_front[
k].size();
1108 unsigned int i1 = 0;
1109 unsigned int i2 = 0;
1112 while (!(i1 == n1 - 1 && i2 == n2 - 1))
1114 std::vector<dof_id_type> elem;
1119 if (i1 != n1 - 1 && i2 != n2 - 1)
1143 else if (i1 == n1 - 1)
1153 else if (i2 == n2 - 1)
1163 Elem * new_elem = Elem::build(
TRI3).release();
1167 mooseAssert(
_cutter_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
1168 new_elem->set_node(i,
_cutter_mesh->node_ptr(elem[i]));
1186 std::vector<dof_id_type> full_front;
1190 for (
unsigned int i = 0; i < size1; ++i)
1197 full_front.insert(full_front.end(),
_front[i].begin(),
_front[i].end());
1200 unsigned int pos1 = std::distance(
_boundary.begin(), it1);
1202 unsigned int pos2 = std::distance(
_boundary.begin(), it2);
1205 full_front.insert(full_front.end(),
_boundary.begin() + pos1,
_boundary.begin() + pos2 + 1);
1209 full_front.insert(full_front.end(),
_boundary.begin(),
_boundary.begin() + pos2 + 1);
1216 const std::vector<Point>
1219 std::vector<Point> crack_front_points(number_crack_front_points);
1223 mooseError(
"number_points_from_provider does not match the number of nodes given in " 1224 "crack_front_nodes");
1225 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
1229 mooseAssert(this_node,
"Node is NULL");
1230 Point & this_point = *this_node;
1231 crack_front_points[i] = this_point;
1233 return crack_front_points;
1236 const std::vector<RealVectorValue>
1239 std::vector<RealVectorValue> crack_plane_normals(number_crack_front_points);
1242 std::unordered_map<dof_id_type, std::vector<dof_id_type>> node_to_elems_map;
1243 node_to_elems_map.clear();
1244 for (
const auto & elem :
_cutter_mesh->element_ptr_range())
1245 for (
auto & node : elem->node_ref_range())
1246 node_to_elems_map[node.id()].push_back(elem->id());
1249 std::unordered_map<dof_id_type, RealVectorValue> elem_to_normal_map;
1250 elem_to_normal_map.clear();
1251 for (
const auto & elem :
_cutter_mesh->element_ptr_range())
1253 Point & p1 = *elem->node_ptr(0);
1254 Point & p2 = *elem->node_ptr(1);
1255 Point & p3 = *elem->node_ptr(2);
1256 Plane elem_plane(p3, p2, p1);
1258 elem_to_normal_map[elem->id()] = normal;
1264 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
1267 std::vector<dof_id_type> elems = node_to_elems_map[id];
1268 unsigned int n_elem = elems.size();
1271 for (
unsigned int j = 0;
j <
n_elem; ++
j)
1272 normal_avr += elem_to_normal_map[elems[
j]];
1273 normal_avr = normal_avr /
n_elem;
1274 crack_plane_normals[i] = normal_avr;
1276 return crack_plane_normals;
1284 unsigned int ibnd = 0;
1288 std::vector<int> index(size_this_segment, -1);
1290 unsigned int i1 = n_inactive_nodes == 0 ? 0 : 1;
1291 unsigned int i2 = n_inactive_nodes == 0 ? size_this_segment : size_this_segment - 1;
1294 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.
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
static InputParameters validParams()
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.
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.
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
Simple base class for XFEM cutting objects that use a mesh to cut.
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()
bool isParamValid(const std::string &name) const
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::unique_ptr< MeshBase > _cutter_mesh
The xfem cutter mesh.
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::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.