16 #include "libmesh/elem.h"    17 #include "libmesh/enum_order.h"    18 #include "libmesh/boundary_info.h"    19 #include "libmesh/mesh_base.h"    20 #include "libmesh/parallel.h"    21 #include "libmesh/parallel_algebra.h"    22 #include "libmesh/utility.h"    23 #include "libmesh/cell_tet4.h"    24 #include "libmesh/face_tri3.h"    25 #include "libmesh/cell_pyramid5.h"    33                 const std::vector<libMesh::BoundaryInfo::BCTuple> & bdry_side_list,
    35                 std::vector<dof_id_type> & converted_elems_ids)
    40   std::vector<std::vector<boundary_id_type>> elem_side_list;
    41   elem_side_list.resize(6);
    45   std::vector<dof_id_type> exist_extra_ids(n_elem_extra_ids);
    47   for (
unsigned int j = 0; j < n_elem_extra_ids; j++)
    50   std::vector<std::vector<unsigned int>> opt_option;
    59   std::vector<std::vector<unsigned int>> rotated_tet_face_indices;
    61   std::vector<std::vector<const Node *>> optimized_node_list;
    64   std::vector<Elem *> elems_Tet4;
    65   for (
const auto i : 
index_range(optimized_node_list))
    67     auto new_elem = std::make_unique<Tet4>();
    68     new_elem->set_node(0, const_cast<Node *>(optimized_node_list[i][0]));
    69     new_elem->set_node(1, const_cast<Node *>(optimized_node_list[i][1]));
    70     new_elem->set_node(2, const_cast<Node *>(optimized_node_list[i][2]));
    71     new_elem->set_node(3, const_cast<Node *>(optimized_node_list[i][3]));
    73     elems_Tet4.push_back(
mesh.
add_elem(std::move(new_elem)));
    74     converted_elems_ids.push_back(elems_Tet4.back()->id());
    76     for (
unsigned int j = 0; j < 4; j++)
    81       if (rotated_tet_face_indices[i][j] < 6)
    83         for (
const auto & side_info : elem_side_list[rotated_tet_face_indices[i][j]])
    84           boundary_info.
add_side(elems_Tet4.back(), j, side_info);
    90   for (
unsigned int i = 0; i < 6; i++)
    91     for (
unsigned int j = 0; j < n_elem_extra_ids; j++)
    93       elems_Tet4[i]->set_extra_integer(j, exist_extra_ids[j]);
    99                   const std::vector<libMesh::BoundaryInfo::BCTuple> & bdry_side_list,
   101                   std::vector<dof_id_type> & converted_elems_ids)
   106   std::vector<std::vector<boundary_id_type>> elem_side_list;
   110   std::vector<dof_id_type> exist_extra_ids(n_elem_extra_ids);
   113   for (
unsigned int j = 0; j < n_elem_extra_ids; j++)
   122   std::vector<std::vector<unsigned int>> rotated_tet_face_indices;
   123   std::vector<std::vector<const Node *>> optimized_node_list;
   126   std::vector<Elem *> elems_Tet4;
   127   for (
const auto i : 
index_range(optimized_node_list))
   129     auto new_elem = std::make_unique<Tet4>();
   130     new_elem->set_node(0, const_cast<Node *>(optimized_node_list[i][0]));
   131     new_elem->set_node(1, const_cast<Node *>(optimized_node_list[i][1]));
   132     new_elem->set_node(2, const_cast<Node *>(optimized_node_list[i][2]));
   133     new_elem->set_node(3, const_cast<Node *>(optimized_node_list[i][3]));
   135     elems_Tet4.push_back(
mesh.
add_elem(std::move(new_elem)));
   136     converted_elems_ids.push_back(elems_Tet4.back()->id());
   138     for (
unsigned int j = 0; j < 4; j++)
   143       if (rotated_tet_face_indices[i][j] < 5)
   145         for (
const auto & side_info : elem_side_list[rotated_tet_face_indices[i][j]])
   146           boundary_info.
add_side(elems_Tet4.back(), j, side_info);
   152   for (
unsigned int i = 0; i < 3; i++)
   153     for (
unsigned int j = 0; j < n_elem_extra_ids; j++)
   155       elems_Tet4[i]->set_extra_integer(j, exist_extra_ids[j]);
   161                     const std::vector<libMesh::BoundaryInfo::BCTuple> & bdry_side_list,
   163                     std::vector<dof_id_type> & converted_elems_ids)
   168   std::vector<std::vector<boundary_id_type>> elem_side_list;
   172   std::vector<dof_id_type> exist_extra_ids(n_elem_extra_ids);
   174   for (
unsigned int j = 0; j < n_elem_extra_ids; j++)
   182   std::vector<std::vector<unsigned int>> rotated_tet_face_indices;
   183   std::vector<std::vector<const Node *>> optimized_node_list;
   186   std::vector<Elem *> elems_Tet4;
   187   for (
const auto i : 
index_range(optimized_node_list))
   189     auto new_elem = std::make_unique<Tet4>();
   190     new_elem->set_node(0, const_cast<Node *>(optimized_node_list[i][0]));
   191     new_elem->set_node(1, const_cast<Node *>(optimized_node_list[i][1]));
   192     new_elem->set_node(2, const_cast<Node *>(optimized_node_list[i][2]));
   193     new_elem->set_node(3, const_cast<Node *>(optimized_node_list[i][3]));
   195     elems_Tet4.push_back(
mesh.
add_elem(std::move(new_elem)));
   196     converted_elems_ids.push_back(elems_Tet4.back()->id());
   198     for (
unsigned int j = 0; j < 4; j++)
   203       if (rotated_tet_face_indices[i][j] < 5)
   205         for (
const auto & side_info : elem_side_list[rotated_tet_face_indices[i][j]])
   206           boundary_info.
add_side(elems_Tet4.back(), j, side_info);
   212   for (
unsigned int i = 0; i < 2; i++)
   213     for (
unsigned int j = 0; j < n_elem_extra_ids; j++)
   215       elems_Tet4[i]->set_extra_integer(j, exist_extra_ids[j]);
   219 std::vector<unsigned int>
   222   const std::vector<std::vector<unsigned int>> preset_indices = {
   223       {1, 3, 4}, {0, 2, 5}, {3, 1, 6}, {2, 0, 7}, {5, 7, 0}, {4, 6, 1}, {7, 5, 2}, {6, 4, 3}};
   224   if (min_id_index > 7)
   225     mooseError(
"The input node index is out of range.");
   227     return preset_indices[min_id_index];
   232                              std::vector<std::vector<unsigned int>> & rotated_tet_face_indices,
   233                              std::vector<std::vector<const Node *>> & tet_nodes_list)
   236   std::vector<dof_id_type> node_ids(8);
   237   for (
unsigned int i = 0; i < 8; i++)
   238     node_ids[i] = hex_nodes[i]->
id();
   240   const unsigned int min_node_id_index = std::distance(
   241       std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
   247   const auto neighbor_node_ids = {node_ids[neighbor_node_indices[0]],
   248                                   node_ids[neighbor_node_indices[1]],
   249                                   node_ids[neighbor_node_indices[2]]};
   250   const unsigned int sec_min_pos =
   251       std::distance(std::begin(neighbor_node_ids),
   252                     std::min_element(std::begin(neighbor_node_ids), std::end(neighbor_node_ids)));
   258   std::vector<unsigned int> face_rotation;
   259   std::vector<unsigned int> rotated_indices;
   260   nodeRotationHEX8(min_node_id_index, sec_min_pos, face_rotation, rotated_indices);
   261   std::vector<const Node *> rotated_hex_nodes;
   262   for (
unsigned int i = 0; i < 8; i++)
   263     rotated_hex_nodes.push_back(hex_nodes[rotated_indices[i]]);
   270   std::vector<std::vector<unsigned int>> tet_face_indices;
   271   const auto tet_nodes_set = 
tetNodesForHex(diagonal_directions, tet_face_indices);
   272   for (
const auto & tet_face_index : tet_face_indices)
   274     rotated_tet_face_indices.push_back(std::vector<unsigned int>());
   275     for (
const auto & face_index : tet_face_index)
   278         rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
   280         rotated_tet_face_indices.back().push_back(6);
   284   for (
const auto & tet_nodes : tet_nodes_set)
   286     tet_nodes_list.push_back(std::vector<const Node *>());
   287     for (
const auto & tet_node : tet_nodes)
   288       tet_nodes_list.back().push_back(rotated_hex_nodes[tet_node]);
   296   const std::vector<std::vector<unsigned int>> face_indices = {
   297       {0, 1, 2, 3}, {4, 5, 6, 7}, {0, 1, 5, 4}, {2, 3, 7, 6}, {1, 2, 6, 5}, {3, 0, 4, 7}};
   298   std::vector<bool> diagonal_directions;
   299   for (
const auto & face_index : face_indices)
   301     std::vector<const Node *> quad_nodes = {hex_nodes[face_index[0]],
   302                                             hex_nodes[face_index[1]],
   303                                             hex_nodes[face_index[2]],
   304                                             hex_nodes[face_index[3]]};
   307   return diagonal_directions;
   313   const std::vector<dof_id_type> node_ids = {
   314       quad_nodes[0]->id(), quad_nodes[1]->id(), quad_nodes[2]->id(), quad_nodes[3]->id()};
   315   const unsigned int min_id_index = std::distance(
   316       std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
   317   if (min_id_index == 0 || min_id_index == 2)
   323 std::vector<std::vector<unsigned int>>
   325                std::vector<std::vector<unsigned int>> & tet_face_indices)
   327   const std::vector<std::vector<bool>> possible_inputs = {{
true, 
true, 
true, 
true, 
true, 
false},
   328                                                           {
true, 
true, 
true, 
true, 
false, 
false},
   329                                                           {
true, 
true, 
true, 
false, 
true, 
false},
   330                                                           {
true, 
false, 
true, 
true, 
true, 
false},
   331                                                           {
true, 
false, 
true, 
true, 
false, 
false},
   332                                                           {
true, 
false, 
true, 
false, 
true, 
false},
   333                                                           {
true, 
false, 
true, 
false, 
false, 
false}};
   335   const unsigned int input_index = std::distance(
   336       std::begin(possible_inputs),
   337       std::find(std::begin(possible_inputs), std::end(possible_inputs), diagonal_directions));
   343           {0, 6, 2, 6}, {1, 6, 2, 6}, {1, 6, 5, 6}, {0, 6, 3, 4}, {6, 6, 3, 6}, {6, 4, 5, 6}};
   344       return {{0, 1, 2, 6}, {0, 5, 1, 6}, {0, 4, 5, 6}, {0, 2, 3, 7}, {0, 6, 2, 7}, {0, 4, 6, 7}};
   347           {0, 1, 2, 6}, {6, 6, 2, 6}, {6, 6, 5, 1}, {0, 6, 3, 4}, {6, 6, 3, 6}, {6, 4, 5, 6}};
   348       return {{0, 1, 2, 5}, {0, 2, 6, 5}, {0, 6, 4, 5}, {0, 2, 3, 7}, {0, 6, 2, 7}, {0, 4, 6, 7}};
   351           {0, 6, 2, 6}, {1, 6, 2, 6}, {1, 6, 5, 6}, {4, 6, 5, 6}, {4, 6, 3, 6}, {0, 6, 3, 6}};
   352       return {{0, 1, 2, 6}, {0, 5, 1, 6}, {0, 4, 5, 6}, {0, 7, 4, 6}, {0, 3, 7, 6}, {0, 2, 3, 6}};
   355           {4, 6, 5, 1}, {6, 6, 5, 6}, {6, 1, 2, 6}, {4, 0, 3, 6}, {6, 6, 3, 6}, {6, 6, 2, 0}};
   356       return {{0, 7, 4, 5}, {0, 6, 7, 5}, {0, 1, 6, 5}, {0, 3, 7, 2}, {0, 7, 6, 2}, {0, 6, 1, 2}};
   358       tet_face_indices = {{0, 1, 2, 6}, {0, 6, 3, 4}, {5, 4, 6, 1}, {5, 6, 3, 2}, {6, 6, 6, 6}};
   359       return {{0, 1, 2, 5}, {0, 2, 3, 7}, {4, 7, 5, 0}, {5, 7, 6, 2}, {0, 2, 7, 5}};
   362           {4, 6, 5, 1}, {6, 6, 5, 6}, {6, 1, 2, 6}, {2, 6, 6, 0}, {3, 6, 6, 0}, {3, 6, 6, 4}};
   363       return {{0, 7, 4, 5}, {0, 6, 7, 5}, {0, 1, 6, 5}, {1, 6, 2, 0}, {2, 6, 3, 0}, {3, 6, 7, 0}};
   366           {1, 4, 5, 6}, {6, 6, 5, 6}, {6, 6, 3, 4}, {1, 6, 2, 0}, {6, 6, 2, 6}, {6, 0, 3, 6}};
   367       return {{0, 4, 5, 7}, {0, 5, 6, 7}, {0, 6, 3, 7}, {0, 5, 1, 2}, {0, 6, 5, 2}, {0, 3, 6, 2}};
   375                  const unsigned int sec_min_pos,
   376                  std::vector<unsigned int> & face_rotation,
   377                  std::vector<unsigned int> & node_rotation)
   383   const std::vector<std::vector<std::vector<unsigned int>>> preset_indices = {
   384       {{0, 1, 2, 3, 4, 5, 6, 7}, {0, 3, 7, 4, 1, 2, 6, 5}, {0, 4, 5, 1, 3, 7, 6, 2}},
   385       {{1, 0, 4, 5, 2, 3, 7, 6}, {1, 2, 3, 0, 5, 6, 7, 4}, {1, 5, 6, 2, 0, 4, 7, 3}},
   386       {{2, 3, 0, 1, 6, 7, 4, 5}, {2, 1, 5, 6, 3, 0, 4, 7}, {2, 6, 7, 3, 1, 5, 4, 0}},
   387       {{3, 2, 6, 7, 0, 1, 5, 4}, {3, 0, 1, 2, 7, 4, 5, 6}, {3, 7, 4, 0, 2, 6, 5, 1}},
   388       {{4, 5, 1, 0, 7, 6, 2, 3}, {4, 7, 6, 5, 0, 3, 2, 1}, {4, 0, 3, 7, 5, 1, 2, 6}},
   389       {{5, 4, 7, 6, 1, 0, 3, 2}, {5, 6, 2, 1, 4, 7, 3, 0}, {5, 1, 0, 4, 6, 2, 3, 7}},
   390       {{6, 7, 3, 2, 5, 4, 0, 1}, {6, 5, 4, 7, 2, 1, 0, 3}, {6, 2, 1, 5, 7, 3, 0, 4}},
   391       {{7, 6, 5, 4, 3, 2, 1, 0}, {7, 4, 0, 3, 6, 5, 1, 2}, {7, 3, 2, 6, 4, 0, 1, 5}}};
   393   const std::vector<std::vector<std::vector<unsigned int>>> preset_face_indices = {
   394       {{0, 1, 2, 3, 4, 5}, {4, 0, 3, 5, 1, 2}, {1, 4, 5, 2, 0, 3}},
   395       {{1, 0, 4, 5, 2, 3}, {0, 2, 3, 4, 1, 5}, {2, 1, 5, 3, 0, 4}},
   396       {{0, 3, 4, 1, 2, 5}, {2, 0, 1, 5, 3, 4}, {3, 2, 5, 4, 0, 1}},
   397       {{3, 0, 2, 5, 4, 1}, {0, 4, 1, 2, 3, 5}, {4, 3, 5, 1, 0, 2}},
   398       {{1, 5, 2, 0, 4, 3}, {5, 4, 3, 2, 1, 0}, {4, 1, 0, 3, 5, 2}},
   399       {{5, 1, 4, 3, 2, 0}, {2, 5, 3, 0, 1, 4}, {1, 2, 0, 4, 5, 3}},
   400       {{3, 5, 4, 0, 2, 1}, {5, 2, 1, 4, 3, 0}, {2, 3, 0, 1, 5, 4}},
   401       {{5, 3, 2, 1, 4, 0}, {4, 5, 1, 0, 3, 2}, {3, 4, 0, 2, 5, 1}}};
   403   if (min_id_index > 7 || sec_min_pos > 2)
   404     mooseError(
"The input node index is out of range.");
   408     face_rotation = preset_face_indices[min_id_index][sec_min_pos];
   409     node_rotation = preset_indices[min_id_index][sec_min_pos];
   415                    std::vector<unsigned int> & face_rotation,
   416                    std::vector<unsigned int> & node_rotation)
   418   const std::vector<std::vector<unsigned int>> preset_indices = {{0, 1, 2, 3, 4, 5},
   425   const std::vector<std::vector<unsigned int>> preset_face_indices = {{0, 1, 2, 3, 4},
   432   if (min_id_index > 5)
   433     mooseError(
"The input node index is out of range.");
   437     face_rotation = preset_face_indices[min_id_index];
   438     node_rotation = preset_indices[min_id_index];
   444                                std::vector<std::vector<unsigned int>> & rotated_tet_face_indices,
   445                                std::vector<std::vector<const Node *>> & tet_nodes_list)
   448   std::vector<dof_id_type> node_ids(6);
   449   for (
unsigned int i = 0; i < 6; i++)
   450     node_ids[i] = prism_nodes[i]->
id();
   452   const unsigned int min_node_id_index = std::distance(
   453       std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
   458   std::vector<unsigned int> face_rotation;
   459   std::vector<unsigned int> rotated_indices;
   461   std::vector<const Node *> rotated_prism_nodes;
   462   for (
unsigned int i = 0; i < 6; i++)
   463     rotated_prism_nodes.push_back(prism_nodes[rotated_indices[i]]);
   465   std::vector<const Node *> key_quad_nodes = {rotated_prism_nodes[1],
   466                                               rotated_prism_nodes[2],
   467                                               rotated_prism_nodes[5],
   468                                               rotated_prism_nodes[4]};
   475   std::vector<std::vector<unsigned int>> tet_face_indices;
   476   const auto tet_nodes_set = 
tetNodesForPrism(diagonal_direction, tet_face_indices);
   477   for (
const auto & tet_face_index : tet_face_indices)
   479     rotated_tet_face_indices.push_back(std::vector<unsigned int>());
   480     for (
const auto & face_index : tet_face_index)
   483         rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
   485         rotated_tet_face_indices.back().push_back(5);
   489   for (
const auto & tet_nodes : tet_nodes_set)
   491     tet_nodes_list.push_back(std::vector<const Node *>());
   492     for (
const auto & tet_node : tet_nodes)
   493       tet_nodes_list.back().push_back(rotated_prism_nodes[tet_node]);
   497 std::vector<std::vector<unsigned int>>
   499                  std::vector<std::vector<unsigned int>> & tet_face_indices)
   502   if (diagonal_direction)
   504     tet_face_indices = {{4, 3, 5, 1}, {2, 1, 5, 5}, {2, 5, 3, 0}};
   505     return {{3, 5, 4, 0}, {1, 4, 5, 0}, {1, 5, 2, 0}};
   509     tet_face_indices = {{4, 3, 5, 1}, {2, 1, 5, 0}, {2, 5, 5, 3}};
   510     return {{3, 5, 4, 0}, {1, 4, 2, 0}, {2, 4, 5, 0}};
   516                      std::vector<unsigned int> & face_rotation,
   517                      std::vector<unsigned int> & node_rotation)
   519   const std::vector<std::vector<unsigned int>> preset_indices = {
   520       {0, 1, 2, 3, 4}, {1, 2, 3, 0, 4}, {2, 3, 0, 1, 4}, {3, 0, 1, 2, 4}};
   522   const std::vector<std::vector<unsigned int>> preset_face_indices = {
   523       {0, 1, 2, 3, 4}, {1, 2, 3, 0, 4}, {2, 3, 0, 1, 4}, {3, 0, 1, 2, 4}};
   525   if (min_id_index > 3)
   526     mooseError(
"The input node index is out of range.");
   530     face_rotation = preset_face_indices[min_id_index];
   531     node_rotation = preset_indices[min_id_index];
   537                                  std::vector<std::vector<unsigned int>> & rotated_tet_face_indices,
   538                                  std::vector<std::vector<const Node *>> & tet_nodes_list)
   541   std::vector<dof_id_type> node_ids(4);
   542   for (
unsigned int i = 0; i < 4; i++)
   543     node_ids[i] = pyramid_nodes[i]->
id();
   545   const unsigned int min_node_id_index = std::distance(
   546       std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
   551   std::vector<unsigned int> face_rotation;
   552   std::vector<unsigned int> rotated_indices;
   554   std::vector<const Node *> rotated_pyramid_nodes;
   555   for (
unsigned int i = 0; i < 5; i++)
   556     rotated_pyramid_nodes.push_back(pyramid_nodes[rotated_indices[i]]);
   559   const std::vector<std::vector<unsigned int>> tet_nodes_set = {{0, 1, 2, 4}, {0, 2, 3, 4}};
   560   const std::vector<std::vector<unsigned int>> tet_face_indices = {{4, 0, 1, 5}, {4, 5, 2, 3}};
   564   for (
const auto & tet_face_index : tet_face_indices)
   566     rotated_tet_face_indices.push_back(std::vector<unsigned int>());
   567     for (
const auto & face_index : tet_face_index)
   570         rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
   572         rotated_tet_face_indices.back().push_back(5);
   576   for (
const auto & tet_nodes : tet_nodes_set)
   578     tet_nodes_list.push_back(std::vector<const Node *>());
   579     for (
const auto & tet_node : tet_nodes)
   580       tet_nodes_list.back().push_back(rotated_pyramid_nodes[tet_node]);
   586                        const std::vector<std::pair<dof_id_type, bool>> & elems_to_process,
   587                        std::vector<dof_id_type> & converted_elems_ids_to_track,
   589                        const bool delete_block_to_remove)
   591   std::vector<dof_id_type> converted_elems_ids_to_retain;
   595   for (
const auto & elem_to_process : elems_to_process)
   602                         elem_to_process.first,
   603                         elem_to_process.second ? converted_elems_ids_to_track
   604                                                : converted_elems_ids_to_retain);
   607       case ElemType::PYRAMID5:
   610                             elem_to_process.first,
   611                             elem_to_process.second ? converted_elems_ids_to_track
   612                                                    : converted_elems_ids_to_retain);
   615       case ElemType::PRISM6:
   618                           elem_to_process.first,
   619                           elem_to_process.second ? converted_elems_ids_to_track
   620                                                  : converted_elems_ids_to_retain);
   624         if (elem_to_process.second)
   625           converted_elems_ids_to_track.push_back(elem_to_process.first);
   627           converted_elems_ids_to_retain.push_back(elem_to_process.first);
   634   if (delete_block_to_remove)
   636     for (
auto elem_it = 
mesh.active_subdomain_elements_begin(block_id_to_remove);
   637          elem_it != 
mesh.active_subdomain_elements_end(block_id_to_remove);
   650   std::set<subdomain_id_type> subdomain_ids_set;
   654   std::vector<std::pair<dof_id_type, bool>> original_elems;
   656   for (
auto elem_it = 
mesh.active_elements_begin(); elem_it != 
mesh.active_elements_end();
   659     if ((*elem_it)->default_order() != Order::FIRST)
   660       mooseError(
"Only first order elements are supported for cutting.");
   661     original_elems.push_back(std::make_pair((*elem_it)->id(), 
false));
   664   std::vector<dof_id_type> converted_elems_ids_to_track;
   667       mesh, original_elems, converted_elems_ids_to_track, block_id_to_remove, 
true);
   673                              const unsigned short n_elem_sides,
   674                              std::vector<std::vector<boundary_id_type>> & elem_side_list)
   676   elem_side_list.resize(n_elem_sides);
   677   const auto selected_bdry_side_list =
   678       std::equal_range(bdry_side_list.begin(), bdry_side_list.end(), elem_id, 
BCTupleKeyComp{});
   679   for (
auto selected_bdry_side = selected_bdry_side_list.first;
   680        selected_bdry_side != selected_bdry_side_list.second;
   681        ++selected_bdry_side)
   683     elem_side_list[std::get<1>(*selected_bdry_side)].push_back(std::get<2>(*selected_bdry_side));
   690             const std::vector<unsigned int> & side_indices,
   691             const std::vector<std::vector<boundary_id_type>> & elem_side_info,
   713                   "The provided element type '" + std::to_string(elem_type) +
   714                       "' is not supported and is not supposed to be passed to this function. "   715                       "Only HEX8, PRISM6 and PYRAMID5 are supported.");
   722                 const std::vector<unsigned int> & side_indices,
   723                 const std::vector<std::vector<boundary_id_type>> & elem_side_info,
   734     if (
std::find(side_indices.begin(), side_indices.end(), i_side) != side_indices.end())
   736           mesh, elem_id, i_side, new_node, elem_side_info[i_side], subdomain_id_shift_base);
   739           mesh, elem_id, i_side, new_node, elem_side_info[i_side], subdomain_id_shift_base);
   746                            const unsigned int & side_index,
   747                            const Node * new_node,
   748                            const std::vector<boundary_id_type> & side_info,
   751   auto new_elem = std::make_unique<Pyramid5>();
   756   new_elem->set_node(4, const_cast<Node *>(new_node));
   760   for (
const auto & bid : side_info)
   767                        const unsigned int & side_index,
   768                        const Node * new_node,
   769                        const std::vector<boundary_id_type> & side_info,
   774   unsigned int lid_index = 0;
   782   auto new_elem_0 = std::make_unique<Tet4>();
   783   new_elem_0->set_node(0,
   787   new_elem_0->set_node(1,
   791   new_elem_0->set_node(2,
   795   new_elem_0->set_node(3, const_cast<Node *>(new_node));
   797   auto new_elem_ptr_0 = 
mesh.
add_elem(std::move(new_elem_0));
   800   auto new_elem_1 = std::make_unique<Tet4>();
   801   new_elem_1->set_node(0,
   805   new_elem_1->set_node(1,
   809   new_elem_1->set_node(2,
   813   new_elem_1->set_node(3, const_cast<Node *>(new_node));
   815   auto new_elem_ptr_1 = 
mesh.
add_elem(std::move(new_elem_1));
   818   for (
const auto & bid : side_info)
   828                   const std::vector<unsigned int> & side_indices,
   829                   const std::vector<std::vector<boundary_id_type>> & elem_side_info,
   839     if (i_side % 4 == 0 ||
   840         std::find(side_indices.begin(), side_indices.end(), i_side) != side_indices.end())
   842           mesh, elem_id, i_side, new_node, elem_side_info[i_side], subdomain_id_shift_base);
   845           mesh, elem_id, i_side, new_node, elem_side_info[i_side], subdomain_id_shift_base);
   852                          const unsigned int & side_index,
   853                          const Node * new_node,
   854                          const std::vector<boundary_id_type> & side_info,
   861   bool is_side_quad = (side_index % 4 != 0);
   862   unsigned int lid_index = 0;
   871   auto new_elem_0 = std::make_unique<Tet4>();
   872   new_elem_0->set_node(0,
   876   new_elem_0->set_node(1,
   880   new_elem_0->set_node(2,
   884   new_elem_0->set_node(3, const_cast<Node *>(new_node));
   886   auto new_elem_ptr_0 = 
mesh.
add_elem(std::move(new_elem_0));
   889   Elem * new_elem_ptr_1 = 
nullptr;
   892     auto new_elem_1 = std::make_unique<Tet4>();
   897     new_elem_1->set_node(1,
   901     new_elem_1->set_node(2,
   905     new_elem_1->set_node(3, const_cast<Node *>(new_node));
   911   for (
const auto & bid : side_info)
   922                              const unsigned int & side_index,
   923                              const Node * new_node,
   924                              const std::vector<boundary_id_type> & side_info,
   929       mesh, elem_id, side_index, new_node, side_info, subdomain_id_shift_base);
   935                     const std::vector<std::vector<boundary_id_type>> & elem_side_info,
   939   unsigned int lid_index = 0;
   946   auto new_elem_0 = std::make_unique<Tet4>();
   947   new_elem_0->set_node(
   950   new_elem_0->set_node(
   953   new_elem_0->set_node(
   958   auto new_elem_ptr_0 = 
mesh.
add_elem(std::move(new_elem_0));
   961   auto new_elem_1 = std::make_unique<Tet4>();
   962   new_elem_1->set_node(
   965   new_elem_1->set_node(
   968   new_elem_1->set_node(
   973   auto new_elem_ptr_1 = 
mesh.
add_elem(std::move(new_elem_1));
   976   for (
const auto & bid : elem_side_info[0])
   978   for (
const auto & bid : elem_side_info[1])
   983   for (
const auto & bid : elem_side_info[2])
   985   for (
const auto & bid : elem_side_info[3])
   990   for (
const auto & bid : elem_side_info[4])
  1007                          const std::vector<BoundaryName> & boundary_names,
  1008                          const unsigned int conversion_element_layer_number,
  1009                          const bool external_boundaries_checking)
  1022   std::vector<boundary_id_type> boundary_ids;
  1023   for (
const auto & 
sideset : boundary_names)
  1034   std::vector<std::pair<dof_id_type, std::vector<unsigned int>>> elems_list;
  1035   std::vector<std::set<dof_id_type>> layered_elems_list;
  1036   layered_elems_list.push_back(std::set<dof_id_type>());
  1040   for (
const auto & side_info : side_list)
  1042     if (std::get<2>(side_info) == uniform_tmp_bid)
  1052             "The provided boundary set contains non-linear side elements, which is not supported.");
  1053       const auto side_type =
  1055       layered_elems_list.back().emplace(std::get<0>(side_info));
  1059       const auto neighbor_ptr =
  1063         if (external_boundaries_checking)
  1065               "The provided boundary contains non-external sides, which is required when "  1066               "external_boundaries_checking is enabled.");
  1068           layered_elems_list.back().emplace(neighbor_ptr->id());
  1071       if (conversion_element_layer_number == 1)
  1073         if (side_type == 
TRI3)
  1075         else if (side_type == 
QUAD4)
  1077           auto pit = std::find_if(elems_list.begin(),
  1079                                   [elem_id = std::get<0>(side_info)](
const auto & p)
  1080                                   { 
return p.first == elem_id; });
  1081           if (elems_list.size() && pit != elems_list.end())
  1083             pit->second.push_back(std::get<1>(side_info));
  1086             elems_list.push_back(std::make_pair(
  1087                 std::get<0>(side_info), std::vector<unsigned int>({std::get<1>(side_info)})));
  1090             auto sit = std::find_if(elems_list.begin(),
  1092                                     [elem_id = neighbor_ptr->id()](
const auto & p)
  1093                                     { 
return p.first == elem_id; });
  1094             if (elems_list.size() && sit != elems_list.end())
  1096               sit->second.push_back(
  1097                   neighbor_ptr->which_neighbor_am_i(
mesh.
elem_ptr(std::get<0>(side_info))));
  1101               elems_list.push_back(std::make_pair(
  1103                   std::vector<unsigned int>(
  1104                       {neighbor_ptr->which_neighbor_am_i(
mesh.
elem_ptr(std::get<0>(side_info)))})));
  1109           throw MooseException(
"The provided boundary set contains C0POLYGON side elements, which "  1110                                "is not supported.");
  1113                       "Impossible scenario: a linear non-polygon side element that is neither TRI3 "  1119   if (conversion_element_layer_number > 1)
  1121     std::set<dof_id_type> total_elems_set(layered_elems_list.back());
  1123     while (layered_elems_list.back().size() &&
  1124            layered_elems_list.size() < conversion_element_layer_number)
  1126       layered_elems_list.push_back(std::set<dof_id_type>());
  1127       for (
const auto & elem_id : *(layered_elems_list.end() - 2))
  1134             if (total_elems_set.find(neighbor_id) == total_elems_set.end())
  1136               layered_elems_list.back().emplace(neighbor_id);
  1137               total_elems_set.emplace(neighbor_id);
  1146   if (layered_elems_list.back().empty())
  1147     layered_elems_list.pop_back();
  1149   if (conversion_element_layer_number > layered_elems_list.size())
  1150     throw MooseException(
"There is fewer layers of elements in the input mesh than the requested "  1151                          "number of layers to convert.");
  1153   std::vector<std::pair<dof_id_type, bool>> original_elems;
  1156   const unsigned int n_layer_conversion = layered_elems_list.size() - 1;
  1157   for (
unsigned int i = 0; i < n_layer_conversion; ++i)
  1158     for (
const auto & elem_id : layered_elems_list[i])
  1164         original_elems.push_back(std::make_pair(elem_id, 
false));
  1171   std::vector<dof_id_type> converted_elems_ids_to_track;
  1173       mesh, original_elems, converted_elems_ids_to_track, block_id_to_remove, 
false);
  1178   if (n_layer_conversion)
  1180     for (
const auto & elem_id : layered_elems_list[n_layer_conversion])
  1185             layered_elems_list[n_layer_conversion - 1].count(
  1188           if (elems_list.size() && elems_list.back().first == elem_id)
  1189             elems_list.back().second.push_back(i_side);
  1191             elems_list.push_back(std::make_pair(elem_id, std::vector<unsigned int>({i_side})));
  1198   for (
const auto & elem_info : elems_list)
  1201     std::vector<std::vector<boundary_id_type>> elem_side_info(
  1203     auto side_range = sideset_map.equal_range(
mesh.
elem_ptr(elem_info.first));
  1204     for (
auto i = side_range.first; i != side_range.second; ++i)
  1205       elem_side_info[i->second.first].push_back(i->second.second);
  1208         mesh, elem_info.first, elem_info.second, elem_side_info, sid_shift_base);
  1212   for (
const auto & elem_info : elems_list)
  1214   for (
auto elem_it = 
mesh.active_subdomain_elements_begin(block_id_to_remove);
  1215        elem_it != 
mesh.active_subdomain_elements_end(block_id_to_remove);
  1228     const std::set<subdomain_id_type> & original_subdomain_ids,
  1230     const SubdomainName & tet_suffix,
  1231     const SubdomainName & pyramid_suffix)
  1233   for (
const auto & subdomain_id : original_subdomain_ids)
  1237       const SubdomainName new_name =
  1243             "This suffix for converted TET4 elements results in a subdomain name, " + new_name +
  1244             ", that already exists in the mesh. Please choose a different suffix.");
  1249       const SubdomainName new_name =
  1252           '_' + pyramid_suffix;
  1255             "This suffix for converted PYRAMID5 elements results in a subdomain name, " + new_name +
  1256             ", that already exists in the mesh. Please choose a different suffix.");
 virtual Point true_centroid() const
void remove_id(boundary_id_type id, bool global=false)
void convertPyramid5Elem(ReplicatedMesh &mesh, const dof_id_type &elem_id, const std::vector< std::vector< boundary_id_type >> &elem_side_info, const SubdomainID &subdomain_id_shift_base)
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array. 
void pyramidElemSplitter(ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
virtual Node *& set_node(const unsigned int i)
std::vector< bool > quadFaceDiagonalDirectionsHex(const std::vector< const Node *> &hex_nodes)
virtual Order default_side_order() const
bool hasBoundaryName(const MeshBase &input_mesh, const BoundaryName &name)
Whether a particular boundary name exists in the mesh. 
void nodeRotationHEX8(const unsigned int min_id_index, const unsigned int sec_min_pos, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
Rotate a HEX8 element's nodes to ensure that the node with the minimum id is the first node; and the ...
std::set< std::string > sideset
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
void createUnitTet4FromHex8(ReplicatedMesh &mesh, const dof_id_type &elem_id, const unsigned int &side_index, const Node *new_node, const std::vector< boundary_id_type > &side_info, const SubdomainID &subdomain_id_shift_base)
void createUnitPyramid5FromPrism6(ReplicatedMesh &mesh, const dof_id_type &elem_id, const unsigned int &side_index, const Node *new_node, const std::vector< boundary_id_type > &side_info, const SubdomainID &subdomain_id_shift_base)
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
unsigned int n_elem_integers() const
bool quadFaceDiagonalDirection(const std::vector< const Node *> &quad_nodes)
void hexNodesToTetNodesDeterminer(std::vector< const Node *> &hex_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
void elementBoundaryInfoCollector(const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, const unsigned short n_elem_sides, std::vector< std::vector< boundary_id_type >> &elem_side_list)
Collect the boundary information of the given element in a mesh. 
std::vector< unsigned int > neighborNodeIndicesHEX8(unsigned int min_id_index)
Calculate the indices (within the element nodes) of the three neighboring nodes of a node in a HEX8 e...
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const BoundaryInfo & get_boundary_info() const
void convert3DMeshToAllTet4(ReplicatedMesh &mesh)
void retainEEID(ReplicatedMesh &mesh, const dof_id_type &elem_id, Elem *new_elem_ptr)
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
auto max(const L &left, const R &right)
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh. 
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
Gets the boundary ID associated with the given BoundaryName. 
std::size_t euclideanMod(T1 dividend, T2 divisor)
perform modulo operator for Euclidean division that ensures a non-negative result ...
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true)=0
std::vector< std::vector< unsigned int > > tetNodesForPrism(const bool diagonal_direction, std::vector< std::vector< unsigned int >> &tet_face_indices)
Creates sets of four nodes indices that can form TET4 elements to replace the original PRISM6 element...
virtual void delete_elem(Elem *e)=0
virtual Elem * add_elem(Elem *e)=0
void nodeRotationPRISM6(unsigned int min_id_index, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
Rotate a PRISM6 element nodes to ensure that the node with the minimum id is the first node...
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
void createUnitTet4FromPrism6(ReplicatedMesh &mesh, const dof_id_type &elem_id, const unsigned int &side_index, const Node *new_node, const std::vector< boundary_id_type > &side_info, const SubdomainID &subdomain_id_shift_base)
std::string & subdomain_name(subdomain_id_type id)
void nodeRotationPYRAMID5(unsigned int min_id_index, std::vector< unsigned int > &face_rotation, std::vector< unsigned int > &node_rotation)
Rotate a PYRAMID5 element nodes to ensure that the node with the minimum id is the first node for the...
void convert3DMeshToAllTet4(ReplicatedMesh &mesh, const std::vector< std::pair< dof_id_type, bool >> &elems_to_process, std::vector< dof_id_type > &converted_elems_ids_to_track, const subdomain_id_type block_id_to_remove, const bool delete_block_to_remove)
Convert all the elements in a 3D mesh, consisting of only linear elements, into TET4 elements...
const std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > & get_sideset_map() const
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh. 
void convertElem(ReplicatedMesh &mesh, const dof_id_type &elem_id, const std::vector< unsigned int > &side_indices, const std::vector< std::vector< boundary_id_type >> &elem_side_info, const SubdomainID &subdomain_id_shift_base)
virtual const Elem * elem_ptr(const dof_id_type i) const=0
virtual unsigned int n_sides() const=0
const Elem * neighbor_ptr(unsigned int i) const
Provides a way for users to bail out of the current solve. 
void prismElemSplitter(ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
void assignConvertedElementsSubdomainNameSuffix(ReplicatedMesh &mesh, const std::set< subdomain_id_type > &original_subdomain_ids, const subdomain_id_type sid_shift_base, const SubdomainName &tet_suffix, const SubdomainName &pyramid_suffix)
virtual bool contract()=0
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
subdomain_id_type subdomain_id() const
const Node * node_ptr(const unsigned int i) const
void pyramidNodesToTetNodesDeterminer(std::vector< const Node *> &pyramid_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
void hexElemSplitter(ReplicatedMesh &mesh, const std::vector< libMesh::BoundaryInfo::BCTuple > &bdry_side_list, const dof_id_type elem_id, std::vector< dof_id_type > &converted_elems_ids)
void convertPrism6Elem(ReplicatedMesh &mesh, const dof_id_type &elem_id, const std::vector< unsigned int > &side_indices, const std::vector< std::vector< boundary_id_type >> &elem_side_info, const SubdomainID &subdomain_id_shift_base)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
IntRange< T > make_range(T beg, T end)
void convertHex8Elem(ReplicatedMesh &mesh, const dof_id_type &elem_id, const std::vector< unsigned int > &side_indices, const std::vector< std::vector< boundary_id_type >> &elem_side_info, const SubdomainID &subdomain_id_shift_base)
std::vector< std::vector< unsigned int > > tetNodesForHex(const std::vector< bool > diagonal_directions, std::vector< std::vector< unsigned int >> &tet_face_indices)
Creates sets of four nodes indices that can form TET4 elements to replace the original HEX8 element...
void changeBoundaryId(MeshBase &mesh, const libMesh::boundary_id_type old_id, const libMesh::boundary_id_type new_id, bool delete_prev)
Changes the old boundary ID to a new ID in the mesh. 
SubdomainID getNextFreeSubdomainID(MeshBase &input_mesh)
Checks input mesh and returns max(block ID) + 1, which represents a block ID that is not currently in...
void prismNodesToTetNodesDeterminer(std::vector< const Node *> &prism_nodes, std::vector< std::vector< unsigned int >> &rotated_tet_face_indices, std::vector< std::vector< const Node *>> &tet_nodes_list)
BoundaryID getNextFreeBoundaryID(MeshBase &input_mesh)
Checks input mesh and returns the largest boundary ID in the mesh plus one, which is a boundary ID in...
void createUnitPyramid5FromHex8(ReplicatedMesh &mesh, const dof_id_type &elem_id, const unsigned int &side_index, const Node *new_node, const std::vector< boundary_id_type > &side_info, const SubdomainID &subdomain_id_shift_base)
virtual ElemType type() const=0
auto index_range(const T &sizable)
void set_extra_integer(const unsigned int index, const dof_id_type value)
void transitionLayerGenerator(ReplicatedMesh &mesh, const std::vector< BoundaryName > &boundary_names, const unsigned int conversion_element_layer_number, const bool external_boundaries_checking)
dof_id_type get_extra_integer(const unsigned int index) const