33#include "libmesh/mesh_communication.h"
34#include "libmesh/partitioner.h"
38 _state_marked_t_step(0),
39 _efa_mesh(
Moose::out),
40 _debug_output_level(1),
41 _min_weight_multiplier(0.0)
43#ifndef LIBMESH_ENABLE_UNIQUE_ID
44 mooseError(
"MOOSE requires unique ids to be enabled in libmesh (configure with "
45 "--enable-unique-id) to use XFEM!");
52 for (std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
_cut_elem_map.begin();
70 std::vector<Point> & crack_front_points)
72 elem_id_crack_tip.clear();
73 crack_front_points.clear();
76 unsigned int crack_tip_index = 0;
79 std::map<unsigned int, const Elem *> elem_id_map;
82 for (std::map<
const Elem *, std::vector<Point>>::iterator mit1 =
87 unsigned int elem_id = mit1->first->id();
88 if (elem_id == std::numeric_limits<unsigned int>::max())
90 elem_id_map[m] = mit1->first;
94 elem_id_map[elem_id] = mit1->first;
97 for (std::map<unsigned int, const Elem *>::iterator mit1 = elem_id_map.begin();
98 mit1 != elem_id_map.end();
101 const Elem * elem = mit1->second;
102 std::map<const Elem *, std::vector<Point>>::iterator mit2 =
106 elem_id_crack_tip[crack_tip_index] = mit2->first;
107 crack_front_points[crack_tip_index] =
117 Elem * elem =
_mesh->elem_ptr(elem_id);
118 std::map<const Elem *, RealVectorValue>::iterator mit;
121 mooseError(
" ERROR: element ", elem->id(),
" already marked for crack growth.");
130 Elem * elem =
_mesh->elem_ptr(elem_id);
131 std::map<const Elem *, unsigned int>::iterator mit;
134 mooseError(
" ERROR: side of element ", elem->id(),
" already marked for crack initiation.");
143 Elem * elem =
_mesh->elem_ptr(elem_id);
144 std::set<const Elem *>::iterator mit;
148 " ERROR: element ", elem->id(),
" already marked for fragment-secondary crack initiation.");
164 const unsigned int interface_id)
166 Elem * elem =
_mesh->elem_ptr(elem_id);
174 const unsigned int interface_id)
176 Elem * elem =
_mesh->elem_ptr(elem_id);
193 std::set<EFAElement *>::iterator sit;
194 for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
196 if (
_mesh->mesh_dimension() == 2)
202 Point origin(0, 0, 0);
203 Point direction(0, 0, 0);
205 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
217 std::vector<Point> tip_data;
218 tip_data.push_back(origin);
219 tip_data.push_back(direction);
220 const Elem * elem =
_mesh->elem_ptr((*sit)->id());
222 std::pair<
const Elem *, std::vector<Point>>(elem, tip_data));
230 bool mesh_changed =
false;
239 _mesh->update_parallel_id_counts();
244 _mesh->allow_renumbering(
false);
245 _mesh->skip_partitioning(
true);
246 _mesh->prepare_for_use();
266 const std::vector<std::shared_ptr<NonlinearSystemBase>> & nl,
270 mooseError(
"Use of XFEM with distributed mesh is not yet supported");
272 for (
const auto & elem :
_mesh->active_element_ptr_range())
273 if (elem->level() > 0)
274 mooseError(
"XFEM does not currently support mesh adaptivity or adaptively refined meshes");
276 bool mesh_changed =
false;
298 _mesh->allow_renumbering(
false);
299 _mesh->skip_partitioning(
true);
300 _mesh->prepare_for_use();
321 mooseError(
"XFEM does not currently support multiple nonlinear systems");
323 nls[0]->serializeSolution();
325 NumericVector<Number> & current_solution = *nls[0]->system().current_local_solution;
326 NumericVector<Number> & old_solution = nls[0]->solutionOld();
327 NumericVector<Number> & older_solution = nls[0]->solutionOlder();
329 NumericVector<Number> & old_aux_solution = aux.
solutionOld();
330 NumericVector<Number> & older_aux_solution = aux.
solutionOlder();
336 current_solution.close();
337 old_solution.close();
338 older_solution.close();
339 current_aux_solution.close();
340 old_aux_solution.close();
341 older_aux_solution.close();
353 for (
auto & elem :
_mesh->element_ptr_range())
355 std::vector<unsigned int> quad;
356 for (
unsigned int i = 0; i < elem->n_nodes(); ++i)
357 quad.push_back(elem->node_id(i));
359 if (
_mesh->mesh_dimension() == 2)
361 else if (
_mesh->mesh_dimension() == 3)
368 for (
auto & elem :
_mesh->element_ptr_range())
370 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
_cut_elem_map.find(elem->unique_id());
389 bool marked_sides =
false;
390 if (
_mesh->mesh_dimension() == 2)
395 else if (
_mesh->mesh_dimension() == 3)
406 bool marked_edges =
false;
407 bool marked_nodes =
false;
411 for (
const auto & gmei : gme.second)
415 for (
unsigned int i = 0; i < gmei._elem_cut_edges.size(); ++i)
418 gmei._elem_cut_edges[i]._host_side_id))
421 gmei._elem_cut_edges[i]._host_side_id,
422 gmei._elem_cut_edges[i]._distance);
427 for (
unsigned int i = 0; i < gmei._elem_cut_nodes.size(); ++i)
433 for (
unsigned int i = 0; i < gmei._frag_cut_edges.size();
437 gmei._frag_cut_edges[i]._host_side_id))
440 gmei._frag_cut_edges[i]._host_side_id,
441 gmei._frag_cut_edges[i]._distance))
452 return marked_edges || marked_nodes;
460 Point crack_tip_origin,
461 Point crack_tip_direction,
462 Real & distance_keep,
463 unsigned int & edge_id_keep,
466 std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
467 Point edge1(0.0, 0.0, 0.0);
468 Point edge2(0.0, 0.0, 0.0);
469 Point left_angle(0.0, 0.0, 0.0);
470 Point right_angle(0.0, 0.0, 0.0);
471 Point left_angle_normal(0.0, 0.0, 0.0);
472 Point right_angle_normal(0.0, 0.0, 0.0);
473 Point crack_direction_normal(0.0, 0.0, 0.0);
474 Point edge1_to_tip(0.0, 0.0, 0.0);
475 Point edge2_to_tip(0.0, 0.0, 0.0);
476 Point edge1_to_tip_normal(0.0, 0.0, 0.0);
477 Point edge2_to_tip_normal(0.0, 0.0, 0.0);
479 Real cos_45 = std::cos(45.0 / 180.0 * 3.14159);
480 Real sin_45 = std::sin(45.0 / 180.0 * 3.14159);
482 left_angle(0) = cos_45 * crack_tip_direction(0) - sin_45 * crack_tip_direction(1);
483 left_angle(1) = sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
485 right_angle(0) = cos_45 * crack_tip_direction(0) + sin_45 * crack_tip_direction(1);
486 right_angle(1) = -sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
488 left_angle_normal(0) = -left_angle(1);
489 left_angle_normal(1) = left_angle(0);
491 right_angle_normal(0) = -right_angle(1);
492 right_angle_normal(1) = right_angle(0);
494 crack_direction_normal(0) = -crack_tip_direction(1);
495 crack_direction_normal(1) = crack_tip_direction(0);
497 Real angle_min = 0.0;
501 for (
unsigned int i = 0; i <
nsides; ++i)
508 edge1_to_tip = (edge_ends[0] * 0.95 + edge_ends[1] * 0.05) - crack_tip_origin;
509 edge2_to_tip = (edge_ends[0] * 0.05 + edge_ends[1] * 0.95) - crack_tip_origin;
511 edge1_to_tip /=
pow(edge1_to_tip.norm_sq(), 0.5);
512 edge2_to_tip /=
pow(edge2_to_tip.norm_sq(), 0.5);
514 edge1_to_tip_normal(0) = -edge1_to_tip(1);
515 edge1_to_tip_normal(1) = edge1_to_tip(0);
517 edge2_to_tip_normal(0) = -edge2_to_tip(1);
518 edge2_to_tip_normal(1) = edge2_to_tip(0);
520 Real angle_edge1_normal = edge1_to_tip_normal * normal;
521 Real angle_edge2_normal = edge2_to_tip_normal * normal;
523 if (std::abs(angle_edge1_normal) > std::abs(angle_min) &&
524 (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
527 distance_keep = 0.05;
528 normal_keep = edge1_to_tip_normal;
529 angle_min = angle_edge1_normal;
531 else if (std::abs(angle_edge2_normal) > std::abs(angle_min) &&
532 (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
535 distance_keep = 0.95;
536 normal_keep = edge2_to_tip_normal;
537 angle_min = angle_edge2_normal;
541 crack_tip_origin, left_angle_normal, edge_ends[0], edge_ends[1],
distance) &&
544 if (std::abs(left_angle_normal * normal) > std::abs(angle_min) &&
545 (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
549 normal_keep = left_angle_normal;
550 angle_min = left_angle_normal * normal;
554 crack_tip_origin, right_angle_normal, edge_ends[0], edge_ends[1],
distance) &&
557 if (std::abs(right_angle_normal * normal) > std::abs(angle_min) &&
558 (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
562 normal_keep = right_angle_normal;
563 angle_min = right_angle_normal * normal;
567 crack_direction_normal,
573 if (std::abs(crack_direction_normal * normal) > std::abs(angle_min) &&
574 (crack_tip_direction * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
578 normal_keep = crack_direction_normal;
579 angle_min = crack_direction_normal * normal;
586 if ((distance_keep - 0.05) < 0.0)
588 distance_keep = 0.05;
590 else if ((distance_keep - 0.95) > 0.0)
592 distance_keep = 0.95;
599 bool marked_edges =
false;
600 for (std::map<const Elem *, RealVectorValue>::iterator pmeit =
_state_marked_elems.begin();
604 const Elem * elem = pmeit->first;
605 RealVectorValue normal = pmeit->second;
609 if (volfrac_elem < 0.25)
618 unsigned int orig_cut_side_id = std::numeric_limits<unsigned int>::max();
619 Real orig_cut_distance = -1.0;
624 Point crack_tip_origin(0, 0, 0);
625 Point crack_tip_direction(0, 0, 0);
630 if (orig_cut_side_id <
nsides)
632 orig_edge = CEMElem->
getEdge(orig_cut_side_id);
636 mooseError(
"element ", elem->id(),
" has no valid crack-tip edge");
639 std::map<const Elem *, std::vector<Point>>::iterator ecodm =
643 crack_tip_origin = (ecodm->second)[0];
644 crack_tip_direction = (ecodm->second)[1];
647 mooseError(
"element ", elem->id(),
" cannot find its crack tip origin and direction.");
651 std::map<const Elem *, unsigned int>::iterator mit1;
653 std::set<const Elem *>::iterator mit2;
658 orig_cut_side_id = mit1->second;
662 orig_cut_distance = 0.5;
664 orig_edge = CEMElem->
getEdge(orig_cut_side_id);
667 Point elem_center(0.0, 0.0, 0.0);
669 for (
unsigned int i = 0; i <
nsides; ++i)
674 elem_center /=
nsides * 2.0;
678 crack_tip_origin = edge_center;
679 crack_tip_direction = elem_center - edge_center;
680 crack_tip_direction /=
pow(crack_tip_direction.norm_sq(), 0.5);
690 " flagged for a secondary crack, but has ",
694 if (interior_edge_id.size() == 1)
695 orig_cut_side_id = interior_edge_id[0];
699 orig_cut_distance = 0.5;
703 Point elem_center(0.0, 0.0, 0.0);
706 for (
unsigned int i = 0; i < nsides_frag; ++i)
713 elem_center /= nsides_frag * 2.0;
717 crack_tip_origin = edge_center;
718 crack_tip_direction = elem_center - edge_center;
719 crack_tip_direction /=
pow(crack_tip_direction.norm_sq(), 0.5);
724 " flagged for state-based growth, but has no edge intersections");
727 Point cut_origin(0.0, 0.0, 0.0);
731 mooseError(
"element ", elem->id(),
" does not have valid orig_node");
734 std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
735 Point edge1(0.0, 0.0, 0.0);
736 Point edge2(0.0, 0.0, 0.0);
737 Point cut_edge_point(0.0, 0.0, 0.0);
738 bool find_compatible_direction =
false;
739 unsigned int edge_id_keep = 0;
740 Real distance_keep = 0.0;
741 Point normal_keep(0.0, 0.0, 0.0);
743 bool edge_cut =
false;
745 for (
unsigned int i = 0; i <
nsides; ++i)
752 crack_tip_origin, normal, edge_ends[0], edge_ends[1],
distance) &&
758 normal_keep = normal;
765 Point between_two_cuts = (cut_edge_point - crack_tip_origin);
766 between_two_cuts /=
pow(between_two_cuts.norm_sq(), 0.5);
767 Real angle_between_two_cuts = between_two_cuts * crack_tip_direction;
769 if (angle_between_two_cuts > std::cos(45.0 / 180.0 * 3.14159))
770 find_compatible_direction =
true;
772 if (!find_compatible_direction && edge_cut)
789 Point growth_direction(0.0, 0.0, 0.0);
791 growth_direction(0) = -normal_keep(1);
792 growth_direction(1) = normal_keep(0);
794 if (growth_direction * crack_tip_direction < 1.0e-10)
795 growth_direction *= (-1.0);
797 Real x0 = crack_tip_origin(0);
798 Real y0 = crack_tip_origin(1);
804 for (
const auto & elem :
_mesh->element_ptr_range())
806 std::vector<CutEdgeForCrackGrowthIncr> elem_cut_edges;
816 for (
unsigned int i = 0; i < elem_cut_edges.size(); ++i)
819 elem_cut_edges[i]._host_side_id))
822 elem->id(), elem_cut_edges[i]._host_side_id, elem_cut_edges[i]._distance);
832 for (
unsigned int i = 0; i < CEMElem->
getFragment(0)->numEdges(); ++i)
841 crack_tip_origin, normal, edge_ends[0], edge_ends[1],
distance) &&
863 bool marked_faces =
false;
867 for (
const auto & gmei : gme.second)
871 for (
unsigned int i = 0; i < gmei._elem_cut_faces.size(); ++i)
873 if (!EFAElem->
isFacePhantom(gmei._elem_cut_faces[i]._face_id))
876 gmei._elem_cut_faces[i]._face_id,
877 gmei._elem_cut_faces[i]._face_edge,
878 gmei._elem_cut_faces[i]._position);
883 for (
unsigned int i = 0; i < gmei._frag_cut_faces.size();
889 gmei._frag_cut_faces[i]._face_id,
890 gmei._frag_cut_faces[i]._face_edge,
891 gmei._frag_cut_faces[i]._position);
904 bool marked_faces =
false;
911 Point cut_origin, RealVectorValue cut_normal, Point & edge_p1, Point & edge_p2, Real & dist)
914 bool does_intersect =
false;
915 Point origin2p1 = edge_p1 - cut_origin;
916 Real plane2p1 = cut_normal(0) * origin2p1(0) + cut_normal(1) * origin2p1(1);
917 Point origin2p2 = edge_p2 - cut_origin;
918 Real plane2p2 = cut_normal(0) * origin2p2(0) + cut_normal(1) * origin2p2(1);
920 if (plane2p1 * plane2p2 < 0.0)
922 dist = -plane2p1 / (plane2p2 - plane2p1);
923 does_intersect =
true;
925 return does_intersect;
931 bool mesh_changed =
false;
933 std::set<Node *> nodes_to_delete;
934 std::set<Node *> nodes_to_delete_displaced;
935 std::set<unsigned int> cutelems_to_delete;
936 unsigned int deleted_elem_count = 0;
937 std::vector<std::string> healed_geometric_cuts;
946 Elem * elem1 =
const_cast<Elem *
>(it.first);
947 Elem * elem2 =
const_cast<Elem *
>(it.second);
949 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
955 cutelems_to_delete.insert(elem1->unique_id());
957 for (
unsigned int in = 0; in < elem1->n_nodes(); ++in)
959 Node * e1node = elem1->node_ptr(in);
960 Node * e2node = elem2->node_ptr(in);
964 elem1->set_node(in, e2node);
965 nodes_to_delete.insert(e1node);
967 else if (e1node != e2node)
968 nodes_to_delete.insert(e2node);
972 mooseError(
"Could not find XFEMCutElem for element to be kept in healing");
977 std::vector<const Elem *> healed_elems = {elem1, elem2};
983 for (
auto e : healed_elems)
984 if (elem1->processor_id() ==
_mesh->processor_id() &&
985 e->processor_id() ==
_mesh->processor_id())
993 if (parent_gcsid == gcsid)
1002 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
1008 for (
unsigned int in = 0; in < elem1_displaced->n_nodes(); ++in)
1010 Node * e1node_displaced = elem1_displaced->node_ptr(in);
1011 Node * e2node_displaced = elem2_displaced->node_ptr(in);
1013 e1node_displaced != e2node_displaced)
1015 elem1_displaced->set_node(in, e2node_displaced);
1016 nodes_to_delete_displaced.insert(e1node_displaced);
1018 else if (e1node_displaced != e2node_displaced)
1019 nodes_to_delete_displaced.insert(e2node_displaced);
1023 mooseError(
"Could not find XFEMCutElem for element to be kept in healing");
1025 elem2_displaced->nullify_neighbors();
1034 cutelems_to_delete.insert(elem2->unique_id());
1035 elem2->nullify_neighbors();
1036 _mesh->get_boundary_info().remove(elem2);
1037 unsigned int deleted_elem_id = elem2->id();
1038 _mesh->delete_elem(elem2);
1041 if (deleted_elem_count == 0)
1043 _console <<
"XFEM healing deleted element: " << deleted_elem_id << std::endl;
1045 ++deleted_elem_count;
1046 mesh_changed =
true;
1051 for (
auto & sit : nodes_to_delete)
1053 Node * node_to_delete = sit;
1054 dof_id_type deleted_node_id = node_to_delete->id();
1055 _mesh->get_boundary_info().remove(node_to_delete);
1056 _mesh->delete_node(node_to_delete);
1058 _console <<
"XFEM healing deleted node: " << deleted_node_id << std::endl;
1063 for (
auto & sit : nodes_to_delete_displaced)
1065 Node * node_to_delete_displaced = sit;
1066 _displaced_mesh->get_boundary_info().remove(node_to_delete_displaced);
1071 for (
auto & ced : cutelems_to_delete)
1099 _console <<
"\nXFEM mesh healing complete\n";
1100 _console <<
"Names of healed geometric cut objects: ";
1101 for (
auto geomcut : healed_geometric_cuts)
1104 _console <<
"# deleted nodes: " << nodes_to_delete.size() <<
"\n";
1105 _console <<
"# deleted elements: " << deleted_elem_count <<
"\n";
1109 return mesh_changed;
1116 if (nls.size() != 1)
1117 mooseError(
"XFEM does not currently support multiple nonlinear systems");
1119 std::map<unsigned int, Node *> efa_id_to_new_node;
1120 std::map<unsigned int, Node *> efa_id_to_new_node2;
1121 std::map<unsigned int, Elem *> efa_id_to_new_elem;
1134 _console <<
"\nXFEM Element fragment algorithm mesh prior to cutting:\n";
1143 _console <<
"\nXFEM Element fragment algorithm mesh after cutting:\n";
1152 bool mesh_changed = (new_nodes.size() + new_elements.size() + delete_elements.size() > 0);
1157 nls[0]->serializeSolution();
1162 NumericVector<Number> & current_solution = *nls[0]->system().current_local_solution;
1163 NumericVector<Number> & old_solution = nls[0]->solutionOld();
1164 NumericVector<Number> & older_solution = nls[0]->solutionOlder();
1166 NumericVector<Number> & old_aux_solution = aux.
solutionOld();
1167 NumericVector<Number> & older_aux_solution = aux.
solutionOlder();
1169 std::map<Node *, Node *> new_nodes_to_parents;
1172 for (
unsigned int i = 0; i < new_nodes.size(); ++i)
1174 unsigned int new_node_id = new_nodes[i]->id();
1175 unsigned int parent_id = new_nodes[i]->parent()->id();
1177 Node * parent_node =
_mesh->node_ptr(parent_id);
1178 Node * new_node = Node::build(*parent_node,
_mesh->max_node_id()).release();
1179 _mesh->add_node(new_node);
1181 new_nodes_to_parents[new_node] = parent_node;
1183 new_node->set_n_systems(parent_node->n_systems());
1184 efa_id_to_new_node.
insert(std::make_pair(new_node_id, new_node));
1186 _console <<
"XFEM added new node: " << new_node->id() << std::endl;
1190 Node * new_node2 = Node::build(*parent_node2,
_displaced_mesh->max_node_id()).release();
1193 new_node2->set_n_systems(parent_node2->n_systems());
1194 efa_id_to_new_node2.insert(std::make_pair(new_node_id, new_node2));
1199 std::map<unsigned int, std::vector<const Elem *>> temporary_parent_children_map;
1201 std::vector<boundary_id_type> parent_boundary_ids;
1203 for (
unsigned int i = 0; i < new_elements.size(); ++i)
1205 unsigned int parent_id = new_elements[i]->getParent()->id();
1206 unsigned int efa_child_id = new_elements[i]->id();
1208 Elem * parent_elem =
_mesh->elem_ptr(parent_id);
1209 Elem * libmesh_elem = Elem::build(parent_elem->type()).release();
1215 if (parent_elem == it.first)
1216 it.first = libmesh_elem;
1217 else if (parent_elem == it.second)
1218 it.second = libmesh_elem;
1223 if (new_elements[i]->getParent()->numChildren() > 1)
1224 temporary_parent_children_map[parent_elem->id()].push_back(libmesh_elem);
1226 Elem * parent_elem2 =
nullptr;
1227 Elem * libmesh_elem2 =
nullptr;
1231 libmesh_elem2 = Elem::build(parent_elem2->type()).release();
1237 if (parent_elem2 == it.first)
1238 it.first = libmesh_elem2;
1239 else if (parent_elem2 == it.second)
1240 it.second = libmesh_elem2;
1245 for (
unsigned int j = 0; j < new_elements[i]->numNodes(); ++j)
1247 unsigned int node_id = new_elements[i]->getNode(j)->id();
1248 Node * libmesh_node;
1250 std::map<unsigned int, Node *>::iterator nit = efa_id_to_new_node.find(node_id);
1251 if (nit != efa_id_to_new_node.end())
1252 libmesh_node = nit->second;
1254 libmesh_node =
_mesh->node_ptr(node_id);
1256 if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1257 libmesh_node->processor_id() = parent_elem->processor_id();
1259 libmesh_elem->set_node(j, libmesh_node);
1262 if (parent_elem->is_semilocal(
_mesh->processor_id()))
1264 Node * solution_node = libmesh_node;
1265 if (new_nodes_to_parents.find(libmesh_node) != new_nodes_to_parents.end())
1266 solution_node = new_nodes_to_parents[libmesh_node];
1269 (libmesh_node->processor_id() ==
_mesh->processor_id()))
1282 current_aux_solution,
1284 older_aux_solution);
1288 Node * parent_node = parent_elem->node_ptr(j);
1289 _mesh->get_boundary_info().boundary_ids(parent_node, parent_boundary_ids);
1290 _mesh->get_boundary_info().add_node(libmesh_node, parent_boundary_ids);
1294 std::map<unsigned int, Node *>::iterator nit2 = efa_id_to_new_node2.find(node_id);
1295 if (nit2 != efa_id_to_new_node2.end())
1296 libmesh_node = nit2->second;
1300 if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1301 libmesh_node->processor_id() = parent_elem2->processor_id();
1303 libmesh_elem2->set_node(j, libmesh_node);
1305 parent_node = parent_elem2->node_ptr(j);
1306 _displaced_mesh->get_boundary_info().boundary_ids(parent_node, parent_boundary_ids);
1307 _displaced_mesh->get_boundary_info().add_node(libmesh_node, parent_boundary_ids);
1311 libmesh_elem->set_p_level(parent_elem->p_level());
1312 libmesh_elem->set_p_refinement_flag(parent_elem->p_refinement_flag());
1313 _mesh->add_elem(libmesh_elem);
1314 libmesh_elem->set_n_systems(parent_elem->n_systems());
1315 libmesh_elem->subdomain_id() = parent_elem->subdomain_id();
1316 libmesh_elem->processor_id() = parent_elem->processor_id();
1320 std::map<const Elem *, std::vector<Point>>::iterator mit =
1330 _console <<
"XFEM added new element: " << libmesh_elem->id() << std::endl;
1333 if (
_mesh->mesh_dimension() == 2)
1336 if (!new_efa_elem2d)
1337 mooseError(
"EFAelem is not of EFAelement2D type");
1341 libmesh_elem->n_sides());
1343 else if (
_mesh->mesh_dimension() == 3)
1346 if (!new_efa_elem3d)
1347 mooseError(
"EFAelem is not of EFAelement3D type");
1351 libmesh_elem->n_sides());
1353 _cut_elem_map.insert(std::pair<unique_id_type, XFEMCutElem *>(libmesh_elem->unique_id(), xfce));
1354 efa_id_to_new_elem.insert(std::make_pair(efa_child_id, libmesh_elem));
1358 libmesh_elem2->set_p_level(parent_elem2->p_level());
1359 libmesh_elem2->set_p_refinement_flag(parent_elem2->p_refinement_flag());
1361 libmesh_elem2->set_n_systems(parent_elem2->n_systems());
1362 libmesh_elem2->subdomain_id() = parent_elem2->subdomain_id();
1363 libmesh_elem2->processor_id() = parent_elem2->processor_id();
1366 unsigned int n_sides = parent_elem->n_sides();
1367 for (
unsigned int side = 0; side < n_sides; ++side)
1369 _mesh->get_boundary_info().boundary_ids(parent_elem, side, parent_boundary_ids);
1370 _mesh->get_boundary_info().add_side(libmesh_elem, side, parent_boundary_ids);
1374 n_sides = parent_elem2->n_sides();
1375 for (
unsigned int side = 0; side < n_sides; ++side)
1377 _displaced_mesh->get_boundary_info().boundary_ids(parent_elem2, side, parent_boundary_ids);
1378 _displaced_mesh->get_boundary_info().add_side(libmesh_elem2, side, parent_boundary_ids);
1382 unsigned int n_edges = parent_elem->n_edges();
1383 for (
unsigned int edge = 0; edge < n_edges; ++edge)
1385 _mesh->get_boundary_info().edge_boundary_ids(parent_elem, edge, parent_boundary_ids);
1386 _mesh->get_boundary_info().add_edge(libmesh_elem, edge, parent_boundary_ids);
1390 n_edges = parent_elem2->n_edges();
1391 for (
unsigned int edge = 0; edge < n_edges; ++edge)
1394 parent_elem2, edge, parent_boundary_ids);
1395 _displaced_mesh->get_boundary_info().add_edge(libmesh_elem2, edge, parent_boundary_ids);
1400 if (parent_elem->processor_id() ==
_mesh->processor_id())
1402 if (
_material_data[0]->getMaterialPropertyStorage().hasStatefulProperties())
1406 for (
unsigned int side = 0; side < parent_elem->n_sides(); ++side)
1408 _mesh->get_boundary_info().boundary_ids(parent_elem, side, parent_boundary_ids);
1409 std::vector<boundary_id_type>::iterator it_bd = parent_boundary_ids.begin();
1410 for (; it_bd != parent_boundary_ids.end(); ++it_bd)
1430 if (cei.
match(old_cei.second))
1434 _console <<
"XFEM set material properties for element: " << libmesh_elem->id()
1452 current_aux_solution,
1454 older_aux_solution);
1459 for (std::size_t i = 0; i < delete_elements.size(); ++i)
1461 Elem * elem_to_delete =
_mesh->elem_ptr(delete_elements[i]->
id());
1464 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
1468 delete cemit->second;
1476 elem_to_delete->nullify_neighbors();
1477 _mesh->get_boundary_info().remove(elem_to_delete);
1478 unsigned int deleted_elem_id = elem_to_delete->id();
1479 _mesh->delete_elem(elem_to_delete);
1481 _console <<
"XFEM deleted element: " << deleted_elem_id << std::endl;
1485 Elem * elem_to_delete2 =
_displaced_mesh->elem_ptr(delete_elements[i]->
id());
1486 elem_to_delete2->nullify_neighbors();
1492 for (std::map<
unsigned int, std::vector<const Elem *>>::iterator it =
1493 temporary_parent_children_map.begin();
1494 it != temporary_parent_children_map.end();
1497 std::vector<const Elem *> & sibling_elem_vec = it->second;
1504 if (it->first == elem_id)
1506 std::make_pair(sibling_elem_vec[0], sibling_elem_vec[1]));
1519 std::make_pair(elem, elem_pair));
1525 temporary_parent_children_map.clear();
1533 std::set<EFAElement *>::const_iterator sit;
1534 for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
1536 unsigned int eid = (*sit)->id();
1537 Elem * crack_tip_elem;
1538 std::map<unsigned int, Elem *>::iterator eit = efa_id_to_new_elem.find(eid);
1539 if (eit != efa_id_to_new_elem.end())
1540 crack_tip_elem = eit->second;
1542 crack_tip_elem =
_mesh->elem_ptr(eid);
1551 if ((*sit)->getParent() !=
nullptr)
1553 if (
_mesh->mesh_dimension() == 2)
1557 mooseError(
"EFAelem is not of EFAelement2D type");
1559 for (
unsigned int edge_id = 0; edge_id < efa_elem2d->
numEdges(); ++edge_id)
1561 for (
unsigned int en_iter = 0; en_iter < efa_elem2d->
numEdgeNeighbors(edge_id);
1565 if (edge_neighbor !=
nullptr && edge_neighbor->
id() == mie)
1570 else if (
_mesh->mesh_dimension() == 3)
1574 mooseError(
"EFAelem is not of EFAelement3D type");
1576 for (
unsigned int face_id = 0; face_id < efa_elem3d->
numFaces(); ++face_id)
1578 for (
unsigned int fn_iter = 0; fn_iter < efa_elem3d->
numFaceNeighbors(face_id);
1582 if (face_neighbor !=
nullptr && face_neighbor->
id() == mie)
1595 _console <<
"\nXFEM mesh cutting with element fragment algorithm complete\n";
1596 _console <<
"# new nodes: " << new_nodes.size() <<
"\n";
1597 _console <<
"# new elements: " << new_elements.size() <<
"\n";
1598 _console <<
"# deleted elements: " << delete_elements.size() <<
"\n";
1604 return mesh_changed;
1611 MeshBase * displaced_mesh)
const
1613 Point node_coor(0.0, 0.0, 0.0);
1614 std::vector<EFANode *> master_nodes;
1615 std::vector<Point> master_points;
1616 std::vector<double> master_weights;
1618 CEMElem->
getMasterInfo(CEMnode, master_nodes, master_weights);
1619 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1624 const Node * node = elem->node_ptr(local_node_id);
1626 node = displaced_mesh->node_ptr(node->id());
1627 Point node_p((*node)(0), (*node)(1), (*node)(2));
1628 master_points.push_back(node_p);
1631 mooseError(
"master nodes must be permanent");
1633 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1634 node_coor += master_weights[i] * master_points[i];
1642 Real phys_volfrac = 1.0;
1643 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1656 return phys_volfrac;
1662 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1680 unsigned int plane_id)
const
1683 Point planedata(0.0, 0.0, 0.0);
1684 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1692 if ((
unsigned int)quantity < 3)
1694 unsigned int index = (
unsigned int)quantity;
1696 comp = planedata(index);
1698 else if ((
unsigned int)quantity < 6)
1700 unsigned int index = (
unsigned int)quantity - 3;
1702 comp = planedata(index);
1705 mooseError(
"In get_cut_plane index out of range");
1742 std::vector<std::vector<Point>> & frag_faces,
1743 bool displaced_mesh)
const
1745 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1764 mooseError(
"EFAelem is not of EFAelement2D type");
1776 mooseError(
"EFAelem is not of EFAelement3D type");
1784 std::vector<std::vector<Point>> & frag_edges)
const
1791 mooseError(
"element ", elem->id(),
" has more than one fragment at this point");
1792 for (
unsigned int i = 0; i < CEMElem->
getFragment(0)->numEdges(); ++i)
1794 std::vector<Point> p_line(2, Point(0.0, 0.0, 0.0));
1797 frag_edges.push_back(p_line);
1805 std::vector<std::vector<Point>> & frag_faces)
const
1812 mooseError(
"element ", elem->id(),
" has more than one fragment at this point");
1813 for (
unsigned int i = 0; i < CEMElem->
getFragment(0)->numFaces(); ++i)
1816 std::vector<Point> p_line(num_face_nodes, Point(0.0, 0.0, 0.0));
1817 for (
unsigned int j = 0; j < num_face_nodes; ++j)
1819 frag_faces.push_back(p_line);
1833 if (xfem_qrule ==
"volfrac")
1835 else if (xfem_qrule ==
"moment_fitting")
1837 else if (xfem_qrule ==
"direct")
1866 bool have_weights =
false;
1870 mooseAssert(xfce !=
nullptr,
"Must have valid XFEMCutElem object here");
1872 have_weights =
true;
1874 Real ave_weight_multiplier = 0;
1875 for (
unsigned int i = 0; i < weights.
size(); ++i)
1876 ave_weight_multiplier += weights[i];
1877 ave_weight_multiplier /= weights.
size();
1882 for (
unsigned int i = 0; i < weights.
size(); ++i)
1883 weights[i] += amount_to_add;
1886 return have_weights;
1896 bool have_weights =
false;
1900 mooseAssert(xfce !=
nullptr,
"Must have valid XFEMCutElem object here");
1902 have_weights =
true;
1904 return have_weights;
1909 unsigned int plane_id,
1911 std::vector<Point> & intersectionPoints,
1912 bool displaced_mesh)
const
1914 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1928 std::vector<Point> & quad_pts,
1929 std::vector<Real> & quad_wts)
const
1931 Point p1 = intersection_points[0];
1932 Point p2 = intersection_points[1];
1935 std::size_t num_qpoints = 2;
1938 Real xi0 = -std::sqrt(1.0 / 3.0);
1939 Real xi1 = std::sqrt(1.0 / 3.0);
1941 quad_wts.resize(num_qpoints);
1942 quad_pts.resize(num_qpoints);
1944 Real integ_jacobian =
pow((p1 - p2).norm_sq(), 0.5) * 0.5;
1946 quad_wts[0] = 1.0 * integ_jacobian;
1947 quad_wts[1] = 1.0 * integ_jacobian;
1949 quad_pts[0] = (1.0 - xi0) / 2.0 * p1 + (1.0 + xi0) / 2.0 * p2;
1950 quad_pts[1] = (1.0 - xi1) / 2.0 * p1 + (1.0 + xi1) / 2.0 * p2;
1955 std::vector<Point> & quad_pts,
1956 std::vector<Real> & quad_wts)
const
1958 std::size_t nnd_pe = intersection_points.size();
1959 Point xcrd(0.0, 0.0, 0.0);
1960 for (std::size_t i = 0; i < nnd_pe; ++i)
1961 xcrd += intersection_points[i];
1964 quad_pts.resize(nnd_pe);
1965 quad_wts.resize(nnd_pe);
1969 for (std::size_t j = 0; j < nnd_pe; ++j)
1971 std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
1972 std::vector<Point> subtrig_points(3, Point(0.0, 0.0, 0.0));
1974 int jplus1 = j < nnd_pe - 1 ? j + 1 : 0;
1975 subtrig_points[0] = xcrd;
1976 subtrig_points[1] = intersection_points[j];
1977 subtrig_points[2] = intersection_points[jplus1];
1979 std::vector<std::vector<Real>> sg2;
1981 for (std::size_t l = 0; l < sg2.size(); ++l)
1984 std::vector<Real> tsg_line(3, 0.0);
1985 for (std::size_t k = 0; k < 3; ++k)
1987 tsg_line[0] += shape[k][2] * subtrig_points[k](0);
1988 tsg_line[1] += shape[k][2] * subtrig_points[k](1);
1989 tsg_line[2] += shape[k][2] * subtrig_points[k](2);
1991 quad_pts[j + l] = Point(tsg_line[0], tsg_line[1], tsg_line[2]);
1992 quad_wts[j + l] = sg2[l][3] * jac;
1999 const Node * node_to_store_from,
2001 std::map<unique_id_type, std::vector<Real>> & stored_solution,
2002 const NumericVector<Number> & current_solution,
2003 const NumericVector<Number> & old_solution,
2004 const NumericVector<Number> & older_solution)
2006 std::vector<dof_id_type> stored_solution_dofs =
getNodeSolutionDofs(node_to_store_from, sys);
2007 std::vector<Real> stored_solution_scratch;
2009 std::size_t stored_solution_size =
2011 stored_solution_scratch.reserve(stored_solution_size);
2015 for (
auto dof : stored_solution_dofs)
2016 stored_solution_scratch.push_back(current_solution(dof));
2020 for (
auto dof : stored_solution_dofs)
2021 stored_solution_scratch.push_back(old_solution(dof));
2023 for (
auto dof : stored_solution_dofs)
2024 stored_solution_scratch.push_back(older_solution(dof));
2027 if (stored_solution_scratch.size() > 0)
2028 stored_solution[node_to_store_to->unique_id()] = stored_solution_scratch;
2033 const Elem * elem_to_store_from,
2035 std::map<unique_id_type, std::vector<Real>> & stored_solution,
2036 const NumericVector<Number> & current_solution,
2037 const NumericVector<Number> & old_solution,
2038 const NumericVector<Number> & older_solution)
2041 std::vector<Real> stored_solution_scratch;
2043 std::size_t stored_solution_size =
2045 stored_solution_scratch.reserve(stored_solution_size);
2049 for (
auto dof : stored_solution_dofs)
2050 stored_solution_scratch.push_back(current_solution(dof));
2054 for (
auto dof : stored_solution_dofs)
2055 stored_solution_scratch.push_back(old_solution(dof));
2057 for (
auto dof : stored_solution_dofs)
2058 stored_solution_scratch.push_back(older_solution(dof));
2061 if (stored_solution_scratch.size() > 0)
2062 stored_solution[elem_to_store_to->unique_id()] = stored_solution_scratch;
2067 const std::map<unique_id_type, std::vector<Real>> & stored_solution,
2068 NumericVector<Number> & current_solution,
2069 NumericVector<Number> & old_solution,
2070 NumericVector<Number> & older_solution)
2072 for (
auto & node :
_mesh->local_node_ptr_range())
2074 auto mit = stored_solution.find(node->unique_id());
2075 if (mit != stored_solution.end())
2077 const std::vector<Real> & stored_node_solution = mit->second;
2080 stored_solution_dofs,
2087 for (
auto & elem : as_range(
_mesh->local_elements_begin(),
_mesh->local_elements_end()))
2089 auto mit = stored_solution.find(elem->unique_id());
2090 if (mit != stored_solution.end())
2092 const std::vector<Real> & stored_elem_solution = mit->second;
2095 stored_solution_dofs,
2105 const std::vector<dof_id_type> & stored_solution_dofs,
2106 NumericVector<Number> & current_solution,
2107 NumericVector<Number> & old_solution,
2108 NumericVector<Number> & older_solution)
2112 const auto old_solution_offset = stored_solution_dofs.size();
2113 const auto older_solution_offset = old_solution_offset * 2;
2115 for (std::size_t i = 0; i < stored_solution_dofs.size(); ++i)
2117 current_solution.set(stored_solution_dofs[i], stored_solution[i]);
2120 old_solution.set(stored_solution_dofs[i], stored_solution[old_solution_offset + i]);
2121 older_solution.set(stored_solution_dofs[i], stored_solution[older_solution_offset + i]);
2126std::vector<dof_id_type>
2131 std::vector<dof_id_type> solution_dofs;
2132 solution_dofs.reserve(
vars.size());
2133 for (
auto var :
vars)
2135 if (!var->isNodal())
2138 if (var_subdomains.empty() || var_subdomains.find(sid) != var_subdomains.end())
2140 unsigned int n_comp = elem->n_comp(sys.
number(), var->number());
2141 for (
unsigned int icomp = 0; icomp < n_comp; ++icomp)
2143 dof_id_type elem_dof = elem->dof_number(sys.
number(), var->number(), icomp);
2144 solution_dofs.push_back(elem_dof);
2149 return solution_dofs;
2152std::vector<dof_id_type>
2157 std::vector<dof_id_type> solution_dofs;
2158 solution_dofs.reserve(
vars.size());
2159 for (
auto var :
vars)
2164 std::set<SubdomainID> intersect;
2165 set_intersection(var_subdomains.begin(),
2166 var_subdomains.end(),
2169 std::inserter(intersect, intersect.begin()));
2170 if (var_subdomains.empty() || !intersect.empty())
2172 unsigned int n_comp = node->n_comp(sys.
number(), var->number());
2173 for (
unsigned int icomp = 0; icomp < n_comp; ++icomp)
2175 dof_id_type node_dof = node->dof_number(sys.
number(), var->number(), icomp);
2176 solution_dofs.push_back(node_dof);
2181 return solution_dofs;
2189 std::set<unsigned int> elems = gcmit.second;
2190 if (elems.find(elem->id()) != elems.end())
2201 const auto & elem_props = storage.
props(state).at(elem);
2202 auto & serialized_props =
_geom_cut_elems[elem]._elem_material_properties[state - 1];
2203 serialized_props.clear();
2204 for (
const auto & side_props_pair : elem_props)
2206 const auto side = side_props_pair.first;
2207 std::ostringstream oss;
2209 serialized_props[side].assign(oss.str());
2226 bool need_boundary_materials =
false;
2227 for (
unsigned int side = 0; side < child_elem->n_sides(); ++side)
2229 std::vector<boundary_id_type> elem_boundary_ids;
2230 _mesh->get_boundary_info().boundary_ids(child_elem, side, elem_boundary_ids);
2231 for (
auto bdid : elem_boundary_ids)
2233 need_boundary_materials =
true;
2237 if (need_boundary_materials)
2252 const auto & serialized_props = cached_props[state - 1];
2253 for (
const auto & [side, serialized_side_props] : serialized_props)
2255 std::istringstream iss;
2256 iss.str(serialized_side_props);
2269 const Elem * elem_from,
2270 std::unordered_map<const Elem *, Xfem::CutElemInfo> & cached_cei)
const
2273 mooseAssert(cached_cei.count(elem_from) > 0,
"XFEM: Unable to find cached material properties.");
2282 bool need_boundary_materials =
false;
2283 for (
unsigned int side = 0; side < elem->n_sides(); ++side)
2285 std::vector<boundary_id_type> elem_boundary_ids;
2286 _mesh->get_boundary_info().boundary_ids(elem, side, elem_boundary_ids);
2287 for (
auto bdid : elem_boundary_ids)
2289 need_boundary_materials =
true;
2293 if (need_boundary_materials)
2302 const Elem * cut_elem,
2303 const Elem * parent_elem)
const
2306 parent_elem = cut_elem;
2316 for (
auto i : e0->node_index_range())
2318 return e0->node_ptr(i);
2319 mooseError(
"cannot find a physical node in the current element");
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
void dataLoad(std::istream &stream, LineSegment &l, void *context)
void dataStore(std::ostream &stream, LineSegment &l, void *context)
void mooseError(Args &&... args)
const ExecFlagType EXEC_XFEM_MARK
Exec flag used to execute MooseObjects while elements are being marked for cutting by XFEM.
unsigned int CutSubdomainID
void ErrorVector unsigned int
const libMesh::QBase *const & qRule() const
virtual libMesh::System & system() override
virtual void serializeSolution()
const ConsoleStream _console
bool isPartialOverlap(const EFAEdge &other) const
EFANode * getNode(unsigned int index) const
EFANode * getEmbeddedNode(unsigned int index) const
bool hasIntersection() const
virtual unsigned int numFragments() const
EFAFragment2D * getFragment(unsigned int frag_id) const
unsigned int getCrackTipSplitElementID() const
bool isEdgePhantom(unsigned int edge_id) const
EFANode * getTipEmbeddedNode() const
EFAEdge * getEdge(unsigned int edge_id) const
unsigned int numEdges() const
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
unsigned int numEdgeNeighbors(unsigned int edge_id) const
virtual bool isFinalCut() const
EFAElement2D * getEdgeNeighbor(unsigned int edge_id, unsigned int neighbor_id) const
unsigned int getTipEdgeID() const
EFAFace * getFragmentFace(unsigned int frag_id, unsigned int face_id) const
EFAElement3D * getFaceNeighbor(unsigned int face_id, unsigned int neighbor_id) const
unsigned int numFaces() const
virtual unsigned int numFragments() const
EFAFragment3D * getFragment(unsigned int frag_id) const
bool isFacePhantom(unsigned int face_id) const
unsigned int numFaceNeighbors(unsigned int face_id) const
virtual void getMasterInfo(EFANode *node, std::vector< EFANode * > &master_nodes, std::vector< double > &master_weights) const =0
virtual bool isPartial() const =0
unsigned int getLocalNodeIndex(EFANode *node) const
unsigned int numNodes() const
EFANode * getNode(unsigned int node_id) const
std::vector< unsigned int > getInteriorEdgeID() const
unsigned int numEdges() const
bool isSecondaryInteriorEdge(unsigned int edge_id) const
bool isThirdInteriorFace(unsigned int face_id) const
void addElemNodeIntersection(unsigned int elemid, unsigned int nodeid)
void updatePhysicalLinksAndFragments()
const std::vector< EFANode * > & getNewNodes()
EFAElement * add3DElement(const std::vector< unsigned int > &quad, unsigned int id)
EFAElement * getElemByID(unsigned int id)
void addFragFaceIntersection(unsigned int ElemID, unsigned int FragFaceID, const std::vector< unsigned int > &FragFaceEdgeID, const std::vector< double > &position)
const std::vector< EFAElement * > & getChildElements()
void addElemFaceIntersection(unsigned int elemid, unsigned int faceid, const std::vector< unsigned int > &edgeid, const std::vector< double > &position)
void updateEdgeNeighbors()
void restoreFragmentInfo(EFAElement *const elem, const EFAElement *const from_elem)
void addElemEdgeIntersection(unsigned int elemid, unsigned int edgeid, double position)
const std::set< EFAElement * > & getCrackTipElements()
EFAElement * add2DElement(const std::vector< unsigned int > &quad, unsigned int id)
bool addFragEdgeIntersection(unsigned int elemid, unsigned int frag_edge_id, double position)
void updateTopology(bool mergeUncutVirtualEdges=true)
const std::vector< EFAElement * > & getParentElements()
void initCrackTipTopology()
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
virtual void execute(const ExecFlagType &exec_type)
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, const THREAD_ID tid)
virtual int & timeStep() const
virtual bool isTransient() const override
bool shouldHealMesh() const
Should the elements cut by this cutting object be healed in the current time step?
void setInterfaceID(unsigned int interface_id)
Set the interface ID for this cutting object.
virtual CutSubdomainID getCutSubdomainID(const Node *) const
Get CutSubdomainID telling which side the node belongs to relative to the cut.
bool hasStatefulProperties() const
const PropsType & props(const unsigned int state=0) const
libMesh::IntRange< unsigned int > statefulIndexRange() const
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
unsigned int size() const
virtual bool isDistributedMesh() const
const std::set< SubdomainID > & getNodeBlockIds(const Node &node) const
bool isSemiLocal(Node *const node) const
const std::set< SubdomainID > & getSubdomainsForVar(unsigned int var_number) const
unsigned int number() const
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
NumericVector< Number > & solutionOld()
NumericVector< Number > & solutionOlder()
virtual bool cutElementByCrackGrowthIncrement(const Elem *elem, std::vector< CutEdgeForCrackGrowthIncr > &cut_edges, Real time)
virtual void getCrackTipOriginAndDirection(unsigned tip_id, Point &origin, Point &direction) const =0
virtual const EFAElement * getEFAElement() const =0
void getWeightMultipliers(MooseArray< Real > &weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points)
virtual Point getCutPlaneNormal(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
void getFaceWeightMultipliers(MooseArray< Real > &face_weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points, unsigned int side)
Real getPhysicalVolumeFraction() const
Returns the volume fraction of the element fragment.
virtual Point getCutPlaneOrigin(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
virtual void getIntersectionInfo(unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, MeshBase *displaced_mesh=nullptr) const =0
virtual void computePhysicalVolumeFraction()=0
Computes the volume fraction of the element fragment.
bool isPointPhysical(const Point &p) const
virtual void getFragmentFaces(std::vector< std::vector< Point > > &frag_faces, MeshBase *displaced_mesh=nullptr) const =0
MeshBase * _displaced_mesh
std::vector< MaterialData * > _material_data
FEProblemBase * _fe_problem
std::vector< MaterialData * > _bnd_material_data
void storeMaterialPropertiesForElementHelper(const Elem *elem, MaterialPropertyStorage &storage)
virtual void getXFEMIntersectionInfo(const Elem *elem, unsigned int plane_id, Point &normal, std::vector< Point > &intersectionPoints, bool displaced_mesh=false) const
std::vector< const GeometricCutUserObject * > _geometric_cuts
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.
virtual bool updateHeal() override
EFAElement2D * getEFAElem2D(const Elem *elem)
Get the EFAElement2D object for a specified libMesh element.
bool markCutFacesByState()
std::map< const GeometricCutUserObject *, unsigned int > _geom_marker_id_map
Data structure for storing the GeommetricCutUserObjects and their corresponding id.
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.
virtual void initSolution(const std::vector< std::shared_ptr< NonlinearSystemBase > > &nl, AuxiliarySystem &aux) override
virtual void getXFEMqRuleOnSurface(std::vector< Point > &intersection_points, std::vector< Point > &quad_pts, std::vector< Real > &quad_wts) const
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.
void storeCrackTipOriginAndDirection()
Real _crack_growth_increment
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.
void loadMaterialPropertiesForElementHelper(const Elem *elem, const Xfem::CachedMaterialProperties &cached_props, MaterialPropertyStorage &storage) const
Load the material properties.
void addGeometricCut(GeometricCutUserObject *geometric_cut)
bool markCutFacesByGeometry()
std::map< unsigned int, std::set< unsigned int > > _geom_marker_id_elems
Data structure for storing the elements cut by specific geometric cutters.
virtual void getXFEMqRuleOnLine(std::vector< Point > &intersection_points, std::vector< Point > &quad_pts, std::vector< Real > &quad_wts) const
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_displaced_elems
bool cutMeshWithEFA(const std::vector< std::shared_ptr< NonlinearSystemBase > > &nl, AuxiliarySystem &aux)
std::map< unique_id_type, XFEMCutElem * > _cut_elem_map
bool markCutEdgesByGeometry()
ElementFragmentAlgorithm _efa_mesh
bool isElemCut(const Elem *elem, XFEMCutElem *&xfce) const
void setDebugOutputLevel(unsigned int debug_output_level)
Controls amount of debugging information output.
void setMinWeightMultiplier(Real min_weight_multiplier)
Controls the minimum average weight multiplier for each element.
Point getEFANodeCoords(EFANode *CEMnode, EFAElement *CEMElem, const Elem *elem, MeshBase *displaced_mesh=nullptr) const
int _state_marked_t_step
The timestep index at which the state marks were added.
Real getPhysicalVolumeFraction(const Elem *elem) const
Get the volume fraction of an element that is physical.
std::map< const Elem *, RealVectorValue > _state_marked_elems
void addStateMarkedFrag(unsigned int elem_id, RealVectorValue &normal)
Xfem::XFEM_QRULE _XFEM_qrule
std::map< unsigned int, ElementPairLocator::ElementPairList > _sibling_elems
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::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.
bool isElemAtCrackTip(const Elem *elem) const
virtual bool getXFEMFaceWeights(MooseArray< Real > &weights, const Elem *elem, QBase *qrule, const MooseArray< Point > &q_points, unsigned int side) override
bool healMesh()
Potentially heal the mesh by merging some of the pairs of partial elements cut by XFEM back into sing...
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.
void getFragmentFaces(const Elem *elem, std::vector< std::vector< Point > > &frag_faces, bool displaced_mesh=false) const
std::map< const Elem *, unsigned int > _state_marked_elem_sides
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...
void setCrackGrowthMethod(bool use_crack_growth_increment, Real crack_growth_increment)
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 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.
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.
std::unordered_map< const Elem *, Xfem::CutElemInfo > _geom_cut_elems
All geometrically cut elements and their CutElemInfo during the current execution of XFEM_MARK.
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 clearGeomMarkedElems()
Clear out the list of elements to be marked for cutting.
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.
void getCrackTipOrigin(std::map< unsigned int, const Elem * > &elem_id_crack_tip, std::vector< Point > &crack_front_points)
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)
EFAElement3D * getEFAElem3D(const Elem *elem)
Get the EFAElement3D object for a specified libMesh element.
bool markCutEdgesByState(Real time)
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.
void getFragmentEdges(const Elem *elem, EFAElement2D *CEMElem, std::vector< std::vector< Point > > &frag_edges) const
Xfem::XFEM_QRULE & getXFEMQRule()
void addStateMarkedElem(unsigned int elem_id, RealVectorValue &normal)
virtual bool update(Real time, const std::vector< std::shared_ptr< NonlinearSystemBase > > &nl, AuxiliarySystem &aux) override
virtual bool getXFEMWeights(MooseArray< Real > &weights, const Elem *elem, QBase *qrule, const MooseArray< Point > &q_points) override
std::set< const Elem * > _crack_tip_elems
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,...
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.
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.
unsigned int _debug_output_level
Controls amount of debugging output information 0: None 1: Summary 2: Details on modifications to mes...
XFEM(const InputParameters ¶ms)
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< Point > > _elem_crack_origin_direction_map
const GeometricCutUserObject * getGeometricCutForElem(const Elem *elem) const
Get the GeometricCutUserObject associated with an element.
void setXFEMQRule(std::string &xfem_qrule)
bool initCutIntersectionEdge(Point cut_origin, RealVectorValue cut_normal, Point &edge_p1, Point &edge_p2, Real &dist)
Real _min_weight_multiplier
The minimum average multiplier applied by XFEM to the standard quadrature weights to integrate partia...
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...
std::set< const Elem * > _crack_tip_elems_to_be_healed
std::set< const Elem * > _state_marked_frags
bool _use_crack_growth_increment
void clearStateMarkedElems()
void make_elems_parallel_consistent(MeshBase &)
void make_nodes_parallel_consistent(MeshBase &)
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices)
unsigned int n_points() const
std::unique_ptr< NumericVector< Number > > current_local_solution
void stdQuadr2D(unsigned int nen, unsigned int iord, std::vector< std::vector< Real > > &sg2)
void shapeFunc2D(unsigned int nen, std::vector< Real > &ss, std::vector< Point > &xl, std::vector< std::vector< Real > > &shp, Real &xsj, bool natl_flg)
std::array< std::unordered_map< unsigned int, std::string >, 2 > CachedMaterialProperties
Convenient typedef for local storage of stateful material properties.
Information about a cut element.
CachedMaterialProperties _elem_material_properties
bool match(const CutElemInfo &rhs)
CachedMaterialProperties _bnd_material_properties
Data structure describing geometrically described cut through 2D element.
Data structure describing geometrically described cut through 3D element.
Real distance(const Point &p)