25 #include "AuxiliarySystem.h"
26 #include "MooseVariable.h"
27 #include "NonlinearSystem.h"
28 #include "FEProblem.h"
30 #include "MooseUtils.h"
32 #include "libmesh/mesh_communication.h"
33 #include "libmesh/partitioner.h"
36 : XFEMInterface(params), _efa_mesh(Moose::out), _debug_output_level(1)
38 #ifndef LIBMESH_ENABLE_UNIQUE_ID
39 mooseError(
"MOOSE requires unique ids to be enabled in libmesh (configure with "
40 "--enable-unique-id) to use XFEM!");
47 for (std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
_cut_elem_map.begin();
65 std::vector<Point> & crack_front_points)
67 elem_id_crack_tip.clear();
68 crack_front_points.clear();
71 unsigned int crack_tip_index = 0;
74 std::map<unsigned int, const Elem *> elem_id_map;
77 for (std::map<
const Elem *, std::vector<Point>>::iterator mit1 =
82 unsigned int elem_id = mit1->first->id();
85 elem_id_map[m] = mit1->first;
90 elem_id_map[elem_id] = mit1->first;
94 for (std::map<unsigned int, const Elem *>::iterator mit1 = elem_id_map.begin();
95 mit1 != elem_id_map.end();
98 const Elem * elem = mit1->second;
99 std::map<const Elem *, std::vector<Point>>::iterator mit2 =
103 elem_id_crack_tip[crack_tip_index] = mit2->first;
104 crack_front_points[crack_tip_index] =
114 Elem * elem = _mesh->elem_ptr(elem_id);
115 std::map<const Elem *, RealVectorValue>::iterator mit;
118 mooseError(
" ERROR: element ", elem->id(),
" already marked for crack growth.");
126 Elem * elem = _mesh->elem_ptr(elem_id);
127 std::map<const Elem *, unsigned int>::iterator mit;
131 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;
147 " 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)
198 EFAElement2D * CEMElem = dynamic_cast<EFAElement2D *>(*sit);
202 Point origin(0, 0, 0);
203 Point direction(0, 0, 0);
205 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
206 it =
_cut_elem_map.find(_mesh->elem_ptr(cts_id)->unique_id());
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;
236 _mesh->update_parallel_id_counts();
237 MeshCommunication().make_elems_parallel_consistent(*_mesh);
238 MeshCommunication().make_nodes_parallel_consistent(*_mesh);
241 _mesh->allow_renumbering(
false);
242 _mesh->skip_partitioning(
true);
243 _mesh->prepare_for_use();
249 _displaced_mesh->update_parallel_id_counts();
250 MeshCommunication().make_elems_parallel_consistent(*_displaced_mesh);
251 MeshCommunication().make_nodes_parallel_consistent(*_displaced_mesh);
252 _displaced_mesh->allow_renumbering(
false);
253 _displaced_mesh->skip_partitioning(
true);
254 _displaced_mesh->prepare_for_use();
265 XFEM::update(Real time, NonlinearSystemBase & nl, AuxiliarySystem & aux)
267 if (_moose_mesh->isDistributedMesh())
268 mooseError(
"Use of XFEM with distributed mesh is not yet supported");
270 bool mesh_changed =
false;
291 _mesh->allow_renumbering(
false);
292 _mesh->skip_partitioning(
true);
293 _mesh->prepare_for_use();
299 _displaced_mesh->allow_renumbering(
false);
300 _displaced_mesh->skip_partitioning(
true);
301 _displaced_mesh->prepare_for_use();
315 nl.serializeSolution();
316 aux.serializeSolution();
317 NumericVector<Number> & current_solution = *nl.system().current_local_solution;
318 NumericVector<Number> & old_solution = nl.solutionOld();
319 NumericVector<Number> & older_solution = nl.solutionOlder();
320 NumericVector<Number> & current_aux_solution = *aux.system().current_local_solution;
321 NumericVector<Number> & old_aux_solution = aux.solutionOld();
322 NumericVector<Number> & older_aux_solution = aux.solutionOlder();
328 current_solution.close();
329 old_solution.close();
330 older_solution.close();
331 current_aux_solution.close();
332 old_aux_solution.close();
333 older_aux_solution.close();
345 for (
auto & elem : _mesh->element_ptr_range())
347 std::vector<unsigned int> quad;
348 for (
unsigned int i = 0; i < elem->n_nodes(); ++i)
349 quad.push_back(elem->node_id(i));
350 if (_mesh->mesh_dimension() == 2)
352 else if (_mesh->mesh_dimension() == 3)
355 mooseError(
"XFEM only works for 2D and 3D");
359 for (
auto & elem : _mesh->element_ptr_range())
361 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
_cut_elem_map.find(elem->unique_id());
380 bool marked_sides =
false;
381 if (_mesh->mesh_dimension() == 2)
386 else if (_mesh->mesh_dimension() == 3)
397 bool marked_edges =
false;
398 bool marked_nodes =
false;
402 for (
const auto & gmei : gme.second)
406 for (
unsigned int i = 0; i < gmei._elem_cut_edges.size(); ++i)
409 gmei._elem_cut_edges[i]._host_side_id))
412 gmei._elem_cut_edges[i]._host_side_id,
413 gmei._elem_cut_edges[i]._distance);
418 for (
unsigned int i = 0; i < gmei._elem_cut_nodes.size(); ++i)
424 for (
unsigned int i = 0; i < gmei._frag_cut_edges.size();
428 gmei._frag_cut_edges[i]._host_side_id))
431 gmei._frag_cut_edges[i]._host_side_id,
432 gmei._frag_cut_edges[i]._distance))
443 return marked_edges || marked_nodes;
451 Point crack_tip_origin,
452 Point crack_tip_direction,
453 Real & distance_keep,
454 unsigned int & edge_id_keep,
457 std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
458 Point edge1(0.0, 0.0, 0.0);
459 Point edge2(0.0, 0.0, 0.0);
460 Point left_angle(0.0, 0.0, 0.0);
461 Point right_angle(0.0, 0.0, 0.0);
462 Point left_angle_normal(0.0, 0.0, 0.0);
463 Point right_angle_normal(0.0, 0.0, 0.0);
464 Point crack_direction_normal(0.0, 0.0, 0.0);
465 Point edge1_to_tip(0.0, 0.0, 0.0);
466 Point edge2_to_tip(0.0, 0.0, 0.0);
467 Point edge1_to_tip_normal(0.0, 0.0, 0.0);
468 Point edge2_to_tip_normal(0.0, 0.0, 0.0);
470 Real cos_45 = std::cos(45.0 / 180.0 * 3.14159);
471 Real sin_45 = std::sin(45.0 / 180.0 * 3.14159);
473 left_angle(0) = cos_45 * crack_tip_direction(0) - sin_45 * crack_tip_direction(1);
474 left_angle(1) = sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
476 right_angle(0) = cos_45 * crack_tip_direction(0) + sin_45 * crack_tip_direction(1);
477 right_angle(1) = -sin_45 * crack_tip_direction(0) + cos_45 * crack_tip_direction(1);
479 left_angle_normal(0) = -left_angle(1);
480 left_angle_normal(1) = left_angle(0);
482 right_angle_normal(0) = -right_angle(1);
483 right_angle_normal(1) = right_angle(0);
485 crack_direction_normal(0) = -crack_tip_direction(1);
486 crack_direction_normal(1) = crack_tip_direction(0);
488 Real angle_min = 0.0;
490 unsigned int nsides = CEMElem->
numEdges();
492 for (
unsigned int i = 0; i < nsides; ++i)
499 edge1_to_tip = (edge_ends[0] * 0.95 + edge_ends[1] * 0.05) - crack_tip_origin;
500 edge2_to_tip = (edge_ends[0] * 0.05 + edge_ends[1] * 0.95) - crack_tip_origin;
502 edge1_to_tip /=
pow(edge1_to_tip.norm_sq(), 0.5);
503 edge2_to_tip /=
pow(edge2_to_tip.norm_sq(), 0.5);
505 edge1_to_tip_normal(0) = -edge1_to_tip(1);
506 edge1_to_tip_normal(1) = edge1_to_tip(0);
508 edge2_to_tip_normal(0) = -edge2_to_tip(1);
509 edge2_to_tip_normal(1) = edge2_to_tip(0);
511 Real angle_edge1_normal = edge1_to_tip_normal * normal;
512 Real angle_edge2_normal = edge2_to_tip_normal * normal;
514 if (std::abs(angle_edge1_normal) > std::abs(angle_min) &&
515 (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
518 distance_keep = 0.05;
519 normal_keep = edge1_to_tip_normal;
520 angle_min = angle_edge1_normal;
522 else if (std::abs(angle_edge2_normal) > std::abs(angle_min) &&
523 (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
526 distance_keep = 0.95;
527 normal_keep = edge2_to_tip_normal;
528 angle_min = angle_edge2_normal;
532 crack_tip_origin, left_angle_normal, edge_ends[0], edge_ends[1], distance) &&
535 if (std::abs(left_angle_normal * normal) > std::abs(angle_min) &&
536 (edge1_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
539 distance_keep = distance;
540 normal_keep = left_angle_normal;
541 angle_min = left_angle_normal * normal;
545 crack_tip_origin, right_angle_normal, edge_ends[0], edge_ends[1], distance) &&
548 if (std::abs(right_angle_normal * normal) > std::abs(angle_min) &&
549 (edge2_to_tip * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
552 distance_keep = distance;
553 normal_keep = right_angle_normal;
554 angle_min = right_angle_normal * normal;
558 crack_direction_normal,
564 if (std::abs(crack_direction_normal * normal) > std::abs(angle_min) &&
565 (crack_tip_direction * crack_tip_direction) > std::cos(45.0 / 180.0 * 3.14159))
568 distance_keep = distance;
569 normal_keep = crack_direction_normal;
570 angle_min = crack_direction_normal * normal;
577 if ((distance_keep - 0.05) < 0.0)
579 distance_keep = 0.05;
581 else if ((distance_keep - 0.95) > 0.0)
583 distance_keep = 0.95;
590 bool marked_edges =
false;
591 for (std::map<const Elem *, RealVectorValue>::iterator pmeit =
_state_marked_elems.begin();
595 const Elem * elem = pmeit->first;
596 RealVectorValue normal = pmeit->second;
600 if (volfrac_elem < 0.25)
608 unsigned int nsides = CEMElem->
numEdges();
609 unsigned int orig_cut_side_id = 999999;
610 Real orig_cut_distance = -1.0;
615 Point crack_tip_origin(0, 0, 0);
616 Point crack_tip_direction(0, 0, 0);
621 if (orig_cut_side_id < nsides)
623 orig_edge = CEMElem->
getEdge(orig_cut_side_id);
627 mooseError(
"element ", elem->id(),
" has no valid crack-tip edge");
630 std::map<const Elem *, std::vector<Point>>::iterator ecodm =
634 crack_tip_origin = (ecodm->second)[0];
635 crack_tip_direction = (ecodm->second)[1];
638 mooseError(
"element ", elem->id(),
" cannot find its crack tip origin and direction.");
642 std::map<const Elem *, unsigned int>::iterator mit1;
644 std::set<const Elem *>::iterator mit2;
649 orig_cut_side_id = mit1->second;
653 orig_cut_distance = 0.5;
655 orig_edge = CEMElem->
getEdge(orig_cut_side_id);
658 Point elem_center(0.0, 0.0, 0.0);
660 for (
unsigned int i = 0; i < nsides; ++i)
665 elem_center /= nsides * 2.0;
669 crack_tip_origin = edge_center;
670 crack_tip_direction = elem_center - edge_center;
671 crack_tip_direction /=
pow(crack_tip_direction.norm_sq(), 0.5);
679 mooseError(
"element ",
681 " flagged for a secondary crack, but has ",
685 if (interior_edge_id.size() == 1)
686 orig_cut_side_id = interior_edge_id[0];
690 orig_cut_distance = 0.5;
694 Point elem_center(0.0, 0.0, 0.0);
697 for (
unsigned int i = 0; i < nsides_frag; ++i)
704 elem_center /= nsides_frag * 2.0;
708 crack_tip_origin = edge_center;
709 crack_tip_direction = elem_center - edge_center;
710 crack_tip_direction /=
pow(crack_tip_direction.norm_sq(), 0.5);
713 mooseError(
"element ",
715 " flagged for state-based growth, but has no edge intersections");
718 Point cut_origin(0.0, 0.0, 0.0);
722 mooseError(
"element ", elem->id(),
" does not have valid orig_node");
725 std::vector<Point> edge_ends(2, Point(0.0, 0.0, 0.0));
726 Point edge1(0.0, 0.0, 0.0);
727 Point edge2(0.0, 0.0, 0.0);
728 Point cut_edge_point(0.0, 0.0, 0.0);
729 bool find_compatible_direction =
false;
730 unsigned int edge_id_keep = 0;
731 Real distance_keep = 0.0;
732 Point normal_keep(0.0, 0.0, 0.0);
734 bool edge_cut =
false;
736 for (
unsigned int i = 0; i < nsides; ++i)
743 crack_tip_origin, normal, edge_ends[0], edge_ends[1], distance) &&
746 cut_edge_point = distance * edge_ends[1] + (1.0 - distance) * edge_ends[0];
747 distance_keep = distance;
749 normal_keep = normal;
756 Point between_two_cuts = (cut_edge_point - crack_tip_origin);
757 between_two_cuts /=
pow(between_two_cuts.norm_sq(), 0.5);
758 Real angle_between_two_cuts = between_two_cuts * crack_tip_direction;
760 if (angle_between_two_cuts > std::cos(45.0 / 180.0 * 3.14159))
761 find_compatible_direction =
true;
763 if (!find_compatible_direction && edge_cut)
780 Point growth_direction(0.0, 0.0, 0.0);
782 growth_direction(0) = -normal_keep(1);
783 growth_direction(1) = normal_keep(0);
785 if (growth_direction * crack_tip_direction < 1.0e-10)
786 growth_direction *= (-1.0);
788 Real x0 = crack_tip_origin(0);
789 Real y0 = crack_tip_origin(1);
795 for (
const auto & elem : _mesh->element_ptr_range())
797 std::vector<CutEdgeForCrackGrowthIncr> elem_cut_edges;
807 for (
unsigned int i = 0; i < elem_cut_edges.size(); ++i)
810 elem_cut_edges[i]._host_side_id))
813 elem->id(), elem_cut_edges[i]._host_side_id, elem_cut_edges[i]._distance);
832 crack_tip_origin, normal, edge_ends[0], edge_ends[1], distance) &&
854 bool marked_faces =
false;
858 for (
const auto & gmei : gme.second)
862 for (
unsigned int i = 0; i < gmei._elem_cut_faces.size(); ++i)
864 if (!EFAElem->
isFacePhantom(gmei._elem_cut_faces[i]._face_id))
867 gmei._elem_cut_faces[i]._face_id,
868 gmei._elem_cut_faces[i]._face_edge,
869 gmei._elem_cut_faces[i]._position);
874 for (
unsigned int i = 0; i < gmei._frag_cut_faces.size();
880 gmei._frag_cut_faces[i]._face_id,
881 gmei._frag_cut_faces[i]._face_edge,
882 gmei._frag_cut_faces[i]._position);
895 bool marked_faces =
false;
902 Point cut_origin, RealVectorValue cut_normal, Point & edge_p1, Point & edge_p2, Real & dist)
905 bool does_intersect =
false;
906 Point origin2p1 = edge_p1 - cut_origin;
907 Real plane2p1 = cut_normal(0) * origin2p1(0) + cut_normal(1) * origin2p1(1);
908 Point origin2p2 = edge_p2 - cut_origin;
909 Real plane2p2 = cut_normal(0) * origin2p2(0) + cut_normal(1) * origin2p2(1);
911 if (plane2p1 * plane2p2 < 0.0)
913 dist = -plane2p1 / (plane2p2 - plane2p1);
914 does_intersect =
true;
916 return does_intersect;
922 bool mesh_changed =
false;
924 std::set<Node *> nodes_to_delete;
925 std::set<Node *> nodes_to_delete_displaced;
926 std::set<unsigned int> cutelems_to_delete;
927 unsigned int deleted_elem_count = 0;
928 std::vector<std::string> healed_geometric_cuts;
937 Elem * elem1 = const_cast<Elem *>(it.first);
938 Elem * elem2 = const_cast<Elem *>(it.second);
940 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
946 cutelems_to_delete.insert(elem1->unique_id());
948 for (
unsigned int in = 0; in < elem1->n_nodes(); ++in)
950 Node * e1node = elem1->node_ptr(in);
951 Node * e2node = elem2->node_ptr(in);
955 elem1->set_node(in) = e2node;
956 nodes_to_delete.insert(e1node);
958 else if (e1node != e2node)
959 nodes_to_delete.insert(e2node);
963 mooseError(
"Could not find XFEMCutElem for element to be kept in healing");
967 Elem * elem1_displaced = _displaced_mesh->elem_ptr(it.first->id());
968 Elem * elem2_displaced = _displaced_mesh->elem_ptr(it.second->id());
970 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
976 for (
unsigned int in = 0; in < elem1_displaced->n_nodes(); ++in)
978 Node * e1node_displaced = elem1_displaced->node_ptr(in);
979 Node * e2node_displaced = elem2_displaced->node_ptr(in);
981 e1node_displaced != e2node_displaced)
983 elem1_displaced->set_node(in) = e2node_displaced;
984 nodes_to_delete_displaced.insert(e1node_displaced);
986 else if (e1node_displaced != e2node_displaced)
987 nodes_to_delete_displaced.insert(e2node_displaced);
991 mooseError(
"Could not find XFEMCutElem for element to be kept in healing");
993 elem2_displaced->nullify_neighbors();
994 _displaced_mesh->boundary_info->remove(elem2_displaced);
995 _displaced_mesh->delete_elem(elem2_displaced);
998 cutelems_to_delete.insert(elem2->unique_id());
999 elem2->nullify_neighbors();
1000 _mesh->boundary_info->remove(elem2);
1001 unsigned int deleted_elem_id = elem2->id();
1002 _mesh->delete_elem(elem2);
1005 if (deleted_elem_count == 0)
1007 _console <<
"XFEM healing deleted element: " << deleted_elem_id <<
"\n";
1009 ++deleted_elem_count;
1010 mesh_changed =
true;
1015 for (
auto & sit : nodes_to_delete)
1017 Node * node_to_delete = sit;
1018 dof_id_type deleted_node_id = node_to_delete->id();
1019 _mesh->boundary_info->remove(node_to_delete);
1020 _mesh->delete_node(node_to_delete);
1022 _console <<
"XFEM healing deleted node: " << deleted_node_id <<
"\n";
1025 if (_displaced_mesh)
1027 for (
auto & sit : nodes_to_delete_displaced)
1029 Node * node_to_delete = sit;
1030 _displaced_mesh->boundary_info->remove(node_to_delete);
1031 _displaced_mesh->delete_node(node_to_delete);
1035 for (
auto & ced : cutelems_to_delete)
1046 if (_displaced_mesh)
1063 _console <<
"\nXFEM mesh healing complete\n";
1064 _console <<
"Names of healed geometric cut objects: ";
1065 for (
auto geomcut : healed_geometric_cuts)
1066 _console << geomcut <<
" ";
1068 _console <<
"# deleted nodes: " << nodes_to_delete.size() <<
"\n";
1069 _console <<
"# deleted elements: " << deleted_elem_count <<
"\n";
1070 _console << std::flush;
1073 return mesh_changed;
1079 std::map<unsigned int, Node *> efa_id_to_new_node;
1080 std::map<unsigned int, Node *> efa_id_to_new_node2;
1081 std::map<unsigned int, Elem *> efa_id_to_new_elem;
1089 _console <<
"\nXFEM Element fragment algorithm mesh prior to cutting:\n";
1090 _console << std::flush;
1098 _console <<
"\nXFEM Element fragment algorithm mesh after cutting:\n";
1099 _console << std::flush;
1107 bool mesh_changed = (new_nodes.size() + new_elements.size() + delete_elements.size() > 0);
1112 nl.serializeSolution();
1113 aux.serializeSolution();
1117 NumericVector<Number> & current_solution = *nl.system().current_local_solution;
1118 NumericVector<Number> & old_solution = nl.solutionOld();
1119 NumericVector<Number> & older_solution = nl.solutionOlder();
1120 NumericVector<Number> & current_aux_solution = *aux.system().current_local_solution;
1121 NumericVector<Number> & old_aux_solution = aux.solutionOld();
1122 NumericVector<Number> & older_aux_solution = aux.solutionOlder();
1124 std::map<Node *, Node *> new_nodes_to_parents;
1127 for (
unsigned int i = 0; i < new_nodes.size(); ++i)
1129 unsigned int new_node_id = new_nodes[i]->id();
1130 unsigned int parent_id = new_nodes[i]->parent()->id();
1132 Node * parent_node = _mesh->node_ptr(parent_id);
1133 Node * new_node = Node::build(*parent_node, _mesh->n_nodes()).release();
1134 _mesh->add_node(new_node);
1136 new_nodes_to_parents[new_node] = parent_node;
1138 new_node->set_n_systems(parent_node->n_systems());
1139 efa_id_to_new_node.insert(std::make_pair(new_node_id, new_node));
1141 _console <<
"XFEM added new node: " << new_node->id() <<
"\n";
1142 if (_displaced_mesh)
1144 const Node * parent_node2 = _displaced_mesh->node_ptr(parent_id);
1145 Node * new_node2 = Node::build(*parent_node2, _displaced_mesh->n_nodes()).release();
1146 _displaced_mesh->add_node(new_node2);
1148 new_node2->set_n_systems(parent_node2->n_systems());
1149 efa_id_to_new_node2.insert(std::make_pair(new_node_id, new_node2));
1154 std::map<unsigned int, std::vector<const Elem *>> temporary_parent_children_map;
1156 std::vector<boundary_id_type> parent_boundary_ids;
1158 for (
unsigned int i = 0; i < new_elements.size(); ++i)
1160 unsigned int parent_id = new_elements[i]->getParent()->id();
1161 unsigned int efa_child_id = new_elements[i]->id();
1163 Elem * parent_elem = _mesh->elem_ptr(parent_id);
1164 Elem * libmesh_elem = Elem::build(parent_elem->type()).release();
1170 if (parent_elem == it.first)
1171 it.first = libmesh_elem;
1172 else if (parent_elem == it.second)
1173 it.second = libmesh_elem;
1178 if (new_elements[i]->getParent()->numChildren() > 1)
1179 temporary_parent_children_map[parent_elem->id()].push_back(libmesh_elem);
1181 Elem * parent_elem2 = NULL;
1182 Elem * libmesh_elem2 = NULL;
1183 if (_displaced_mesh)
1185 parent_elem2 = _displaced_mesh->elem_ptr(parent_id);
1186 libmesh_elem2 = Elem::build(parent_elem2->type()).release();
1192 if (parent_elem2 == it.first)
1193 it.first = libmesh_elem2;
1194 else if (parent_elem2 == it.second)
1195 it.second = libmesh_elem2;
1200 for (
unsigned int j = 0; j < new_elements[i]->numNodes(); ++j)
1202 unsigned int node_id = new_elements[i]->getNode(j)->id();
1203 Node * libmesh_node;
1205 std::map<unsigned int, Node *>::iterator nit = efa_id_to_new_node.find(node_id);
1206 if (nit != efa_id_to_new_node.end())
1207 libmesh_node = nit->second;
1209 libmesh_node = _mesh->node_ptr(node_id);
1211 if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1212 libmesh_node->processor_id() = parent_elem->processor_id();
1214 libmesh_elem->set_node(j) = libmesh_node;
1217 if (parent_elem->is_semilocal(_mesh->processor_id()))
1219 Node * solution_node = libmesh_node;
1220 if (new_nodes_to_parents.find(libmesh_node) != new_nodes_to_parents.end())
1221 solution_node = new_nodes_to_parents[libmesh_node];
1223 if ((_moose_mesh->isSemiLocal(solution_node)) ||
1224 (solution_node->processor_id() == _mesh->processor_id()))
1237 current_aux_solution,
1239 older_aux_solution);
1243 Node * parent_node = parent_elem->node_ptr(j);
1244 _mesh->boundary_info->boundary_ids(parent_node, parent_boundary_ids);
1245 _mesh->boundary_info->add_node(libmesh_node, parent_boundary_ids);
1247 if (_displaced_mesh)
1249 std::map<unsigned int, Node *>::iterator nit2 = efa_id_to_new_node2.find(node_id);
1250 if (nit2 != efa_id_to_new_node2.end())
1251 libmesh_node = nit2->second;
1253 libmesh_node = _displaced_mesh->node_ptr(node_id);
1255 if (libmesh_node->processor_id() == DofObject::invalid_processor_id)
1256 libmesh_node->processor_id() = parent_elem2->processor_id();
1258 libmesh_elem2->set_node(j) = libmesh_node;
1260 parent_node = parent_elem2->node_ptr(j);
1261 _displaced_mesh->boundary_info->boundary_ids(parent_node, parent_boundary_ids);
1262 _displaced_mesh->boundary_info->add_node(libmesh_node, parent_boundary_ids);
1266 libmesh_elem->set_p_level(parent_elem->p_level());
1267 libmesh_elem->set_p_refinement_flag(parent_elem->p_refinement_flag());
1268 _mesh->add_elem(libmesh_elem);
1269 libmesh_elem->set_n_systems(parent_elem->n_systems());
1270 libmesh_elem->subdomain_id() = parent_elem->subdomain_id();
1271 libmesh_elem->processor_id() = parent_elem->processor_id();
1275 if (parent_elem->processor_id() == _mesh->processor_id())
1277 (*_material_data)[0]->copy(*libmesh_elem, *parent_elem, 0);
1278 for (
unsigned int side = 0; side < parent_elem->n_sides(); ++side)
1280 _mesh->boundary_info->boundary_ids(parent_elem, side, parent_boundary_ids);
1281 std::vector<boundary_id_type>::iterator it_bd = parent_boundary_ids.begin();
1282 for (; it_bd != parent_boundary_ids.end(); ++it_bd)
1284 if (_fe_problem->needBoundaryMaterialOnSide(*it_bd, 0))
1285 (*_bnd_material_data)[0]->copy(*libmesh_elem, *parent_elem, side);
1301 current_aux_solution,
1303 older_aux_solution);
1308 std::map<const Elem *, std::vector<Point>>::iterator mit =
1318 _console <<
"XFEM added new element: " << libmesh_elem->id() <<
"\n";
1321 if (_mesh->mesh_dimension() == 2)
1323 EFAElement2D * new_efa_elem2d = dynamic_cast<EFAElement2D *>(new_elements[i]);
1324 if (!new_efa_elem2d)
1325 mooseError(
"EFAelem is not of EFAelement2D type");
1328 _fe_problem->assembly(0).qRule()->n_points(),
1329 libmesh_elem->n_sides());
1331 else if (_mesh->mesh_dimension() == 3)
1333 EFAElement3D * new_efa_elem3d = dynamic_cast<EFAElement3D *>(new_elements[i]);
1334 if (!new_efa_elem3d)
1335 mooseError(
"EFAelem is not of EFAelement3D type");
1338 _fe_problem->assembly(0).qRule()->n_points(),
1339 libmesh_elem->n_sides());
1341 _cut_elem_map.insert(std::pair<unique_id_type, XFEMCutElem *>(libmesh_elem->unique_id(), xfce));
1342 efa_id_to_new_elem.insert(std::make_pair(efa_child_id, libmesh_elem));
1344 if (_displaced_mesh)
1346 libmesh_elem2->set_p_level(parent_elem2->p_level());
1347 libmesh_elem2->set_p_refinement_flag(parent_elem2->p_refinement_flag());
1348 _displaced_mesh->add_elem(libmesh_elem2);
1349 libmesh_elem2->set_n_systems(parent_elem2->n_systems());
1350 libmesh_elem2->subdomain_id() = parent_elem2->subdomain_id();
1351 libmesh_elem2->processor_id() = parent_elem2->processor_id();
1354 unsigned int n_sides = parent_elem->n_sides();
1355 for (
unsigned int side = 0; side < n_sides; ++side)
1357 _mesh->boundary_info->boundary_ids(parent_elem, side, parent_boundary_ids);
1358 _mesh->boundary_info->add_side(libmesh_elem, side, parent_boundary_ids);
1360 if (_displaced_mesh)
1362 n_sides = parent_elem2->n_sides();
1363 for (
unsigned int side = 0; side < n_sides; ++side)
1365 _displaced_mesh->boundary_info->boundary_ids(parent_elem2, side, parent_boundary_ids);
1366 _displaced_mesh->boundary_info->add_side(libmesh_elem2, side, parent_boundary_ids);
1370 unsigned int n_edges = parent_elem->n_edges();
1371 for (
unsigned int edge = 0; edge < n_edges; ++edge)
1373 _mesh->boundary_info->edge_boundary_ids(parent_elem, edge, parent_boundary_ids);
1374 _mesh->boundary_info->add_edge(libmesh_elem, edge, parent_boundary_ids);
1376 if (_displaced_mesh)
1378 n_edges = parent_elem2->n_edges();
1379 for (
unsigned int edge = 0; edge < n_edges; ++edge)
1381 _displaced_mesh->boundary_info->edge_boundary_ids(parent_elem2, edge, parent_boundary_ids);
1382 _displaced_mesh->boundary_info->add_edge(libmesh_elem2, edge, parent_boundary_ids);
1388 for (std::size_t i = 0; i < delete_elements.size(); ++i)
1390 Elem * elem_to_delete = _mesh->elem_ptr(delete_elements[i]->
id());
1393 std::map<unique_id_type, XFEMCutElem *>::iterator cemit =
1397 delete cemit->second;
1401 elem_to_delete->nullify_neighbors();
1402 _mesh->boundary_info->remove(elem_to_delete);
1403 unsigned int deleted_elem_id = elem_to_delete->id();
1404 _mesh->delete_elem(elem_to_delete);
1406 _console <<
"XFEM deleted element: " << deleted_elem_id <<
"\n";
1408 if (_displaced_mesh)
1410 Elem * elem_to_delete2 = _displaced_mesh->elem_ptr(delete_elements[i]->
id());
1411 elem_to_delete2->nullify_neighbors();
1412 _displaced_mesh->boundary_info->remove(elem_to_delete2);
1413 _displaced_mesh->delete_elem(elem_to_delete2);
1417 for (std::map<
unsigned int, std::vector<const Elem *>>::iterator it =
1418 temporary_parent_children_map.begin();
1419 it != temporary_parent_children_map.end();
1422 std::vector<const Elem *> & sibling_elem_vec = it->second;
1429 if (it->first == elem_id)
1431 std::make_pair(sibling_elem_vec[0], sibling_elem_vec[1]));
1435 if (_displaced_mesh)
1441 Elem * elem = _displaced_mesh->elem_ptr(se.first->id());
1442 Elem * elem_pair = _displaced_mesh->elem_ptr(se.second->id());
1444 std::make_pair(elem, elem_pair));
1450 temporary_parent_children_map.clear();
1458 std::set<EFAElement *>::const_iterator sit;
1459 for (sit = CrackTipElements.begin(); sit != CrackTipElements.end(); ++sit)
1461 unsigned int eid = (*sit)->id();
1462 Elem * crack_tip_elem;
1463 std::map<unsigned int, Elem *>::iterator eit = efa_id_to_new_elem.find(eid);
1464 if (eit != efa_id_to_new_elem.end())
1465 crack_tip_elem = eit->second;
1467 crack_tip_elem = _mesh->elem_ptr(eid);
1476 if ((*sit)->getParent() !=
nullptr)
1478 if ((*sit)->getParent()->id() == mie)
1487 _console <<
"\nXFEM mesh cutting with element fragment algorithm complete\n";
1488 _console <<
"# new nodes: " << new_nodes.size() <<
"\n";
1489 _console <<
"# new elements: " << new_elements.size() <<
"\n";
1490 _console <<
"# deleted elements: " << delete_elements.size() <<
"\n";
1491 _console << std::flush;
1496 return mesh_changed;
1503 MeshBase * displaced_mesh)
const
1505 Point node_coor(0.0, 0.0, 0.0);
1506 std::vector<EFANode *> master_nodes;
1507 std::vector<Point> master_points;
1508 std::vector<double> master_weights;
1510 CEMElem->
getMasterInfo(CEMnode, master_nodes, master_weights);
1511 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1516 const Node * node = elem->node_ptr(local_node_id);
1518 node = displaced_mesh->node_ptr(node->id());
1519 Point node_p((*node)(0), (*node)(1), (*node)(2));
1520 master_points.push_back(node_p);
1523 mooseError(
"master nodes must be permanent");
1525 for (std::size_t i = 0; i < master_nodes.size(); ++i)
1526 node_coor += master_weights[i] * master_points[i];
1534 Real phys_volfrac = 1.0;
1535 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1548 return phys_volfrac;
1554 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1572 unsigned int plane_id)
const
1575 Point planedata(0.0, 0.0, 0.0);
1576 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1584 if ((
unsigned int)quantity < 3)
1586 unsigned int index = (
unsigned int)quantity;
1588 comp = planedata(index);
1590 else if ((
unsigned int)quantity < 6)
1592 unsigned int index = (
unsigned int)quantity - 3;
1594 comp = planedata(index);
1597 mooseError(
"In get_cut_plane index out of range");
1613 bool is_cut =
false;
1614 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1635 std::vector<std::vector<Point>> & frag_faces,
1636 bool displaced_mesh)
const
1638 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1654 EFAElement2D * EFAelem2D = dynamic_cast<EFAElement2D *>(EFAelem);
1657 mooseError(
"EFAelem is not of EFAelement2D type");
1666 EFAElement3D * EFAelem3D = dynamic_cast<EFAElement3D *>(EFAelem);
1669 mooseError(
"EFAelem is not of EFAelement3D type");
1677 std::vector<std::vector<Point>> & frag_edges)
const
1684 mooseError(
"element ", elem->id(),
" has more than one fragment at this point");
1687 std::vector<Point> p_line(2, Point(0.0, 0.0, 0.0));
1690 frag_edges.push_back(p_line);
1698 std::vector<std::vector<Point>> & frag_faces)
const
1705 mooseError(
"element ", elem->id(),
" has more than one fragment at this point");
1709 std::vector<Point> p_line(num_face_nodes, Point(0.0, 0.0, 0.0));
1710 for (
unsigned int j = 0; j < num_face_nodes; ++j)
1712 frag_faces.push_back(p_line);
1726 if (xfem_qrule ==
"volfrac")
1728 else if (xfem_qrule ==
"moment_fitting")
1730 else if (xfem_qrule ==
"direct")
1751 const MooseArray<Point> & q_points)
1753 bool have_weights =
false;
1757 mooseAssert(xfce != NULL,
"Must have valid XFEMCutElem object here");
1759 have_weights =
true;
1761 return have_weights;
1768 const MooseArray<Point> & q_points,
1771 bool have_weights =
false;
1775 mooseAssert(xfce != NULL,
"Must have valid XFEMCutElem object here");
1777 have_weights =
true;
1779 return have_weights;
1784 unsigned int plane_id,
1786 std::vector<Point> & intersectionPoints,
1787 bool displaced_mesh)
const
1789 std::map<unique_id_type, XFEMCutElem *>::const_iterator it;
1803 std::vector<Point> & quad_pts,
1804 std::vector<Real> & quad_wts)
const
1806 Point p1 = intersection_points[0];
1807 Point p2 = intersection_points[1];
1810 std::size_t num_qpoints = 2;
1813 Real xi0 = -std::sqrt(1.0 / 3.0);
1814 Real xi1 = std::sqrt(1.0 / 3.0);
1816 quad_wts.resize(num_qpoints);
1817 quad_pts.resize(num_qpoints);
1819 Real integ_jacobian =
pow((p1 - p2).norm_sq(), 0.5) * 0.5;
1821 quad_wts[0] = 1.0 * integ_jacobian;
1822 quad_wts[1] = 1.0 * integ_jacobian;
1824 quad_pts[0] = (1.0 - xi0) / 2.0 * p1 + (1.0 + xi0) / 2.0 * p2;
1825 quad_pts[1] = (1.0 - xi1) / 2.0 * p1 + (1.0 + xi1) / 2.0 * p2;
1830 std::vector<Point> & quad_pts,
1831 std::vector<Real> & quad_wts)
const
1833 std::size_t nnd_pe = intersection_points.size();
1834 Point xcrd(0.0, 0.0, 0.0);
1835 for (std::size_t i = 0; i < nnd_pe; ++i)
1836 xcrd += intersection_points[i];
1839 quad_pts.resize(nnd_pe);
1840 quad_wts.resize(nnd_pe);
1844 for (std::size_t j = 0; j < nnd_pe; ++j)
1846 std::vector<std::vector<Real>> shape(3, std::vector<Real>(3, 0.0));
1847 std::vector<Point> subtrig_points(3, Point(0.0, 0.0, 0.0));
1849 int jplus1 = j < nnd_pe - 1 ? j + 1 : 0;
1850 subtrig_points[0] = xcrd;
1851 subtrig_points[1] = intersection_points[j];
1852 subtrig_points[2] = intersection_points[jplus1];
1854 std::vector<std::vector<Real>> sg2;
1856 for (std::size_t l = 0; l < sg2.size(); ++l)
1859 std::vector<Real> tsg_line(3, 0.0);
1860 for (std::size_t k = 0; k < 3; ++k)
1862 tsg_line[0] += shape[k][2] * subtrig_points[k](0);
1863 tsg_line[1] += shape[k][2] * subtrig_points[k](1);
1864 tsg_line[2] += shape[k][2] * subtrig_points[k](2);
1866 quad_pts[j + l] = Point(tsg_line[0], tsg_line[1], tsg_line[2]);
1867 quad_wts[j + l] = sg2[l][3] * jac;
1874 const Node * node_to_store_from,
1876 std::map<unique_id_type, std::vector<Real>> & stored_solution,
1877 const NumericVector<Number> & current_solution,
1878 const NumericVector<Number> & old_solution,
1879 const NumericVector<Number> & older_solution)
1881 std::vector<dof_id_type> stored_solution_dofs =
getNodeSolutionDofs(node_to_store_from, sys);
1882 std::vector<Real> stored_solution_scratch;
1884 std::size_t stored_solution_size =
1885 (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
1886 stored_solution_scratch.reserve(stored_solution_size);
1890 for (
auto dof : stored_solution_dofs)
1891 stored_solution_scratch.push_back(current_solution(dof));
1893 if (_fe_problem->isTransient())
1895 for (
auto dof : stored_solution_dofs)
1896 stored_solution_scratch.push_back(old_solution(dof));
1898 for (
auto dof : stored_solution_dofs)
1899 stored_solution_scratch.push_back(older_solution(dof));
1902 if (stored_solution_scratch.size() > 0)
1903 stored_solution[node_to_store_to->unique_id()] = stored_solution_scratch;
1908 const Elem * elem_to_store_from,
1910 std::map<unique_id_type, std::vector<Real>> & stored_solution,
1911 const NumericVector<Number> & current_solution,
1912 const NumericVector<Number> & old_solution,
1913 const NumericVector<Number> & older_solution)
1916 std::vector<Real> stored_solution_scratch;
1918 std::size_t stored_solution_size =
1919 (_fe_problem->isTransient() ? stored_solution_dofs.size() * 3 : stored_solution_dofs.size());
1920 stored_solution_scratch.reserve(stored_solution_size);
1924 for (
auto dof : stored_solution_dofs)
1925 stored_solution_scratch.push_back(current_solution(dof));
1927 if (_fe_problem->isTransient())
1929 for (
auto dof : stored_solution_dofs)
1930 stored_solution_scratch.push_back(old_solution(dof));
1932 for (
auto dof : stored_solution_dofs)
1933 stored_solution_scratch.push_back(older_solution(dof));
1936 if (stored_solution_scratch.size() > 0)
1937 stored_solution[elem_to_store_to->unique_id()] = stored_solution_scratch;
1942 const std::map<unique_id_type, std::vector<Real>> & stored_solution,
1943 NumericVector<Number> & current_solution,
1944 NumericVector<Number> & old_solution,
1945 NumericVector<Number> & older_solution)
1947 for (
auto & node : _mesh->local_node_ptr_range())
1949 auto mit = stored_solution.find(node->unique_id());
1950 if (mit != stored_solution.end())
1952 const std::vector<Real> & stored_node_solution = mit->second;
1955 stored_solution_dofs,
1962 for (
auto & elem : as_range(_mesh->local_elements_begin(), _mesh->local_elements_end()))
1964 auto mit = stored_solution.find(elem->unique_id());
1965 if (mit != stored_solution.end())
1967 const std::vector<Real> & stored_elem_solution = mit->second;
1970 stored_solution_dofs,
1980 const std::vector<dof_id_type> & stored_solution_dofs,
1981 NumericVector<Number> & current_solution,
1982 NumericVector<Number> & old_solution,
1983 NumericVector<Number> & older_solution)
1987 const auto old_solution_offset = stored_solution_dofs.size();
1988 const auto older_solution_offset = old_solution_offset * 2;
1990 for (std::size_t i = 0; i < stored_solution_dofs.size(); ++i)
1992 current_solution.set(stored_solution_dofs[i], stored_solution[i]);
1993 if (_fe_problem->isTransient())
1995 old_solution.set(stored_solution_dofs[i], stored_solution[old_solution_offset + i]);
1996 older_solution.set(stored_solution_dofs[i], stored_solution[older_solution_offset + i]);
2001 std::vector<dof_id_type>
2004 SubdomainID sid = elem->subdomain_id();
2005 const std::vector<MooseVariableFEBase *> & vars = sys.getVariables(0);
2006 std::vector<dof_id_type> solution_dofs;
2007 solution_dofs.reserve(vars.size());
2008 for (
auto var : vars)
2010 if (!var->isNodal())
2012 const std::set<SubdomainID> & var_subdomains = sys.getSubdomainsForVar(var->number());
2013 if (var_subdomains.empty() || var_subdomains.find(sid) != var_subdomains.end())
2015 unsigned int n_comp = elem->n_comp(sys.number(), var->number());
2016 for (
unsigned int icomp = 0; icomp < n_comp; ++icomp)
2018 dof_id_type elem_dof = elem->dof_number(sys.number(), var->number(), icomp);
2019 solution_dofs.push_back(elem_dof);
2024 return solution_dofs;
2027 std::vector<dof_id_type>
2030 const std::set<SubdomainID> & sids = _moose_mesh->getNodeBlockIds(*node);
2031 const std::vector<MooseVariableFEBase *> & vars = sys.getVariables(0);
2032 std::vector<dof_id_type> solution_dofs;
2033 solution_dofs.reserve(vars.size());
2034 for (
auto var : vars)
2038 const std::set<SubdomainID> & var_subdomains = sys.getSubdomainsForVar(var->number());
2039 std::set<SubdomainID> intersect;
2040 set_intersection(var_subdomains.begin(),
2041 var_subdomains.end(),
2044 std::inserter(intersect, intersect.begin()));
2045 if (var_subdomains.empty() || !intersect.empty())
2047 unsigned int n_comp = node->n_comp(sys.number(), var->number());
2048 for (
unsigned int icomp = 0; icomp < n_comp; ++icomp)
2050 dof_id_type node_dof = node->dof_number(sys.number(), var->number(), icomp);
2051 solution_dofs.push_back(node_dof);
2056 return solution_dofs;