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(
"REPORTER FUNCTION",
"FUNCTION");
35 "growth_increment_method", growthRate,
"choose from FUNCTION, REPORTER");
36 params.
addParam<FunctionName>(
"growth_direction_x",
37 "Function defining x-component of crack growth direction");
38 params.
addParam<FunctionName>(
"growth_direction_y",
39 "Function defining y-component of crack growth direction");
40 params.
addParam<FunctionName>(
"growth_direction_z",
41 "Function defining z-component of crack growth direction");
43 params.
addParam<VectorPostprocessorName>(
44 "ki_vectorpostprocessor",
"II_KI_1",
"Name of the VectorPostprocessor that computes K_I");
45 params.
addParam<VectorPostprocessorName>(
"kii_vectorpostprocessor",
47 "The name of the vectorpostprocessor that contains KII");
49 "The name of the Reporter that computes the growth increment");
50 params.
addParam<FunctionName>(
"growth_rate",
"Function defining crack growth rate");
52 "size_control", 0,
"Criterion for refining elements while growing the crack");
53 params.
addParam<
unsigned int>(
"n_step_growth", 0,
"Number of steps for crack growth");
62 _mesh(_subproblem.
mesh()),
64 _growth_increment_method(
66 _n_step_growth(getParam<unsigned
int>(
"n_step_growth")),
67 _is_mesh_modified(false),
68 _func_x(parameters.isParamValid(
"growth_direction_x") ? &getFunction(
"growth_direction_x")
70 _func_y(parameters.isParamValid(
"growth_direction_y") ? &getFunction(
"growth_direction_y")
72 _func_z(parameters.isParamValid(
"growth_direction_z") ? &getFunction(
"growth_direction_z")
74 _func_v(parameters.isParamValid(
"growth_rate") ? &getFunction(
"growth_rate") : nullptr),
76 ? &getVectorPostprocessorValue(
77 "ki_vectorpostprocessor",
78 getParam<VectorPostprocessorName>(
"ki_vectorpostprocessor"))
81 ? &getVectorPostprocessorValue(
82 "kii_vectorpostprocessor",
83 getParam<VectorPostprocessorName>(
"kii_vectorpostprocessor"))
85 _growth_inc_reporter((_growth_increment_method ==
GrowthRateEnum::REPORTER)
86 ? &getReporterValueByName<
std::vector<
Real>>(
95 paramError(
"size_control",
"Crack growth needs size control.");
101 mooseError(
"function is not specified for the function method that defines growth direction");
119 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
122 mooseError(
"The input cut mesh should include tri elements only!");
124 mooseError(
"The input cut mesh must be 2D elements only!");
176 std::vector<Xfem::CutEdge> & ,
177 std::vector<Xfem::CutNode> & )
const 179 mooseError(
"invalid method for 3D mesh cutting");
185 std::vector<Xfem::CutFace> & cut_faces)
const 190 bool elem_cut =
false;
192 if (elem->dim() != _elem_dim)
193 mooseError(
"The structural mesh to be cut by a surface mesh must be 3D!");
195 for (
unsigned int i = 0; i < elem->n_sides(); ++i)
198 std::unique_ptr<const Elem> curr_side = elem->side_ptr(i);
199 if (curr_side->dim() != 2)
200 mooseError(
"In cutElementByGeometry dimension of side must be 2, but it is ",
202 unsigned int n_edges = curr_side->n_sides();
204 std::vector<unsigned int> cut_edges;
205 std::vector<Real> cut_pos;
207 for (
unsigned int j = 0;
j < n_edges;
j++)
210 std::unique_ptr<const Elem> curr_edge = curr_side->side_ptr(
j);
211 if (curr_edge->type() !=
EDGE2)
212 mooseError(
"In cutElementByGeometry face edge must be EDGE2, but type is: ",
214 " base element type is: ",
216 const Node * node1 = curr_edge->node_ptr(0);
217 const Node * node2 = curr_edge->node_ptr(1);
219 for (
const auto & cut_elem : _cutter_mesh->element_ptr_range())
221 std::vector<Point> vertices;
223 for (
auto & node : cut_elem->node_ref_range())
225 Point & this_point = node;
226 vertices.push_back(this_point);
232 cut_edges.push_back(
j);
239 if (cut_edges.size() == 2)
248 cut_faces.push_back(mycut);
256 std::vector<Xfem::CutEdge> & )
const 258 mooseError(
"invalid method for 3D mesh cutting");
264 std::vector<Xfem::CutFace> & )
const 267 mooseError(
"cutFragmentByGeometry not yet implemented for 3D mesh cutting");
274 const std::vector<Point> & vertices,
277 bool has_intersection =
false;
279 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
280 Point point = vertices[0];
281 Point normal = elem_plane.unit_normal(point);
283 std::array<Real, 3> plane_point = {{point(0), point(1), point(2)}};
284 std::array<Real, 3> planenormal = {{normal(0), normal(1), normal(2)}};
285 std::array<Real, 3> edge_point1 = {{p1(0), p1(1), p1(2)}};
286 std::array<Real, 3> edge_point2 = {{p2(0), p2(1), p2(2)}};
287 std::array<Real, 3> cut_point = {{0.0, 0.0, 0.0}};
290 &plane_point[0], &planenormal[0], &edge_point1[0], &edge_point2[0], &cut_point[0]) == 1)
292 Point temp_p(cut_point[0], cut_point[1], cut_point[2]);
296 has_intersection =
true;
299 return has_intersection;
305 const std::vector<Point> & vertices,
308 bool has_intersection =
false;
310 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
311 Point point = vertices[0];
312 Point normal = elem_plane.unit_normal(point);
314 std::array<Real, 3> plane_point = {{point(0), point(1), point(2)}};
315 std::array<Real, 3> planenormal = {{normal(0), normal(1), normal(2)}};
316 std::array<Real, 3> p_begin = {{p1(0), p1(1), p1(2)}};
317 std::array<Real, 3> p_end = {{p2(0), p2(1), p2(2)}};
318 std::array<Real, 3> cut_point = {{0.0, 0.0, 0.0}};
321 &plane_point[0], &planenormal[0], &p_begin[0], &p_end[0], &cut_point[0]) == 1)
323 Point
p(cut_point[0], cut_point[1], cut_point[2]);
324 Real dotp = ((
p - p1) * (p2 - p1)) / ((p2 - p1) * (p2 - p1));
328 has_intersection =
true;
331 return has_intersection;
337 Real dotp1 = (p1 -
p) * (p2 - p1);
338 Real dotp2 = (p2 -
p) * (p2 - p1);
339 return (dotp1 * dotp2 <= 0.0);
345 const Point &
p)
const 349 return len_p1_p / full_len;
354 const Point &
p)
const 356 unsigned int n_node = vertices.size();
358 Plane elem_plane(vertices[0], vertices[1], vertices[2]);
359 Point normal = elem_plane.unit_normal(vertices[0]);
362 unsigned int counter = 0;
364 for (
unsigned int i = 0; i < n_node; ++i)
366 unsigned int iplus1 = (i < n_node - 1 ? i + 1 : 0);
367 Point middle2p =
p - 0.5 * (vertices[i] + vertices[iplus1]);
368 const Point side_tang = vertices[iplus1] - vertices[i];
369 Point side_norm = side_tang.cross(normal);
372 if (middle2p * side_norm <= 0.0)
375 if (counter == n_node)
383 auto boundary_node_ids = MeshTools::find_boundary_nodes(*
_cutter_mesh);
384 for (
auto it = boundary_node_ids.cbegin(); it != boundary_node_ids.cend(); it++)
387 std::vector<dof_id_type> neighbors;
397 std::vector<dof_id_type> corner_elem_id;
398 unsigned int counter = 0;
403 for (
const auto & cut_elem :
_cutter_mesh->element_ptr_range())
407 node_id[i] = cut_elem->node_ptr(i)->id();
411 if (is_node_on_boundary[0] && is_node_on_boundary[1] && is_node_on_boundary[2])
415 corner_elem_id.push_back(counter);
423 if (is_node_on_boundary[i] && is_node_on_boundary[(i + 1 <= 2) ? i + 1 : 0])
426 dof_id_type node2 = node_id[(i + 1 <= 2) ? i + 1 : 0];
428 std::swap(node1, node2);
433 std::swap(node1, node2);
446 for (
unsigned int i = 0; i < corner_elem_id.size(); ++i)
452 Elem * cut_elem = *elem_it;
456 bool is_edge_inside = 0;
459 dof_id_type node2 = cut_elem->node_ptr((
j + 1 <= 2) ?
j + 1 : 0)->id();
461 std::swap(node1, node2);
463 unsigned int counter = 0;
464 for (
const auto & cut_elem2 :
_cutter_mesh->element_ptr_range())
466 if (counter != corner_elem_id[i])
471 dof_id_type node4 = cut_elem2->node_ptr((
k + 1 <= 2) ?
k + 1 : 0)->id();
473 std::swap(node3, node4);
475 if (node1 == node3 && node2 == node4)
485 if (is_edge_inside == 0)
491 std::swap(node1, node2);
502 if ((*it)._id1 == node1 && (*it)._id2 == node2)
523 "_boundary_map does not have this key");
525 "_boundary_map does not have this key");
534 if (it->second.size() != 2)
536 "Boundary nodes in the cutter mesh must have exactly two neighbors; this one has: ",
550 "_boundary_map does not have this key");
561 else if (node4 == node1)
568 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 must be 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,
_cutter_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;
752 mooseAssert(
_ki_vpp->size() ==
_kii_vpp->size(),
"KI and KII VPPs must be the same size");
754 "the number of crack front nodes in the self-similar method should equal to the " 755 "size of VPP defined at the crack front");
757 "the number of crack front nodes should be the same in _crack_front_points and " 758 "_active_boundary[0]");
764 for (
unsigned int j = i1;
j < i2; ++
j)
775 Real sqrt_k = std::sqrt(ki * ki + 8 * kii * kii);
781 theta_m = 2 * std::atan((ki - sqrt_k) / (4 * kii));
782 theta_p = 2 * std::atan((ki + sqrt_k) / (4 * kii));
786 Real sigma_tt_m = ki * (3 * std::cos(theta_m / 2) + std::cos(3 * theta_m / 2)) +
787 kii * (-3 * std::sin(theta_m / 2) - 3 * std::sin(3 * theta_m / 2));
788 Real sigma_tt_p = ki * (3 * std::cos(theta_p / 2) + std::cos(3 * theta_p / 2)) +
789 kii * (-3 * std::sin(theta_p / 2) - 3 * std::sin(3 * theta_p / 2));
791 if (sigma_tt_m > sigma_tt_p)
802 dir_cfc(0) = std::cos(theta);
803 dir_cfc(1) = std::sin(theta);
811 mooseError(
"This growth_dir_method is not pre-defined!");
815 for (
unsigned int j = 0;
j < 3; ++
j)
830 Real length = std::sqrt(pt * pt);
847 std::vector<dof_id_type> temp;
858 for (
unsigned int j = i1;
j < i2; ++
j)
861 mooseAssert(this_node,
"Node is NULL");
862 Point & this_point = *this_node;
866 Real growth_increment = 0;
878 growth_increment = 0;
885 mooseError(
"This growth_increment_method is not pre-defined!");
889 for (
unsigned int k = 0;
k < 3; ++
k)
890 x(
k) = this_point(
k) + dir(
k) * growth_increment;
892 this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
926 for (
unsigned int i = 0; i <
_front.size(); ++i)
928 if (
_front[i].size() >= 2)
930 std::vector<Point> pint1;
931 std::vector<Point> pint2;
932 std::vector<Real> length1;
933 std::vector<Real> length2;
937 mooseAssert(this_node,
"Node is NULL");
938 Point & p2 = *this_node;
940 if (
_front[i].size() >= 4)
946 mooseAssert(this_node,
"Node is NULL");
947 Point & p1 = *this_node;
949 node_id =
_front[i].back();
951 mooseAssert(this_node,
"Node is NULL");
952 Point & p4 = *this_node;
954 if (
_front[i].size() >= 4)
960 mooseAssert(this_node,
"Node is NULL");
961 Point & p3 = *this_node;
967 pl->enable_out_of_mesh_mode();
968 const Elem * elem = (*pl)(p1);
975 for (
const auto & belem : range)
978 std::vector<Point> vertices;
981 std::unique_ptr<const Elem> curr_side = elem->side_ptr(belem->_side);
982 for (
unsigned int j = 0;
j < curr_side->n_nodes(); ++
j)
984 const Node * node = curr_side->node_ptr(
j);
985 const Point & this_point = *node;
986 vertices.push_back(this_point);
992 length1.push_back((pt - p1) * (pt - p1));
997 length2.push_back((pt - p3) * (pt - p3));
1001 if (length1.size() != 0 && do_inter1)
1003 auto it1 = std::min_element(length1.begin(), length1.end());
1004 Point inter1 = pint1[std::distance(length1.begin(), it1)];
1007 Node * this_node = Node::build(inter1,
_cutter_mesh->n_nodes()).release();
1010 mooseAssert(
_cutter_mesh->n_nodes() - 1 > 0,
"The cut mesh must be at least one element.");
1013 auto it =
_front[i].begin();
1020 if (length2.size() != 0 && do_inter2)
1022 auto it2 = std::min_element(length2.begin(), length2.end());
1023 Point inter2 = pint2[std::distance(length2.begin(), it2)];
1026 Node * this_node = Node::build(inter2,
_cutter_mesh->n_nodes()).release();
1031 auto it =
_front[i].begin();
1032 unsigned int m =
_front[i].size();
1033 _front[i].insert(it + m, n);
1045 std::vector<std::vector<dof_id_type>> new_front(
_front.begin(),
_front.end());
1047 for (
unsigned int ifront = 0; ifront <
_front.size(); ++ifront)
1049 unsigned int i1 =
_front[ifront].size() - 1;
1051 i1 =
_front[ifront].size();
1053 for (
unsigned int i = i1; i >= 1; --i)
1055 unsigned int i2 = i;
1057 i2 = (i <=
_front[ifront].size() - 1 ? i : 0);
1066 std::array<Real, 3> x1;
1067 std::array<Real, 3> x2;
1070 mooseAssert(this_node,
"Node is NULL");
1071 Point & p1 = *this_node;
1073 mooseAssert(this_node,
"Node is NULL");
1074 Point & p2 = *this_node;
1076 for (
unsigned int j = 0;
j < 3; ++
j)
1082 for (
unsigned int j = 0;
j < n; ++
j)
1085 for (
unsigned int k = 0;
k < 3; ++
k)
1086 x(
k) = x2[
k] - (x2[
k] - x1[
k]) * (
j + 1) / (n + 1);
1088 Node * this_node = Node::build(
x,
_cutter_mesh->n_nodes()).release();
1093 auto it = new_front[ifront].begin();
1094 new_front[ifront].insert(it + i,
id);
1114 mooseError(
"the crack front and the tracked crack front definition must match in terms of " 1115 "their end nodes\n _front[0][0]= " +
1118 "\n _tracked_crack_front_points.back()=" +
1131 "_active_boundary and _front must be the same size!");
1140 for (
unsigned int k = 0;
k <
_front.size(); ++
k)
1143 unsigned int n2 =
_front[
k].size();
1145 unsigned int i1 = 0;
1146 unsigned int i2 = 0;
1149 while (!(i1 == n1 - 1 && i2 == n2 - 1))
1151 std::vector<dof_id_type> elem;
1156 if (i1 != n1 - 1 && i2 != n2 - 1)
1180 else if (i1 == n1 - 1)
1190 else if (i2 == n2 - 1)
1200 Elem * new_elem = Elem::build(
TRI3).release();
1204 mooseAssert(
_cutter_mesh->node_ptr(elem[i]) !=
nullptr,
"Node is NULL");
1205 new_elem->set_node(i,
_cutter_mesh->node_ptr(elem[i]));
1223 std::vector<dof_id_type> full_front;
1227 for (
unsigned int i = 0; i < size1; ++i)
1234 full_front.insert(full_front.end(),
_front[i].begin(),
_front[i].end());
1237 unsigned int pos1 = std::distance(
_boundary.begin(), it1);
1239 unsigned int pos2 = std::distance(
_boundary.begin(), it2);
1242 full_front.insert(full_front.end(),
_boundary.begin() + pos1,
_boundary.begin() + pos2 + 1);
1246 full_front.insert(full_front.end(),
_boundary.begin(),
_boundary.begin() + pos2 + 1);
1253 const std::vector<Point>
1256 std::vector<Point> crack_front_points(number_crack_front_points);
1260 mooseError(
"Number of nodes in CrackFrontDefinition does not match the number of nodes in the " 1261 "cutter_mesh.\nCrackFrontDefinition nodes = " +
1265 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
1269 mooseAssert(this_node,
"Node is NULL");
1270 Point & this_point = *this_node;
1271 crack_front_points[i] = this_point;
1273 return crack_front_points;
1276 const std::vector<RealVectorValue>
1279 std::vector<RealVectorValue> crack_plane_normals(number_crack_front_points);
1282 std::unordered_map<dof_id_type, std::vector<dof_id_type>> node_to_elems_map;
1283 node_to_elems_map.clear();
1284 for (
const auto & elem :
_cutter_mesh->element_ptr_range())
1285 for (
auto & node : elem->node_ref_range())
1286 node_to_elems_map[node.id()].push_back(elem->id());
1289 std::unordered_map<dof_id_type, RealVectorValue> elem_to_normal_map;
1290 elem_to_normal_map.clear();
1291 for (
const auto & elem :
_cutter_mesh->element_ptr_range())
1293 Point & p1 = *elem->node_ptr(0);
1294 Point & p2 = *elem->node_ptr(1);
1295 Point & p3 = *elem->node_ptr(2);
1296 Plane elem_plane(p3, p2, p1);
1298 elem_to_normal_map[elem->id()] = normal;
1304 for (
unsigned int i = 0; i < number_crack_front_points; ++i)
1307 std::vector<dof_id_type> elems = node_to_elems_map[id];
1308 unsigned int n_elem = elems.size();
1311 for (
unsigned int j = 0;
j <
n_elem; ++
j)
1312 normal_avr += elem_to_normal_map[elems[
j]];
1313 normal_avr = normal_avr /
n_elem;
1314 crack_plane_normals[i] = normal_avr;
1316 return crack_plane_normals;
1324 unsigned int ibnd = 0;
1328 std::vector<int> index(size_this_segment, -1);
1330 unsigned int i1 = n_inactive_nodes == 0 ? 0 : 1;
1331 unsigned int i2 = n_inactive_nodes == 0 ? size_this_segment : size_this_segment - 1;
1334 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...
Real _size_control
Used for cutter mesh refinement and front advancement.
T & getUserObject(const std::string &name, unsigned int tid=0) const
void paramError(const std::string ¶m, Args... args) const
void findBoundaryNodes()
Find boundary nodes of the cutter mesh This is a simple algorithm simply based on the added angle = 3...
void mooseError(Args &&... args)
const unsigned int _cut_elem_nnode
The cutter mesh has triangluar elements only.
static constexpr Real TOLERANCE
const ReporterMode REPORTER_MODE_ROOT
void findActiveBoundaryNodes()
Find all active boundary nodes in the cutter mesh Find boundary nodes that will grow; nodes outside o...
std::vector< int > getFrontPointsIndex() const
Get crack front points in the active segment -1 means inactive; positive is the point's index in the ...
unsigned int _n_step_growth
Number of steps to grow the mesh.
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.
bool _cfd
is it using the crack_front_definition
const GrowthRateEnum _growth_increment_method
The growth increment 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
virtual unsigned int getNumberOfCrackFrontPoints() const override
Return the total number of crack front points.
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.
const std::vector< Real > *const _ki_vpp
Pointer to fracture integral ki if available.
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.
FEProblemBase & _fe_problem
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
unsigned int _num_crack_front_points
Total number of crack front points in the mesh cutter.
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...
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.
std::string stringify(const T &t)
const std::vector< Real > *const _kii_vpp
Pointer to fracture integral kii if available.
const unsigned int _cut_elem_dim
void initializeCrackFrontNodes()
Determine initial crack front nodes from cutter mesh.
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 ...
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.
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
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
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.
void refineBoundary()
If boundary nodes are too sparse, add nodes in between.
std::vector< std::vector< Point > > _active_direction
Growth direction for active boundaries.
const std::vector< Real > *const _growth_inc_reporter
Pointer to reporter with growth increment if available.
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.