451 LOG_SCOPE(
"all_tri()",
"MeshTools::Modification");
465 std::vector<std::unique_ptr<Elem>> new_elements;
467 unsigned int max_subelems = 1;
476 for (
const Elem * elem :
mesh.element_ptr_range())
479 max_subelems = std::max(max_subelems, poly->n_subtriangles());
481 max_subelems = std::max(max_subelems, polyhedron->n_subelements());
485 new_elements.reserve (max_subelems*n_orig_elem);
495 std::vector<Elem *> new_bndry_elements;
496 std::vector<unsigned short int> new_bndry_sides;
497 std::vector<boundary_id_type> new_bndry_ids;
502 bool added_new_ghost_point =
false;
517#ifdef LIBMESH_ENABLE_UNIQUE_ID
522 std::unique_ptr<const Elem> elem_side, subside_elem;
524 for (
auto & elem :
mesh.element_ptr_range())
530 libmesh_not_implemented_msg(
"Cannot convert a refined element into simplices\n");
534 std::vector<std::unique_ptr<Elem>> subelem(max_subelems);
536 auto set_nodes = [&elem, &subelem]
537 (
const std::initializer_list<std::initializer_list<int>> & node_ids) {
539 for (
auto row : node_ids)
542 Elem * sub = subelem[i++].get();
544 for (
auto node_id : row)
557 if ((elem->
point(0) - elem->
point(2)).norm() <
559 set_nodes({{0,1,2},{0,2,3}});
561 set_nodes({{0,1,3},{1,2,3}});
569 added_new_ghost_point =
true;
583 if ((elem->
point(0) - elem->
point(2)).norm() <
586 set_nodes({{0,1,2,4,5},{0,2,3,3,6,7}});
587 subelem[0]->set_node(5, new_node);
588 subelem[1]->set_node(3, new_node);
592 set_nodes({{3,0,1,7,4},{1,2,3,5,6}});
593 subelem[0]->set_node(5, new_node);
594 subelem[1]->set_node(5, new_node);
606 if ((elem->
point(0) - elem->
point(2)).norm() <
608 set_nodes({{0,1,2,4,5,8},{0,2,3,8,6,7}});
610 set_nodes({{0,1,3,4,8,7},{1,2,3,5,6,8}});
633 const unsigned int highest_n = highest_vertex_on(elem);
637 static const std::array<unsigned int, 8> opposing_node =
638 {6, 7, 4, 5, 2, 3, 0, 1};
640 static const std::vector<std::vector<unsigned int>> sides_opposing_highest =
641 {{2,3,5},{3,4,5},{1,4,5},{1,2,5},{0,2,3},{0,3,4},{0,1,4},{0,1,2}};
642 static const std::vector<std::vector<unsigned int>> nodes_neighboring_highest =
643 {{1,3,4},{0,2,5},{1,3,6},{0,2,7},{0,5,7},{1,4,6},{2,5,7},{3,4,6}};
654 unsigned int next_subelem = 0;
655 for (
auto side : sides_opposing_highest[highest_n])
657 const std::vector<unsigned int> nodes_on_side =
660 auto [dn, dn2] = split_diagonal(elem, nodes_on_side);
662 unsigned int split_on_neighbor =
false;
663 for (
auto n : nodes_neighboring_highest[highest_n])
664 if (dn == n || dn2 == n)
666 split_on_neighbor =
true;
674 if (split_on_neighbor)
676 subelem[next_subelem]->set_node(0, elem->
node_ptr(highest_n));
677 subelem[next_subelem]->set_node(1, elem->
node_ptr(dn));
678 subelem[next_subelem]->set_node(2, elem->
node_ptr(dn2));
679 for (
auto n : nodes_on_side)
680 if (n != dn && n != dn2)
682 subelem[next_subelem]->set_node(3, elem->
node_ptr(n));
685 subelem[next_subelem]->orient(&boundary_info);
688 subelem[next_subelem]->set_node(0, elem->
node_ptr(highest_n));
689 subelem[next_subelem]->set_node(1, elem->
node_ptr(dn));
690 subelem[next_subelem]->set_node(2, elem->
node_ptr(dn2));
691 for (
auto n : reverse(nodes_on_side))
692 if (n != dn && n != dn2)
694 subelem[next_subelem]->set_node(3, elem->
node_ptr(n));
697 subelem[next_subelem]->orient(&boundary_info);
702 subelem[next_subelem]->set_node(0, elem->
node_ptr(highest_n));
703 subelem[next_subelem]->set_node(1, elem->
node_ptr(dn));
704 subelem[next_subelem]->set_node(2, elem->
node_ptr(dn2));
705 for (
auto n : nodes_on_side)
706 for (
auto n2 : nodes_neighboring_highest[highest_n])
709 subelem[next_subelem]->set_node(3, elem->
node_ptr(n));
710 goto break_both_loops;
714 subelem[next_subelem]->orient(&boundary_info);
727 if (next_subelem == 3)
729 subelem[next_subelem]->set_node(0, elem->
node_ptr(opposing_nodes[highest_n][0]));
730 subelem[next_subelem]->set_node(1, elem->
node_ptr(opposing_nodes[highest_n][1]));
731 subelem[next_subelem]->set_node(2, elem->
node_ptr(opposing_nodes[highest_n][2]));
732 subelem[next_subelem]->set_node(3, elem->
node_ptr(opposing_node[highest_n]));
733 subelem[next_subelem]->orient(&boundary_info);
736 subelem[next_subelem]->set_node(0, elem->
node_ptr(opposing_nodes[highest_n][0]));
737 subelem[next_subelem]->set_node(1, elem->
node_ptr(opposing_nodes[highest_n][1]));
738 subelem[next_subelem]->set_node(2, elem->
node_ptr(opposing_nodes[highest_n][2]));
739 subelem[next_subelem]->set_node(3, elem->
node_ptr(highest_n));
740 subelem[next_subelem]->orient(&boundary_info);
744 subelem[next_subelem].reset();
751 if (next_subelem == 4 ||
754 for (
auto side : sides_opposing_highest[highest_n])
756 const std::vector<unsigned int> nodes_on_side =
759 auto [dn, dn2] = split_diagonal(elem, nodes_on_side);
761 unsigned int split_on_neighbor =
false;
762 for (
auto n : nodes_neighboring_highest[highest_n])
763 if (dn == n || dn2 == n)
765 split_on_neighbor =
true;
771 if (!split_on_neighbor)
773 subelem[next_subelem]->set_node(0, elem->
node_ptr(highest_n));
774 subelem[next_subelem]->set_node(1, elem->
node_ptr(dn));
775 subelem[next_subelem]->set_node(2, elem->
node_ptr(dn2));
776 subelem[next_subelem]->set_node(3, elem->
node_ptr(opposing_node[highest_n]));
777 subelem[next_subelem]->orient(&boundary_info);
815 if (split_first_diagonal(elem, 0,4, 1,3))
818 if (split_first_diagonal(elem, 0,5, 2,3))
821 if (split_first_diagonal(elem, 1,5, 2,4))
822 set_nodes({{0,4,5,3},{0,4,1,5},{0,1,2,5}});
826 set_nodes({{0,4,5,3},{0,4,2,5},{0,1,2,4}});
836 set_nodes({{0,4,2,3},{3,4,2,5},{0,1,2,4}});
844 if (split_first_diagonal(elem, 0,5, 2,3))
849 set_nodes({{1,3,4,5},{1,0,3,5},{0,1,2,5}});
856 if (split_first_diagonal(elem, 1,5, 2,4))
857 set_nodes({{0,1,2,3},{3,1,2,5},{1,3,4,5}});
861 set_nodes({{0,1,2,3},{2,3,4,5},{3,1,2,4}});
871 libmesh_experimental();
872 libmesh_fallthrough();
880 if (split_first_diagonal(elem, 0,4, 1,3))
883 if (split_first_diagonal(elem, 0,5, 2,3))
886 if (split_first_diagonal(elem, 1,5, 2,4))
887 set_nodes({{0,4,5,3,15,13,17,9,12,14},
888 {0,4,1,5,15,10,6,17,13,16},
889 {0,1,2,5,6,7,8,17,16,11}});
894 set_nodes({{0,4,5,3,15,13,17,9,12,14},
895 {0,4,2,5,15,16,8,17,13,11},
896 {0,1,2,4,6,7,8,15,10,16}});
906 set_nodes({{0,4,2,3,15,16,8,9,12,17},
907 {3,4,2,5,12,16,17,14,13,11},
908 {0,1,2,4,6,7,8,15,10,16}});
916 if (split_first_diagonal(elem, 0,5, 2,3))
921 set_nodes({{1,3,4,5,15,12,10,16,14,13},
922 {1,0,3,5,6,9,15,16,17,14},
923 {0,1,2,5,6,7,8,17,16,11}});
930 if (split_first_diagonal(elem, 1,5, 2,4))
931 set_nodes({{0,1,2,3,6,7,8,9,15,17},
932 {3,1,2,5,15,7,17,14,16,11},
933 {1,3,4,5,15,12,10,16,14,13}});
938 set_nodes({{0,1,2,3,6,7,8,9,15,17},
939 {2,3,4,5,17,12,16,11,14,13},
940 {3,1,2,4,15,7,17,12,10,16}});
959 if (split_first_diagonal(elem, 0,2, 1,3))
960 set_nodes({{0,1,2,4},{0,2,3,4}});
965 set_nodes({{0,1,3,4},{1,2,3,4}});
982 if (split_first_diagonal(elem, 0,2, 1,3))
983 set_nodes({{0,1,2,4,5,6,13,9,10,11},
984 {0,2,3,4,13,7,8,9,11,12}});
989 set_nodes({{0,1,3,4,5,13,8,9,10,12},
990 {1,2,3,4,6,7,13,10,11,12}});
1003 const C0Polygon * polygon = cast_ptr<const C0Polygon *>(elem);
1005 for (
unsigned int t = 0; t != n_subtri; ++t)
1007 const std::array<int, 3> tri = polygon->
subtriangle(t);
1008 if (tri[0] < 0 || tri[1] < 0 || tri[2] < 0)
1009 libmesh_not_implemented_msg
1010 (
"Cannot convert a C0Polygon whose triangulation\n"
1011 "introduces special (non-vertex) points");
1013 subelem[t]->set_node(0, elem->
node_ptr(tri[0]));
1014 subelem[t]->set_node(1, elem->
node_ptr(tri[1]));
1015 subelem[t]->set_node(2, elem->
node_ptr(tri[2]));
1029 cast_ptr<const C0Polyhedron *>(elem);
1031 for (
unsigned int t = 0; t != n_sub; ++t)
1033 const std::array<int, 4> tet = polyhedron->
subelement(t);
1034 if (tet[0] < 0 || tet[1] < 0 || tet[2] < 0 || tet[3] < 0)
1035 libmesh_not_implemented_msg
1036 (
"Cannot convert a C0Polyhedron whose triangulation\n"
1037 "introduces special (non-vertex) points");
1039 subelem[t]->set_node(0, elem->
node_ptr(tet[0]));
1040 subelem[t]->set_node(1, elem->
node_ptr(tet[1]));
1041 subelem[t]->set_node(2, elem->
node_ptr(tet[2]));
1042 subelem[t]->set_node(3, elem->
node_ptr(tet[3]));
1076 libmesh_not_implemented_msg
1077 (
"Error, encountered unimplemented element "
1078 << Utility::enum_to_string<ElemType>(etype)
1079 <<
" in MeshTools::Modification::all_tri()...");
1084 for (
unsigned int i=0; i != max_subelems; ++i)
1092 subelem[i]->add_extra_integers(nei);
1093 for (
unsigned int ei=0; ei != nei; ++ei)
1109 if (mesh_has_boundary_data || !mesh_is_serial)
1112 std::vector<boundary_id_type> bc_ids;
1123 std::vector<dof_id_type> elem_side_nodes(elem_side->n_nodes());
1124 for (
unsigned int esn=0,
1125 n_esn = cast_int<unsigned int>(elem_side_nodes.size());
1126 esn != n_esn; ++esn)
1127 elem_side_nodes[esn] = elem_side->node_id(esn);
1128 std::sort(elem_side_nodes.begin(), elem_side_nodes.end());
1130 for (
unsigned int i=0; i != max_subelems; ++i)
1133 for (
auto subside : subelem[i]->side_index_range())
1135 subelem[i]->build_side_ptr(subside_elem, subside);
1143 std::vector<dof_id_type> subside_nodes(subside_elem->n_vertices());
1144 for (
unsigned int ssn=0,
1145 n_ssn = cast_int<unsigned int>(subside_nodes.size());
1146 ssn != n_ssn; ++ssn)
1147 subside_nodes[ssn] = subside_elem->node_id(ssn);
1148 std::sort(subside_nodes.begin(), subside_nodes.end());
1152 if (std::includes(elem_side_nodes.begin(), elem_side_nodes.end(),
1153 subside_nodes.begin(), subside_nodes.end()))
1155 for (
const auto & b_id : bc_ids)
1158 new_bndry_ids.push_back(b_id);
1159 new_bndry_elements.push_back(subelem[i].get());
1160 new_bndry_sides.push_back(subside);
1181 for (
unsigned int i=0; i != max_subelems; ++i)
1188 subelem[i]->set_id( max_orig_id + max_subelems*elem->
id() + i );
1190#ifdef LIBMESH_ENABLE_UNIQUE_ID
1191 subelem[i]->set_unique_id(max_unique_id + max_subelems*elem->
unique_id() + i);
1195 new_elements.push_back(std::move(subelem[i]));
1206 for (
auto & elem : new_elements)
1209 if (mesh_has_boundary_data)
1222 bool nbe_nonempty = new_bndry_elements.size();
1230 libmesh_assert_equal_to (new_bndry_elements.size(), new_bndry_sides.size());
1231 libmesh_assert_equal_to (new_bndry_sides.size(), new_bndry_ids.size());
1248 if (added_new_ghost_point)