33 #include "libmesh/mesh_communication.h" 34 #include "libmesh/partitioner.h" 39 _debug_output_level(1),
40 _min_weight_multiplier(0.0)
42 #ifndef LIBMESH_ENABLE_UNIQUE_ID 43 mooseError(
"MOOSE requires unique ids to be enabled in libmesh (configure with " 44 "--enable-unique-id) to use XFEM!");
51 for (std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
_cut_elem_map.begin();
69 std::vector<Point> & crack_front_points)
71 elem_id_crack_tip.clear();
72 crack_front_points.clear();
75 unsigned int crack_tip_index = 0;
78 std::map<unsigned int, const Elem *> elem_id_map;
81 for (std::map<
const Elem *, std::vector<Point>>::iterator mit1 =
86 unsigned int elem_id = mit1->first->id();
87 if (elem_id == std::numeric_limits<unsigned int>::max())
89 elem_id_map[m] = mit1->first;
93 elem_id_map[elem_id] = mit1->first;
96 for (std::map<unsigned int, const Elem *>::iterator mit1 = elem_id_map.begin();
97 mit1 != elem_id_map.end();
100 const Elem * elem = mit1->second;
101 std::map<const Elem *, std::vector<Point>>::iterator mit2 =
105 elem_id_crack_tip[crack_tip_index] = mit2->first;
106 crack_front_points[crack_tip_index] =
116 Elem * elem =
_mesh->elem_ptr(elem_id);
117 std::map<const Elem *, RealVectorValue>::iterator mit;
120 mooseError(
" ERROR: element ", elem->id(),
" already marked for crack growth.");
128 Elem * elem =
_mesh->elem_ptr(elem_id);
129 std::map<const Elem *, unsigned int>::iterator mit;
132 mooseError(
" ERROR: side of element ", elem->id(),
" already marked for crack initiation.");
141 Elem * elem =
_mesh->elem_ptr(elem_id);
142 std::set<const Elem *>::iterator mit;
146 " ERROR: element ", elem->id(),
" already marked for fragment-secondary crack initiation.");
162 const unsigned int interface_id)
164 Elem * elem =
_mesh->elem_ptr(elem_id);
172 const unsigned int interface_id)
174 Elem * elem =
_mesh->elem_ptr(elem_id);
191 std::set<EFAElement *>::iterator sit;
192 for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
194 if (
_mesh->mesh_dimension() == 2)
200 Point origin(0, 0, 0);
201 Point direction(0, 0, 0);
203 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
215 std::vector<Point> tip_data;
216 tip_data.push_back(origin);
217 tip_data.push_back(direction);
218 const Elem * elem =
_mesh->elem_ptr((*sit)->id());
220 std::pair<
const Elem *, std::vector<Point>>(elem, tip_data));
228 bool mesh_changed =
false;
237 _mesh->update_parallel_id_counts();
238 MeshCommunication().make_elems_parallel_consistent(*
_mesh);
239 MeshCommunication().make_nodes_parallel_consistent(*
_mesh);
242 _mesh->allow_renumbering(
false);
243 _mesh->skip_partitioning(
true);
244 _mesh->prepare_for_use();
264 const std::vector<std::shared_ptr<NonlinearSystemBase>> & nl,
268 mooseError(
"Use of XFEM with distributed mesh is not yet supported");
270 for (
const auto & elem :
_mesh->active_element_ptr_range())
271 if (elem->level() > 0)
272 mooseError(
"XFEM does not currently support mesh adaptivity or adaptively refined meshes");
274 bool mesh_changed =
false;
293 _mesh->allow_renumbering(
false);
294 _mesh->skip_partitioning(
true);
295 _mesh->prepare_for_use();
316 mooseError(
"XFEM does not currently support multiple nonlinear systems");
318 nls[0]->serializeSolution();
331 current_solution.
close();
332 old_solution.
close();
333 older_solution.
close();
334 current_aux_solution.
close();
335 old_aux_solution.
close();
336 older_aux_solution.
close();
348 for (
auto & elem :
_mesh->element_ptr_range())
350 std::vector<unsigned int> quad;
351 for (
unsigned int i = 0; i < elem->n_nodes(); ++i)
352 quad.push_back(elem->node_id(i));
354 if (
_mesh->mesh_dimension() == 2)
356 else if (
_mesh->mesh_dimension() == 3)
363 for (
auto & elem :
_mesh->element_ptr_range())
365 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
_cut_elem_map.find(elem->unique_id());
384 bool marked_sides =
false;
385 if (
_mesh->mesh_dimension() == 2)
390 else if (
_mesh->mesh_dimension() == 3)
401 bool marked_edges =
false;
402 bool marked_nodes =
false;
406 for (
const auto & gmei : gme.second)
410 for (
unsigned int i = 0; i < gmei._elem_cut_edges.size(); ++i)
413 gmei._elem_cut_edges[i]._host_side_id))
416 gmei._elem_cut_edges[i]._host_side_id,
417 gmei._elem_cut_edges[i]._distance);
422 for (
unsigned int i = 0; i < gmei._elem_cut_nodes.size(); ++i)
428 for (
unsigned int i = 0; i < gmei._frag_cut_edges.size();
432 gmei._frag_cut_edges[i]._host_side_id))
435 gmei._frag_cut_edges[i]._host_side_id,
436 gmei._frag_cut_edges[i]._distance))
447 return marked_edges || marked_nodes;
455 Point crack_tip_origin,
456 Point crack_tip_direction,
457 Real & distance_keep,
458 unsigned int & edge_id_keep,
461 std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
462 Point edge1(0.0, 0.0, 0.0);
463 Point edge2(0.0, 0.0, 0.0);
464 Point left_angle(0.0, 0.0, 0.0);
465 Point right_angle(0.0, 0.0, 0.0);
466 Point left_angle_normal(0.0, 0.0, 0.0);
467 Point right_angle_normal(0.0, 0.0, 0.0);
468 Point crack_direction_normal(0.0, 0.0, 0.0);
469 Point edge1_to_tip(0.0, 0.0, 0.0);
470 Point edge2_to_tip(0.0, 0.0, 0.0);
471 Point edge1_to_tip_normal(0.0, 0.0, 0.0);
472 Point edge2_to_tip_normal(0.0, 0.0, 0.0);
474 Real cos_45 = std::cos(45.0 / 180.0 * 3.14159);
475 Real sin_45 = std::sin(45.0 / 180.0 * 3.14159);
477 left_angle(0) = cos_45 * crack_tip_direction(0) - sin_45 * crack_tip_direction(1);
478 left_angle(1) = sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
480 right_angle(0) = cos_45 * crack_tip_direction(0) + sin_45 * crack_tip_direction(1);
481 right_angle(1) = -sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
483 left_angle_normal(0) = -left_angle(1);
484 left_angle_normal(1) = left_angle(0);
486 right_angle_normal(0) = -right_angle(1);
487 right_angle_normal(1) = right_angle(0);
489 crack_direction_normal(0) = -crack_tip_direction(1);
490 crack_direction_normal(1) = crack_tip_direction(0);
492 Real angle_min = 0.0;
496 for (
unsigned int i = 0; i <
nsides; ++i)
503 edge1_to_tip = (edge_ends[0] * 0.95 + edge_ends[1] * 0.05) - crack_tip_origin;
504 edge2_to_tip = (edge_ends[0] * 0.05 + edge_ends[1] * 0.95) - crack_tip_origin;
506 edge1_to_tip /=
pow(edge1_to_tip.norm_sq(), 0.5);
507 edge2_to_tip /=
pow(edge2_to_tip.norm_sq(), 0.5);
509 edge1_to_tip_normal(0) = -edge1_to_tip(1);
510 edge1_to_tip_normal(1) = edge1_to_tip(0);
512 edge2_to_tip_normal(0) = -edge2_to_tip(1);
513 edge2_to_tip_normal(1) = edge2_to_tip(0);
515 Real angle_edge1_normal = edge1_to_tip_normal * normal;
516 Real angle_edge2_normal = edge2_to_tip_normal * normal;
518 if (std::abs(angle_edge1_normal) > std::abs(angle_min) &&
519 (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
522 distance_keep = 0.05;
523 normal_keep = edge1_to_tip_normal;
524 angle_min = angle_edge1_normal;
526 else if (std::abs(angle_edge2_normal) > std::abs(angle_min) &&
527 (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
530 distance_keep = 0.95;
531 normal_keep = edge2_to_tip_normal;
532 angle_min = angle_edge2_normal;
536 crack_tip_origin, left_angle_normal, edge_ends[0], edge_ends[1],
distance) &&
539 if (std::abs(left_angle_normal * normal) > std::abs(angle_min) &&
540 (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
544 normal_keep = left_angle_normal;
545 angle_min = left_angle_normal * normal;
549 crack_tip_origin, right_angle_normal, edge_ends[0], edge_ends[1],
distance) &&
552 if (std::abs(right_angle_normal * normal) > std::abs(angle_min) &&
553 (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
557 normal_keep = right_angle_normal;
558 angle_min = right_angle_normal * normal;
562 crack_direction_normal,
568 if (std::abs(crack_direction_normal * normal) > std::abs(angle_min) &&
569 (crack_tip_direction * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
573 normal_keep = crack_direction_normal;
574 angle_min = crack_direction_normal * normal;
581 if ((distance_keep - 0.05) < 0.0)
583 distance_keep = 0.05;
585 else if ((distance_keep - 0.95) > 0.0)
587 distance_keep = 0.95;
594 bool marked_edges =
false;
595 for (std::map<const Elem *, RealVectorValue>::iterator pmeit =
_state_marked_elems.begin();
599 const Elem * elem = pmeit->first;
604 if (volfrac_elem < 0.25)
613 unsigned int orig_cut_side_id = std::numeric_limits<unsigned int>::max();
614 Real orig_cut_distance = -1.0;
619 Point crack_tip_origin(0, 0, 0);
620 Point crack_tip_direction(0, 0, 0);
625 if (orig_cut_side_id <
nsides)
627 orig_edge = CEMElem->
getEdge(orig_cut_side_id);
631 mooseError(
"element ", elem->id(),
" has no valid crack-tip edge");
634 std::map<const Elem *, std::vector<Point>>::iterator ecodm =
638 crack_tip_origin = (ecodm->second)[0];
639 crack_tip_direction = (ecodm->second)[1];
642 mooseError(
"element ", elem->id(),
" cannot find its crack tip origin and direction.");
646 std::map<const Elem *, unsigned int>::iterator mit1;
648 std::set<const Elem *>::iterator mit2;
653 orig_cut_side_id = mit1->second;
657 orig_cut_distance = 0.5;
659 orig_edge = CEMElem->
getEdge(orig_cut_side_id);
662 Point elem_center(0.0, 0.0, 0.0);
664 for (
unsigned int i = 0; i <
nsides; ++i)
669 elem_center /=
nsides * 2.0;
673 crack_tip_origin = edge_center;
674 crack_tip_direction = elem_center - edge_center;
675 crack_tip_direction /=
pow(crack_tip_direction.norm_sq(), 0.5);
685 " flagged for a secondary crack, but has ",
689 if (interior_edge_id.size() == 1)
690 orig_cut_side_id = interior_edge_id[0];
694 orig_cut_distance = 0.5;
698 Point elem_center(0.0, 0.0, 0.0);
701 for (
unsigned int i = 0; i < nsides_frag; ++i)
708 elem_center /= nsides_frag * 2.0;
712 crack_tip_origin = edge_center;
713 crack_tip_direction = elem_center - edge_center;
714 crack_tip_direction /=
pow(crack_tip_direction.norm_sq(), 0.5);
719 " flagged for state-based growth, but has no edge intersections");
722 Point cut_origin(0.0, 0.0, 0.0);
726 mooseError(
"element ", elem->id(),
" does not have valid orig_node");
729 std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
730 Point edge1(0.0, 0.0, 0.0);
731 Point edge2(0.0, 0.0, 0.0);
732 Point cut_edge_point(0.0, 0.0, 0.0);
733 bool find_compatible_direction =
false;
734 unsigned int edge_id_keep = 0;
735 Real distance_keep = 0.0;
736 Point normal_keep(0.0, 0.0, 0.0);
738 bool edge_cut =
false;
740 for (
unsigned int i = 0; i <
nsides; ++i)
747 crack_tip_origin, normal, edge_ends[0], edge_ends[1],
distance) &&
753 normal_keep = normal;
760 Point between_two_cuts = (cut_edge_point - crack_tip_origin);
761 between_two_cuts /=
pow(between_two_cuts.norm_sq(), 0.5);
762 Real angle_between_two_cuts = between_two_cuts * crack_tip_direction;
764 if (angle_between_two_cuts > std::cos(45.0 / 180.0 * 3.14159))
765 find_compatible_direction =
true;
767 if (!find_compatible_direction && edge_cut)
784 Point growth_direction(0.0, 0.0, 0.0);
786 growth_direction(0) = -normal_keep(1);
787 growth_direction(1) = normal_keep(0);
789 if (growth_direction * crack_tip_direction < 1.0e-10)
790 growth_direction *= (-1.0);
792 Real x0 = crack_tip_origin(0);
793 Real y0 = crack_tip_origin(1);
799 for (
const auto & elem :
_mesh->element_ptr_range())
801 std::vector<CutEdgeForCrackGrowthIncr> elem_cut_edges;
811 for (
unsigned int i = 0; i < elem_cut_edges.size(); ++i)
814 elem_cut_edges[i]._host_side_id))
817 elem->id(), elem_cut_edges[i]._host_side_id, elem_cut_edges[i]._distance);
836 crack_tip_origin, normal, edge_ends[0], edge_ends[1],
distance) &&
858 bool marked_faces =
false;
862 for (
const auto & gmei : gme.second)
866 for (
unsigned int i = 0; i < gmei._elem_cut_faces.size(); ++i)
868 if (!EFAElem->
isFacePhantom(gmei._elem_cut_faces[i]._face_id))
871 gmei._elem_cut_faces[i]._face_id,
872 gmei._elem_cut_faces[i]._face_edge,
873 gmei._elem_cut_faces[i]._position);
878 for (
unsigned int i = 0; i < gmei._frag_cut_faces.size();
884 gmei._frag_cut_faces[i]._face_id,
885 gmei._frag_cut_faces[i]._face_edge,
886 gmei._frag_cut_faces[i]._position);
899 bool marked_faces =
false;
906 Point cut_origin,
RealVectorValue cut_normal, Point & edge_p1, Point & edge_p2, Real & dist)
909 bool does_intersect =
false;
910 Point origin2p1 = edge_p1 - cut_origin;
911 Real plane2p1 = cut_normal(0) * origin2p1(0) + cut_normal(1) * origin2p1(1);
912 Point origin2p2 = edge_p2 - cut_origin;
913 Real plane2p2 = cut_normal(0) * origin2p2(0) + cut_normal(1) * origin2p2(1);
915 if (plane2p1 * plane2p2 < 0.0)
917 dist = -plane2p1 / (plane2p2 - plane2p1);
918 does_intersect =
true;
920 return does_intersect;
926 bool mesh_changed =
false;
928 std::set<Node *> nodes_to_delete;
929 std::set<Node *> nodes_to_delete_displaced;
930 std::set<unsigned int> cutelems_to_delete;
931 unsigned int deleted_elem_count = 0;
932 std::vector<std::string> healed_geometric_cuts;
941 Elem * elem1 =
const_cast<Elem *
>(it.first);
942 Elem * elem2 =
const_cast<Elem *
>(it.second);
944 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
950 cutelems_to_delete.insert(elem1->unique_id());
952 for (
unsigned int in = 0; in < elem1->n_nodes(); ++in)
954 Node * e1node = elem1->node_ptr(in);
955 Node * e2node = elem2->node_ptr(in);
959 elem1->set_node(in, e2node);
960 nodes_to_delete.insert(e1node);
962 else if (e1node != e2node)
963 nodes_to_delete.insert(e2node);
967 mooseError(
"Could not find XFEMCutElem for element to be kept in healing");
972 std::vector<const Elem *> healed_elems = {elem1, elem2};
978 for (
auto e : healed_elems)
979 if (elem1->processor_id() ==
_mesh->processor_id() &&
980 e->processor_id() ==
_mesh->processor_id())
988 if (parent_gcsid == gcsid)
997 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
1003 for (
unsigned int in = 0; in < elem1_displaced->n_nodes(); ++in)
1005 Node * e1node_displaced = elem1_displaced->node_ptr(in);
1006 Node * e2node_displaced = elem2_displaced->node_ptr(in);
1008 e1node_displaced != e2node_displaced)
1010 elem1_displaced->set_node(in, e2node_displaced);
1011 nodes_to_delete_displaced.insert(e1node_displaced);
1013 else if (e1node_displaced != e2node_displaced)
1014 nodes_to_delete_displaced.insert(e2node_displaced);
1018 mooseError(
"Could not find XFEMCutElem for element to be kept in healing");
1020 elem2_displaced->nullify_neighbors();
1029 cutelems_to_delete.insert(elem2->unique_id());
1030 elem2->nullify_neighbors();
1031 _mesh->get_boundary_info().remove(elem2);
1032 unsigned int deleted_elem_id = elem2->id();
1033 _mesh->delete_elem(elem2);
1036 if (deleted_elem_count == 0)
1038 _console <<
"XFEM healing deleted element: " << deleted_elem_id << std::endl;
1040 ++deleted_elem_count;
1041 mesh_changed =
true;
1046 for (
auto & sit : nodes_to_delete)
1048 Node * node_to_delete = sit;
1049 dof_id_type deleted_node_id = node_to_delete->id();
1050 _mesh->get_boundary_info().remove(node_to_delete);
1051 _mesh->delete_node(node_to_delete);
1053 _console <<
"XFEM healing deleted node: " << deleted_node_id << std::endl;
1058 for (
auto & sit : nodes_to_delete_displaced)
1060 Node * node_to_delete_displaced = sit;
1061 _displaced_mesh->get_boundary_info().remove(node_to_delete_displaced);
1066 for (
auto & ced : cutelems_to_delete)
1094 _console <<
"\nXFEM mesh healing complete\n";
1095 _console <<
"Names of healed geometric cut objects: ";
1096 for (
auto geomcut : healed_geometric_cuts)
1099 _console <<
"# deleted nodes: " << nodes_to_delete.size() <<
"\n";
1100 _console <<
"# deleted elements: " << deleted_elem_count <<
"\n";
1104 return mesh_changed;
1111 if (nls.size() != 1)
1112 mooseError(
"XFEM does not currently support multiple nonlinear systems");
1114 std::map<unsigned int, Node *> efa_id_to_new_node;
1115 std::map<unsigned int, Node *> efa_id_to_new_node2;
1116 std::map<unsigned int, Elem *> efa_id_to_new_elem;
1129 _console <<
"\nXFEM Element fragment algorithm mesh prior to cutting:\n";
1138 _console <<
"\nXFEM Element fragment algorithm mesh after cutting:\n";
1147 bool mesh_changed = (new_nodes.size() + new_elements.size() + delete_elements.size() > 0);
1152 nls[0]->serializeSolution();
1164 std::map<Node *, Node *> new_nodes_to_parents;
1167 for (
unsigned int i = 0; i < new_nodes.size(); ++i)
1169 unsigned int new_node_id = new_nodes[i]->id();
1170 unsigned int parent_id = new_nodes[i]->parent()->id();
1172 Node * parent_node =
_mesh->node_ptr(parent_id);
1173 Node * new_node = Node::build(*parent_node,
_mesh->max_node_id()).release();
1174 _mesh->add_node(new_node);
1176 new_nodes_to_parents[new_node] = parent_node;
1178 new_node->set_n_systems(parent_node->n_systems());
1179 efa_id_to_new_node.insert(std::make_pair(new_node_id, new_node));
1181 _console <<
"XFEM added new node: " << new_node->id() << std::endl;
1185 Node * new_node2 = Node::build(*parent_node2,
_displaced_mesh->max_node_id()).release();
1188 new_node2->set_n_systems(parent_node2->n_systems());
1189 efa_id_to_new_node2.insert(std::make_pair(new_node_id, new_node2));
1194 std::map<unsigned int, std::vector<const Elem *>> temporary_parent_children_map;
1196 std::vector<boundary_id_type> parent_boundary_ids;
1198 for (
unsigned int i = 0; i < new_elements.size(); ++i)
1200 unsigned int parent_id = new_elements[i]->getParent()->id();
1201 unsigned int efa_child_id = new_elements[i]->id();
1203 Elem * parent_elem =
_mesh->elem_ptr(parent_id);
1204 Elem * libmesh_elem = Elem::build(parent_elem->type()).release();
1210 if (parent_elem == it.first)
1211 it.first = libmesh_elem;
1212 else if (parent_elem == it.second)
1213 it.second = libmesh_elem;
1218 if (new_elements[i]->getParent()->numChildren() > 1)
1219 temporary_parent_children_map[parent_elem->id()].push_back(libmesh_elem);
1221 Elem * parent_elem2 =
nullptr;
1222 Elem * libmesh_elem2 =
nullptr;
1226 libmesh_elem2 = Elem::build(parent_elem2->type()).release();
1232 if (parent_elem2 == it.first)
1233 it.first = libmesh_elem2;
1234 else if (parent_elem2 == it.second)
1235 it.second = libmesh_elem2;
1240 for (
unsigned int j = 0;
j < new_elements[i]->numNodes(); ++
j)
1242 unsigned int node_id = new_elements[i]->getNode(
j)->id();
1243 Node * libmesh_node;
1245 std::map<unsigned int, Node *>::iterator nit = efa_id_to_new_node.find(node_id);
1246 if (nit != efa_id_to_new_node.end())
1247 libmesh_node = nit->second;
1249 libmesh_node =
_mesh->node_ptr(node_id);
1251 if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1252 libmesh_node->processor_id() = parent_elem->processor_id();
1254 libmesh_elem->set_node(
j, libmesh_node);
1257 if (parent_elem->is_semilocal(
_mesh->processor_id()))
1259 Node * solution_node = libmesh_node;
1260 if (new_nodes_to_parents.find(libmesh_node) != new_nodes_to_parents.end())
1261 solution_node = new_nodes_to_parents[libmesh_node];
1264 (libmesh_node->processor_id() ==
_mesh->processor_id()))
1277 current_aux_solution,
1279 older_aux_solution);
1283 Node * parent_node = parent_elem->node_ptr(
j);
1284 _mesh->get_boundary_info().boundary_ids(parent_node, parent_boundary_ids);
1285 _mesh->get_boundary_info().add_node(libmesh_node, parent_boundary_ids);
1289 std::map<unsigned int, Node *>::iterator nit2 = efa_id_to_new_node2.find(node_id);
1290 if (nit2 != efa_id_to_new_node2.end())
1291 libmesh_node = nit2->second;
1295 if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1296 libmesh_node->processor_id() = parent_elem2->processor_id();
1298 libmesh_elem2->set_node(
j, libmesh_node);
1300 parent_node = parent_elem2->node_ptr(
j);
1301 _displaced_mesh->get_boundary_info().boundary_ids(parent_node, parent_boundary_ids);
1302 _displaced_mesh->get_boundary_info().add_node(libmesh_node, parent_boundary_ids);
1306 libmesh_elem->set_p_level(parent_elem->p_level());
1307 libmesh_elem->set_p_refinement_flag(parent_elem->p_refinement_flag());
1308 _mesh->add_elem(libmesh_elem);
1309 libmesh_elem->set_n_systems(parent_elem->n_systems());
1310 libmesh_elem->subdomain_id() = parent_elem->subdomain_id();
1311 libmesh_elem->processor_id() = parent_elem->processor_id();
1315 std::map<const Elem *, std::vector<Point>>::iterator mit =
1325 _console <<
"XFEM added new element: " << libmesh_elem->id() << std::endl;
1328 if (
_mesh->mesh_dimension() == 2)
1331 if (!new_efa_elem2d)
1332 mooseError(
"EFAelem is not of EFAelement2D type");
1336 libmesh_elem->n_sides());
1338 else if (
_mesh->mesh_dimension() == 3)
1341 if (!new_efa_elem3d)
1342 mooseError(
"EFAelem is not of EFAelement3D type");
1346 libmesh_elem->n_sides());
1348 _cut_elem_map.insert(std::pair<unique_id_type, XFEMCutElem *>(libmesh_elem->unique_id(), xfce));
1349 efa_id_to_new_elem.insert(std::make_pair(efa_child_id, libmesh_elem));
1353 libmesh_elem2->set_p_level(parent_elem2->p_level());
1354 libmesh_elem2->set_p_refinement_flag(parent_elem2->p_refinement_flag());
1356 libmesh_elem2->set_n_systems(parent_elem2->n_systems());
1357 libmesh_elem2->subdomain_id() = parent_elem2->subdomain_id();
1358 libmesh_elem2->processor_id() = parent_elem2->processor_id();
1361 unsigned int n_sides = parent_elem->n_sides();
1362 for (
unsigned int side = 0; side < n_sides; ++side)
1364 _mesh->get_boundary_info().boundary_ids(parent_elem, side, parent_boundary_ids);
1365 _mesh->get_boundary_info().add_side(libmesh_elem, side, parent_boundary_ids);
1369 n_sides = parent_elem2->n_sides();
1370 for (
unsigned int side = 0; side < n_sides; ++side)
1372 _displaced_mesh->get_boundary_info().boundary_ids(parent_elem2, side, parent_boundary_ids);
1373 _displaced_mesh->get_boundary_info().add_side(libmesh_elem2, side, parent_boundary_ids);
1377 unsigned int n_edges = parent_elem->n_edges();
1380 _mesh->get_boundary_info().edge_boundary_ids(parent_elem,
edge, parent_boundary_ids);
1381 _mesh->get_boundary_info().add_edge(libmesh_elem,
edge, parent_boundary_ids);
1385 n_edges = parent_elem2->n_edges();
1389 parent_elem2,
edge, parent_boundary_ids);
1395 if (parent_elem->processor_id() ==
_mesh->processor_id())
1397 if (
_material_data[0]->getMaterialPropertyStorage().hasStatefulProperties())
1401 for (
unsigned int side = 0; side < parent_elem->n_sides(); ++side)
1403 _mesh->get_boundary_info().boundary_ids(parent_elem, side, parent_boundary_ids);
1404 std::vector<boundary_id_type>::iterator it_bd = parent_boundary_ids.begin();
1405 for (; it_bd != parent_boundary_ids.end(); ++it_bd)
1425 if (cei.
match(old_cei.second))
1429 _console <<
"XFEM set material properties for element: " << libmesh_elem->id()
1447 current_aux_solution,
1449 older_aux_solution);
1454 for (std::size_t i = 0; i < delete_elements.size(); ++i)
1456 Elem * elem_to_delete =
_mesh->elem_ptr(delete_elements[i]->
id());
1459 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
1463 delete cemit->second;
1471 elem_to_delete->nullify_neighbors();
1472 _mesh->get_boundary_info().remove(elem_to_delete);
1473 unsigned int deleted_elem_id = elem_to_delete->id();
1474 _mesh->delete_elem(elem_to_delete);
1476 _console <<
"XFEM deleted element: " << deleted_elem_id << std::endl;
1480 Elem * elem_to_delete2 =
_displaced_mesh->elem_ptr(delete_elements[i]->
id());
1481 elem_to_delete2->nullify_neighbors();
1487 for (std::map<
unsigned int, std::vector<const Elem *>>::iterator it =
1488 temporary_parent_children_map.begin();
1489 it != temporary_parent_children_map.end();
1492 std::vector<const Elem *> & sibling_elem_vec = it->second;
1499 if (it->first == elem_id)
1501 std::make_pair(sibling_elem_vec[0], sibling_elem_vec[1]));
1514 std::make_pair(elem, elem_pair));
1520 temporary_parent_children_map.clear();
1528 std::set<EFAElement *>::const_iterator sit;
1529 for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
1531 unsigned int eid = (*sit)->id();
1532 Elem * crack_tip_elem;
1533 std::map<unsigned int, Elem *>::iterator eit = efa_id_to_new_elem.find(eid);
1534 if (eit != efa_id_to_new_elem.end())
1535 crack_tip_elem = eit->second;
1537 crack_tip_elem =
_mesh->elem_ptr(eid);
1546 if ((*sit)->getParent() !=
nullptr)
1548 if (
_mesh->mesh_dimension() == 2)
1552 mooseError(
"EFAelem is not of EFAelement2D type");
1554 for (
unsigned int edge_id = 0; edge_id < efa_elem2d->
numEdges(); ++edge_id)
1556 for (
unsigned int en_iter = 0; en_iter < efa_elem2d->
numEdgeNeighbors(edge_id);
1560 if (edge_neighbor !=
nullptr && edge_neighbor->
id() == mie)
1565 else if (
_mesh->mesh_dimension() == 3)
1569 mooseError(
"EFAelem is not of EFAelement3D type");
1571 for (
unsigned int face_id = 0; face_id < efa_elem3d->
numFaces(); ++face_id)
1573 for (
unsigned int fn_iter = 0; fn_iter < efa_elem3d->
numFaceNeighbors(face_id);
1577 if (face_neighbor !=
nullptr && face_neighbor->
id() == mie)
1590 _console <<
"\nXFEM mesh cutting with element fragment algorithm complete\n";
1591 _console <<
"# new nodes: " << new_nodes.size() <<
"\n";
1592 _console <<
"# new elements: " << new_elements.size() <<
"\n";
1593 _console <<
"# deleted elements: " << delete_elements.size() <<
"\n";
1599 return mesh_changed;
1606 MeshBase * displaced_mesh)
const 1608 Point node_coor(0.0, 0.0, 0.0);
1609 std::vector<EFANode *> master_nodes;
1610 std::vector<Point> master_points;
1611 std::vector<double> master_weights;
1613 CEMElem->
getMasterInfo(CEMnode, master_nodes, master_weights);
1614 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1619 const Node * node = elem->node_ptr(local_node_id);
1621 node = displaced_mesh->node_ptr(node->id());
1622 Point node_p((*node)(0), (*node)(1), (*node)(2));
1623 master_points.push_back(node_p);
1626 mooseError(
"master nodes must be permanent");
1628 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1629 node_coor += master_weights[i] * master_points[i];
1637 Real phys_volfrac = 1.0;
1638 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1651 return phys_volfrac;
1657 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1675 unsigned int plane_id)
const 1678 Point planedata(0.0, 0.0, 0.0);
1679 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1687 if ((
unsigned int)quantity < 3)
1689 unsigned int index = (
unsigned int)quantity;
1691 comp = planedata(index);
1693 else if ((
unsigned int)quantity < 6)
1695 unsigned int index = (
unsigned int)quantity - 3;
1697 comp = planedata(index);
1700 mooseError(
"In get_cut_plane index out of range");
1737 std::vector<std::vector<Point>> & frag_faces,
1738 bool displaced_mesh)
const 1740 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1759 mooseError(
"EFAelem is not of EFAelement2D type");
1771 mooseError(
"EFAelem is not of EFAelement3D type");
1779 std::vector<std::vector<Point>> & frag_edges)
const 1786 mooseError(
"element ", elem->id(),
" has more than one fragment at this point");
1789 std::vector<Point> p_line(2, Point(0.0, 0.0, 0.0));
1792 frag_edges.push_back(p_line);
1800 std::vector<std::vector<Point>> & frag_faces)
const 1807 mooseError(
"element ", elem->id(),
" has more than one fragment at this point");
1811 std::vector<Point> p_line(num_face_nodes, Point(0.0, 0.0, 0.0));
1812 for (
unsigned int j = 0;
j < num_face_nodes; ++
j)
1814 frag_faces.push_back(p_line);
1828 if (xfem_qrule ==
"volfrac")
1830 else if (xfem_qrule ==
"moment_fitting")
1832 else if (xfem_qrule ==
"direct")
1861 bool have_weights =
false;
1865 mooseAssert(xfce !=
nullptr,
"Must have valid XFEMCutElem object here");
1867 have_weights =
true;
1869 Real ave_weight_multiplier = 0;
1870 for (
unsigned int i = 0; i < weights.
size(); ++i)
1871 ave_weight_multiplier += weights[i];
1872 ave_weight_multiplier /= weights.
size();
1877 for (
unsigned int i = 0; i < weights.
size(); ++i)
1878 weights[i] += amount_to_add;
1881 return have_weights;
1891 bool have_weights =
false;
1895 mooseAssert(xfce !=
nullptr,
"Must have valid XFEMCutElem object here");
1897 have_weights =
true;
1899 return have_weights;
1904 unsigned int plane_id,
1906 std::vector<Point> & intersectionPoints,
1907 bool displaced_mesh)
const 1909 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1923 std::vector<Point> & quad_pts,
1924 std::vector<Real> & quad_wts)
const 1926 Point p1 = intersection_points[0];
1927 Point p2 = intersection_points[1];
1930 std::size_t num_qpoints = 2;
1933 Real xi0 = -std::sqrt(1.0 / 3.0);
1934 Real xi1 = std::sqrt(1.0 / 3.0);
1936 quad_wts.resize(num_qpoints);
1937 quad_pts.resize(num_qpoints);
1941 quad_wts[0] = 1.0 * integ_jacobian;
1942 quad_wts[1] = 1.0 * integ_jacobian;
1944 quad_pts[0] = (1.0 - xi0) / 2.0 * p1 + (1.0 + xi0) / 2.0 * p2;
1945 quad_pts[1] = (1.0 - xi1) / 2.0 * p1 + (1.0 + xi1) / 2.0 * p2;
1950 std::vector<Point> & quad_pts,
1951 std::vector<Real> & quad_wts)
const 1953 std::size_t nnd_pe = intersection_points.size();
1954 Point xcrd(0.0, 0.0, 0.0);
1955 for (std::size_t i = 0; i < nnd_pe; ++i)
1956 xcrd += intersection_points[i];
1959 quad_pts.resize(nnd_pe);
1960 quad_wts.resize(nnd_pe);
1964 for (std::size_t
j = 0;
j < nnd_pe; ++
j)
1966 std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
1967 std::vector<Point> subtrig_points(3, Point(0.0, 0.0, 0.0));
1969 int jplus1 =
j < nnd_pe - 1 ?
j + 1 : 0;
1970 subtrig_points[0] = xcrd;
1971 subtrig_points[1] = intersection_points[
j];
1972 subtrig_points[2] = intersection_points[jplus1];
1974 std::vector<std::vector<Real>> sg2;
1976 for (std::size_t l = 0; l < sg2.size(); ++l)
1979 std::vector<Real> tsg_line(3, 0.0);
1980 for (std::size_t
k = 0;
k < 3; ++
k)
1982 tsg_line[0] += shape[
k][2] * subtrig_points[
k](0);
1983 tsg_line[1] += shape[
k][2] * subtrig_points[
k](1);
1984 tsg_line[2] += shape[
k][2] * subtrig_points[
k](2);
1986 quad_pts[
j + l] = Point(tsg_line[0], tsg_line[1], tsg_line[2]);
1987 quad_wts[
j + l] = sg2[l][3] * jac;
1994 const Node * node_to_store_from,
2001 std::vector<dof_id_type> stored_solution_dofs =
getNodeSolutionDofs(node_to_store_from, sys);
2002 std::vector<Real> stored_solution_scratch;
2004 std::size_t stored_solution_size =
2006 stored_solution_scratch.reserve(stored_solution_size);
2010 for (
auto dof : stored_solution_dofs)
2011 stored_solution_scratch.push_back(current_solution(dof));
2015 for (
auto dof : stored_solution_dofs)
2016 stored_solution_scratch.push_back(old_solution(dof));
2018 for (
auto dof : stored_solution_dofs)
2019 stored_solution_scratch.push_back(older_solution(dof));
2022 if (stored_solution_scratch.size() > 0)
2023 stored_solution[node_to_store_to->unique_id()] = stored_solution_scratch;
2028 const Elem * elem_to_store_from,
2036 std::vector<Real> stored_solution_scratch;
2038 std::size_t stored_solution_size =
2040 stored_solution_scratch.reserve(stored_solution_size);
2044 for (
auto dof : stored_solution_dofs)
2045 stored_solution_scratch.push_back(current_solution(dof));
2049 for (
auto dof : stored_solution_dofs)
2050 stored_solution_scratch.push_back(old_solution(dof));
2052 for (
auto dof : stored_solution_dofs)
2053 stored_solution_scratch.push_back(older_solution(dof));
2056 if (stored_solution_scratch.size() > 0)
2057 stored_solution[elem_to_store_to->unique_id()] = stored_solution_scratch;
2062 const std::map<
unique_id_type, std::vector<Real>> & stored_solution,
2067 for (
auto & node :
_mesh->local_node_ptr_range())
2069 auto mit = stored_solution.find(node->unique_id());
2070 if (mit != stored_solution.end())
2072 const std::vector<Real> & stored_node_solution = mit->second;
2075 stored_solution_dofs,
2082 for (
auto & elem :
as_range(
_mesh->local_elements_begin(),
_mesh->local_elements_end()))
2084 auto mit = stored_solution.find(elem->unique_id());
2085 if (mit != stored_solution.end())
2087 const std::vector<Real> & stored_elem_solution = mit->second;
2090 stored_solution_dofs,
2100 const std::vector<dof_id_type> & stored_solution_dofs,
2107 const auto old_solution_offset = stored_solution_dofs.size();
2108 const auto older_solution_offset = old_solution_offset * 2;
2110 for (std::size_t i = 0; i < stored_solution_dofs.size(); ++i)
2112 current_solution.
set(stored_solution_dofs[i], stored_solution[i]);
2115 old_solution.
set(stored_solution_dofs[i], stored_solution[old_solution_offset + i]);
2116 older_solution.
set(stored_solution_dofs[i], stored_solution[older_solution_offset + i]);
2121 std::vector<dof_id_type>
2126 std::vector<dof_id_type> solution_dofs;
2127 solution_dofs.reserve(
vars.size());
2128 for (
auto var :
vars)
2130 if (!var->isNodal())
2133 if (var_subdomains.empty() || var_subdomains.find(sid) != var_subdomains.end())
2135 unsigned int n_comp = elem->n_comp(sys.
number(), var->number());
2136 for (
unsigned int icomp = 0; icomp < n_comp; ++icomp)
2139 solution_dofs.push_back(elem_dof);
2144 return solution_dofs;
2147 std::vector<dof_id_type>
2152 std::vector<dof_id_type> solution_dofs;
2153 solution_dofs.reserve(
vars.size());
2154 for (
auto var :
vars)
2159 std::set<SubdomainID> intersect;
2160 set_intersection(var_subdomains.begin(),
2161 var_subdomains.end(),
2164 std::inserter(intersect, intersect.begin()));
2165 if (var_subdomains.empty() || !intersect.empty())
2167 unsigned int n_comp = node->n_comp(sys.
number(), var->number());
2168 for (
unsigned int icomp = 0; icomp < n_comp; ++icomp)
2171 solution_dofs.push_back(node_dof);
2176 return solution_dofs;
2184 std::set<unsigned int> elems = gcmit.second;
2185 if (elems.find(elem->id()) != elems.end())
2196 const auto & elem_props = storage.
props(state).at(elem);
2197 auto & serialized_props =
_geom_cut_elems[elem]._elem_material_properties[state - 1];
2198 serialized_props.clear();
2199 for (
const auto & side_props_pair : elem_props)
2201 const auto side = side_props_pair.first;
2202 std::ostringstream oss;
2204 serialized_props[side].assign(oss.str());
2221 bool need_boundary_materials =
false;
2222 for (
unsigned int side = 0; side < child_elem->n_sides(); ++side)
2224 std::vector<boundary_id_type> elem_boundary_ids;
2225 _mesh->get_boundary_info().boundary_ids(child_elem, side, elem_boundary_ids);
2226 for (
auto bdid : elem_boundary_ids)
2228 need_boundary_materials =
true;
2232 if (need_boundary_materials)
2247 const auto & serialized_props = cached_props[state - 1];
2248 for (
const auto & [side, serialized_side_props] : serialized_props)
2250 std::istringstream iss;
2251 iss.str(serialized_side_props);
2264 const Elem * elem_from,
2265 std::unordered_map<const Elem *, Xfem::CutElemInfo> & cached_cei)
const 2268 mooseAssert(cached_cei.count(elem_from) > 0,
"XFEM: Unable to find cached material properties.");
2273 cei._elem_material_properties,
2277 bool need_boundary_materials =
false;
2278 for (
unsigned int side = 0; side < elem->n_sides(); ++side)
2280 std::vector<boundary_id_type> elem_boundary_ids;
2281 _mesh->get_boundary_info().boundary_ids(elem, side, elem_boundary_ids);
2282 for (
auto bdid : elem_boundary_ids)
2284 need_boundary_materials =
true;
2288 if (need_boundary_materials)
2291 cei._bnd_material_properties,
2297 const Elem * cut_elem,
2298 const Elem * parent_elem)
const 2301 parent_elem = cut_elem;
2311 for (
auto i : e0->node_index_range())
2313 return e0->node_ptr(i);
2314 mooseError(
"cannot find a physical node in the current element");
void getCrackTipOrigin(std::map< unsigned int, const Elem *> &elem_id_crack_tip, std::vector< Point > &crack_front_points)
EFAFragment3D * getFragment(unsigned int frag_id) const
void getFragmentFaces(const Elem *elem, std::vector< std::vector< Point >> &frag_faces, bool displaced_mesh=false) const
void correctCrackExtensionDirection(const Elem *elem, EFAElement2D *CEMElem, EFAEdge *orig_edge, Point normal, Point crack_tip_origin, Point crack_tip_direction, Real &distance_keep, unsigned int &edge_id_keep, Point &normal_keep)
bool _use_crack_growth_increment
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
void setSolutionForDOFs(const std::vector< Real > &stored_solution, const std::vector< dof_id_type > &stored_solution_dofs, NumericVector< Number > ¤t_solution, NumericVector< Number > &old_solution, NumericVector< Number > &older_solution)
Set the solution for a set of DOFs.
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
const GeometricCutUserObject * getGeometricCutForElem(const Elem *elem) const
Get the GeometricCutUserObject associated with an element.
const std::vector< MooseVariableFieldBase *> & getVariables(THREAD_ID tid)
unsigned int numEdgeNeighbors(unsigned int edge_id) const
bool markCutEdgesByState(Real time)
void addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
void storeMaterialPropertiesForElement(const Elem *parent_elem, const Elem *child_elem)
Helper function to store the material properties of a healed element.
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo3D > > _geom_marked_elems_3d
Data structure for storing information about all 3D elements to be cut by geometry.
EFAElement3D * getFaceNeighbor(unsigned int face_id, unsigned int neighbor_id) const
EFANode * getEmbeddedNode(unsigned int index) const
CutSubdomainID getCutSubdomainID(const GeometricCutUserObject *gcuo, const Elem *cut_elem, const Elem *parent_elem=nullptr) const
Determine which cut subdomain the element belongs to relative to the cut.
void shapeFunc2D(unsigned int nen, std::vector< Real > &ss, std::vector< Point > &xl, std::vector< std::vector< Real >> &shp, Real &xsj, bool natl_flg)
Data structure describing geometrically described cut through 3D element.
bool isFacePhantom(unsigned int face_id) const
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
std::vector< const GeometricCutUserObject * > _geometric_cuts
void setSolution(SystemBase &sys, const std::map< unique_id_type, std::vector< Real >> &stored_solution, NumericVector< Number > ¤t_solution, NumericVector< Number > &old_solution, NumericVector< Number > &older_solution)
Set the solution for all locally-owned nodes/elements that have stored values.
unsigned int getCrackTipSplitElementID() const
virtual bool update(Real time, const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux) override
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_elems
Real _crack_growth_increment
bool isSecondaryInteriorEdge(unsigned int edge_id) const
bool shouldHealMesh() const
Should the elements cut by this cutting object be healed in the current time step?
virtual bool getXFEMFaceWeights(MooseArray< Real > &weights, const Elem *elem, QBase *qrule, const MooseArray< Point > &q_points, unsigned int side) override
void mooseError(Args &&... args)
virtual void getFragmentFaces(std::vector< std::vector< Point >> &frag_faces, MeshBase *displaced_mesh=nullptr) const =0
bool isPartialOverlap(const EFAEdge &other) const
std::vector< dof_id_type > getNodeSolutionDofs(const Node *node, SystemBase &sys) const
Get a vector of the dof indices for all components of all variables associated with a node...
const ExecFlagType EXEC_XFEM_MARK
Exec flag used to execute MooseObjects while elements are being marked for cutting by XFEM...
bool isPointInsidePhysicalDomain(const Elem *elem, const Point &point) const
Return true if the point is inside the element physical domain Note: if this element is not cut...
bool isSemiLocal(Node *const node) const
void updateEdgeNeighbors()
void getFragmentEdges(const Elem *elem, EFAElement2D *CEMElem, std::vector< std::vector< Point >> &frag_edges) const
bool match(const CutElemInfo &rhs)
bool cutMeshWithEFA(const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux)
unsigned int getTipEdgeID() const
unsigned int numEdges() const
EFAEdge * getEdge(unsigned int edge_id) const
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_displaced_elems
Real getPhysicalVolumeFraction() const
Returns the volume fraction of the element fragment.
void clearGeomMarkedElems()
Clear out the list of elements to be marked for cutting.
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
EFAElement * add3DElement(const std::vector< unsigned int > &quad, unsigned int id)
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
const std::vector< EFAElement * > & getChildElements()
std::set< const Elem * > _crack_tip_elems
bool healMesh()
Potentially heal the mesh by merging some of the pairs of partial elements cut by XFEM back into sing...
XFEM(const InputParameters ¶ms)
virtual bool isPartial() const =0
ElementFragmentAlgorithm _efa_mesh
const std::set< SubdomainID > & getNodeBlockIds(const Node &node) const
bool hasIntersection() const
virtual unsigned int numFragments() const
NumericVector< Number > & solutionOlder()
std::array< std::unordered_map< unsigned int, std::string >, 2 > CachedMaterialProperties
Convenient typedef for local storage of stateful material properties.
std::vector< unsigned int > getInteriorEdgeID() const
unsigned int numEdges() const
void getFaceWeightMultipliers(MooseArray< Real > &face_weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points, unsigned int side)
bool isEdgePhantom(unsigned int edge_id) const
virtual unsigned int numFragments() const
Real distance(const Point &p)
std::set< const Elem * > _crack_tip_elems_to_be_healed
void addGeometricCut(GeometricCutUserObject *geometric_cut)
std::map< unique_id_type, std::vector< Real > > _cached_aux_solution
Data structure to store the auxiliary solution for nodes/elements affected by XFEM For each node/elem...
unsigned int numFaces() const
bool markCutEdgesByGeometry()
unsigned int CutSubdomainID
FEProblemBase * _fe_problem
std::vector< MaterialData *> _bnd_material_data
EFANode * getNode(unsigned int node_id) const
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
void setMinWeightMultiplier(Real min_weight_multiplier)
Controls the minimum average weight multiplier for each element.
void updateTopology(bool mergeUncutVirtualEdges=true)
const std::vector< EFAElement * > & getParentElements()
virtual const EFAElement * getEFAElement() const =0
void updatePhysicalLinksAndFragments()
bool initCutIntersectionEdge(Point cut_origin, RealVectorValue cut_normal, Point &edge_p1, Point &edge_p2, Real &dist)
void addGeomMarkedElem3D(const unsigned int elem_id, const Xfem::GeomMarkedElemInfo3D geom_info, const unsigned int interface_id)
Add information about a new cut to be performed on a specific 3d element.
virtual void execute(const ExecFlagType &exec_type)
void addElemFaceIntersection(unsigned int elemid, unsigned int faceid, const std::vector< unsigned int > &edgeid, const std::vector< double > &position)
void storeCrackTipOriginAndDirection()
const Node * pickFirstPhysicalNode(const Elem *e, const Elem *e0) const
Return the first node in the provided element that is found to be in the physical domain...
void loadMaterialPropertiesForElement(const Elem *elem, const Elem *elem_from, std::unordered_map< const Elem *, Xfem::CutElemInfo > &cached_cei) const
Helper function to store the material properties of a healed element.
void dataStore(std::ostream &stream, FaceCenteredMapFunctor< T, Map > &m, void *context)
unsigned int size() const
const std::vector< EFANode * > & getNewNodes()
EFAFragment2D * getFragment(unsigned int frag_id) const
Real getCutPlane(const Elem *elem, const Xfem::XFEM_CUTPLANE_QUANTITY quantity, unsigned int plane_id) const
Get specified component of normal or origin for cut plane for a given element.
unsigned int numNodes() const
std::map< const GeometricCutUserObject *, unsigned int > _geom_marker_id_map
Data structure for storing the GeommetricCutUserObjects and their corresponding id.
virtual void getIntersectionInfo(unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, MeshBase *displaced_mesh=nullptr) const =0
std::vector< MaterialData *> _material_data
void addGeomMarkedElem2D(const unsigned int elem_id, const Xfem::GeomMarkedElemInfo2D geom_info, const unsigned int interface_id)
Add information about a new cut to be performed on a specific 2d element.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
void storeSolutionForElement(const Elem *elem_to_store_to, const Elem *elem_to_store_from, SystemBase &sys, std::map< unique_id_type, std::vector< Real >> &stored_solution, const NumericVector< Number > ¤t_solution, const NumericVector< Number > &old_solution, const NumericVector< Number > &older_solution)
Store the solution in stored_solution for a given element.
virtual Point getCutPlaneOrigin(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
virtual bool isFinalCut() const
Xfem::XFEM_QRULE _XFEM_qrule
unsigned int n_points() const
void storeSolutionForNode(const Node *node_to_store_to, const Node *node_to_store_from, SystemBase &sys, std::map< unique_id_type, std::vector< Real >> &stored_solution, const NumericVector< Number > ¤t_solution, const NumericVector< Number > &old_solution, const NumericVector< Number > &older_solution)
Store the solution in stored_solution for a given node.
bool isThirdInteriorFace(unsigned int face_id) const
unsigned int number() const
virtual void getXFEMqRuleOnLine(std::vector< Point > &intersection_points, std::vector< Point > &quad_pts, std::vector< Real > &quad_wts) const
Data structure describing geometrically described cut through 2D element.
void loadMaterialPropertiesForElementHelper(const Elem *elem, const Xfem::CachedMaterialProperties &cached_props, MaterialPropertyStorage &storage) const
Load the material properties.
void setDebugOutputLevel(unsigned int debug_output_level)
Controls amount of debugging information output.
std::map< const Elem *, std::vector< Point > > _elem_crack_origin_direction_map
virtual void getXFEMIntersectionInfo(const Elem *elem, unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, bool displaced_mesh=false) const
std::map< const Elem *, std::vector< Xfem::GeomMarkedElemInfo2D > > _geom_marked_elems_2d
Data structure for storing information about all 2D elements to be cut by geometry.
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
void addFragFaceIntersection(unsigned int ElemID, unsigned int FragFaceID, const std::vector< unsigned int > &FragFaceEdgeID, const std::vector< double > &position)
virtual CutSubdomainID getCutSubdomainID(const Node *) const
Get CutSubdomainID telling which side the node belongs to relative to the cut.
bool hasStatefulProperties() const
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
virtual void initSolution(const std::vector< std::shared_ptr< NonlinearSystemBase >> &nl, AuxiliarySystem &aux) override
std::set< const Elem * > _state_marked_frags
EFANode * getTipEmbeddedNode() const
void restoreFragmentInfo(EFAElement *const elem, const EFAElement *const from_elem)
void storeMaterialPropertiesForElementHelper(const Elem *elem, MaterialPropertyStorage &storage)
const PropsType & props(const unsigned int state=0) const
virtual void getMasterInfo(EFANode *node, std::vector< EFANode *> &master_nodes, std::vector< double > &master_weights) const =0
EFAElement3D * getEFAElem3D(const Elem *elem)
Get the EFAElement3D object for a specified libMesh element.
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
virtual void computePhysicalVolumeFraction()=0
Computes the volume fraction of the element fragment.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool isElemAtCrackTip(const Elem *elem) const
void stdQuadr2D(unsigned int nen, unsigned int iord, std::vector< std::vector< Real >> &sg2)
std::vector< dof_id_type > getElementSolutionDofs(const Elem *elem, SystemBase &sys) const
Get a vector of the dof indices for all components of all variables associated with an element...
Xfem::XFEM_QRULE & getXFEMQRule()
Real getPhysicalVolumeFraction(const Elem *elem) const
Get the volume fraction of an element that is physical.
virtual bool getXFEMWeights(MooseArray< Real > &weights, const Elem *elem, QBase *qrule, const MooseArray< Point > &q_points) override
virtual void getXFEMqRuleOnSurface(std::vector< Point > &intersection_points, std::vector< Point > &quad_pts, std::vector< Real > &quad_wts) const
EFAElement * add2DElement(const std::vector< unsigned int > &quad, unsigned int id)
bool markCutFacesByGeometry()
unsigned int getLocalNodeIndex(EFANode *node) const
void setCrackGrowthMethod(bool use_crack_growth_increment, Real crack_growth_increment)
void addStateMarkedElem(unsigned int elem_id, RealVectorValue &normal)
EFAElement * getElemByID(unsigned int id)
MeshBase * _displaced_mesh
const libMesh::QBase *const & qRule() const
std::unique_ptr< NumericVector< Number > > current_local_solution
const std::set< SubdomainID > & getSubdomainsForVar(unsigned int var_number) const
std::map< unique_id_type, std::vector< Real > > _cached_solution
Data structure to store the nonlinear solution for nodes/elements affected by XFEM For each node/elem...
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
void dataLoad(std::istream &stream, FaceCenteredMapFunctor< T, Map > &m, void *context)
virtual void set(const numeric_index_type i, const Number value)=0
virtual bool updateHeal() override
const ConsoleStream _console
virtual void serializeSolution()
void clearStateMarkedElems()
void getWeightMultipliers(MooseArray< Real > &weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points)
virtual libMesh::System & system() override
virtual bool isTransient() const override
virtual bool cutElementByCrackGrowthIncrement(const Elem *elem, std::vector< CutEdgeForCrackGrowthIncr > &cut_edges, Real time)
void setXFEMQRule(std::string &xfem_qrule)
EFAFace * getFragmentFace(unsigned int frag_id, unsigned int face_id) const
NumericVector< Number > & solutionOld()
std::map< const Elem *, unsigned int > _state_marked_elem_sides
virtual bool isDistributedMesh() const
Information about a cut element.
EFANode * getNode(unsigned int index) const
const std::set< EFAElement * > & getCrackTipElements()
static const std::string k
unsigned int numFaceNeighbors(unsigned int face_id) const
Point getEFANodeCoords(EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
std::map< const Elem *, RealVectorValue > _state_marked_elems
EFAElement2D * getEFAElem2D(const Elem *elem)
Get the EFAElement2D object for a specified libMesh element.
virtual Point getCutPlaneNormal(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
void ErrorVector unsigned int
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
void initCrackTipTopology()
bool markCutFacesByState()
void setInterfaceID(unsigned int interface_id)
Set the interface ID for this cutting object.
Real _min_weight_multiplier
The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partia...
void addStateMarkedFrag(unsigned int elem_id, RealVectorValue &normal)
unsigned int numFaces() const
virtual void getCrackTipOriginAndDirection(unsigned tip_id, Point &origin, Point &direction) const =0
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK...
libMesh::IntRange< unsigned int > statefulIndexRange() const
bool isPointPhysical(const Point &p) const
std::unordered_map< const Elem *, Xfem::CutElemInfo > _old_geom_cut_elems
All geometrically cut elements and their CutElemInfo before the current execution of XFEM_MARK...