293 std::vector<std::vector<unsigned int>> & rotated_tet_face_indices,
294 std::vector<std::vector<const Node *>> & tet_nodes_list)
297 std::vector<dof_id_type> node_ids(8);
298 for (
unsigned int i = 0; i < 8; i++)
299 node_ids[i] = hex_nodes[i]->
id();
301 const unsigned int min_node_id_index = std::distance(
302 std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
308 const auto neighbor_node_ids = {node_ids[neighbor_node_indices[0]],
309 node_ids[neighbor_node_indices[1]],
310 node_ids[neighbor_node_indices[2]]};
311 const unsigned int sec_min_pos =
312 std::distance(std::begin(neighbor_node_ids),
313 std::min_element(std::begin(neighbor_node_ids), std::end(neighbor_node_ids)));
319 std::vector<unsigned int> face_rotation;
320 std::vector<unsigned int> rotated_indices;
321 nodeRotationHEX8(min_node_id_index, sec_min_pos, face_rotation, rotated_indices);
322 std::vector<const Node *> rotated_hex_nodes;
323 for (
unsigned int i = 0; i < 8; i++)
324 rotated_hex_nodes.push_back(hex_nodes[rotated_indices[i]]);
331 std::vector<std::vector<unsigned int>> tet_face_indices;
332 const auto tet_nodes_set =
tetNodesForHex(diagonal_directions, tet_face_indices);
333 for (
const auto & tet_face_index : tet_face_indices)
335 rotated_tet_face_indices.push_back(std::vector<unsigned int>());
336 for (
const auto & face_index : tet_face_index)
339 rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
341 rotated_tet_face_indices.back().push_back(6);
345 for (
const auto & tet_nodes : tet_nodes_set)
347 tet_nodes_list.push_back(std::vector<const Node *>());
348 for (
const auto & tet_node : tet_nodes)
349 tet_nodes_list.back().push_back(rotated_hex_nodes[tet_node]);
386 std::vector<std::vector<unsigned int>> & tet_face_indices)
388 const std::vector<std::vector<bool>> possible_inputs = {{
true,
true,
true,
true,
true,
false},
389 {
true,
true,
true,
true,
false,
false},
390 {
true,
true,
true,
false,
true,
false},
391 {
true,
false,
true,
true,
true,
false},
392 {
true,
false,
true,
true,
false,
false},
393 {
true,
false,
true,
false,
true,
false},
394 {
true,
false,
true,
false,
false,
false}};
396 const unsigned int input_index = std::distance(
397 std::begin(possible_inputs),
398 std::find(std::begin(possible_inputs), std::end(possible_inputs), diagonal_directions));
404 {0, 6, 2, 6}, {1, 6, 2, 6}, {1, 6, 5, 6}, {0, 6, 3, 4}, {6, 6, 3, 6}, {6, 4, 5, 6}};
405 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}};
408 {0, 1, 2, 6}, {6, 6, 2, 6}, {6, 6, 5, 1}, {0, 6, 3, 4}, {6, 6, 3, 6}, {6, 4, 5, 6}};
409 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}};
412 {0, 6, 2, 6}, {1, 6, 2, 6}, {1, 6, 5, 6}, {4, 6, 5, 6}, {4, 6, 3, 6}, {0, 6, 3, 6}};
413 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}};
416 {4, 6, 5, 1}, {6, 6, 5, 6}, {6, 1, 2, 6}, {4, 0, 3, 6}, {6, 6, 3, 6}, {6, 6, 2, 0}};
417 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}};
419 tet_face_indices = {{0, 1, 2, 6}, {0, 6, 3, 4}, {5, 4, 6, 1}, {5, 6, 3, 2}, {6, 6, 6, 6}};
420 return {{0, 1, 2, 5}, {0, 2, 3, 7}, {4, 7, 5, 0}, {5, 7, 6, 2}, {0, 2, 7, 5}};
423 {4, 6, 5, 1}, {6, 6, 5, 6}, {6, 1, 2, 6}, {2, 6, 6, 0}, {3, 6, 6, 0}, {3, 6, 6, 4}};
424 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}};
427 {1, 4, 5, 6}, {6, 6, 5, 6}, {6, 6, 3, 4}, {1, 6, 2, 0}, {6, 6, 2, 6}, {6, 0, 3, 6}};
428 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}};
436 const unsigned int sec_min_pos,
437 std::vector<unsigned int> & face_rotation,
438 std::vector<unsigned int> & node_rotation)
444 const std::vector<std::vector<std::vector<unsigned int>>> preset_indices = {
445 {{0, 1, 2, 3, 4, 5, 6, 7}, {0, 3, 7, 4, 1, 2, 6, 5}, {0, 4, 5, 1, 3, 7, 6, 2}},
446 {{1, 0, 4, 5, 2, 3, 7, 6}, {1, 2, 3, 0, 5, 6, 7, 4}, {1, 5, 6, 2, 0, 4, 7, 3}},
447 {{2, 3, 0, 1, 6, 7, 4, 5}, {2, 1, 5, 6, 3, 0, 4, 7}, {2, 6, 7, 3, 1, 5, 4, 0}},
448 {{3, 2, 6, 7, 0, 1, 5, 4}, {3, 0, 1, 2, 7, 4, 5, 6}, {3, 7, 4, 0, 2, 6, 5, 1}},
449 {{4, 5, 1, 0, 7, 6, 2, 3}, {4, 7, 6, 5, 0, 3, 2, 1}, {4, 0, 3, 7, 5, 1, 2, 6}},
450 {{5, 4, 7, 6, 1, 0, 3, 2}, {5, 6, 2, 1, 4, 7, 3, 0}, {5, 1, 0, 4, 6, 2, 3, 7}},
451 {{6, 7, 3, 2, 5, 4, 0, 1}, {6, 5, 4, 7, 2, 1, 0, 3}, {6, 2, 1, 5, 7, 3, 0, 4}},
452 {{7, 6, 5, 4, 3, 2, 1, 0}, {7, 4, 0, 3, 6, 5, 1, 2}, {7, 3, 2, 6, 4, 0, 1, 5}}};
454 const std::vector<std::vector<std::vector<unsigned int>>> preset_face_indices = {
455 {{0, 1, 2, 3, 4, 5}, {4, 0, 3, 5, 1, 2}, {1, 4, 5, 2, 0, 3}},
456 {{1, 0, 4, 5, 2, 3}, {0, 2, 3, 4, 1, 5}, {2, 1, 5, 3, 0, 4}},
457 {{0, 3, 4, 1, 2, 5}, {2, 0, 1, 5, 3, 4}, {3, 2, 5, 4, 0, 1}},
458 {{3, 0, 2, 5, 4, 1}, {0, 4, 1, 2, 3, 5}, {4, 3, 5, 1, 0, 2}},
459 {{1, 5, 2, 0, 4, 3}, {5, 4, 3, 2, 1, 0}, {4, 1, 0, 3, 5, 2}},
460 {{5, 1, 4, 3, 2, 0}, {2, 5, 3, 0, 1, 4}, {1, 2, 0, 4, 5, 3}},
461 {{3, 5, 4, 0, 2, 1}, {5, 2, 1, 4, 3, 0}, {2, 3, 0, 1, 5, 4}},
462 {{5, 3, 2, 1, 4, 0}, {4, 5, 1, 0, 3, 2}, {3, 4, 0, 2, 5, 1}}};
464 if (min_id_index > 7 || sec_min_pos > 2)
465 mooseError(
"The input node index is out of range.");
469 face_rotation = preset_face_indices[min_id_index][sec_min_pos];
470 node_rotation = preset_indices[min_id_index][sec_min_pos];
598 std::vector<std::vector<unsigned int>> & rotated_tet_face_indices,
599 std::vector<std::vector<const Node *>> & tet_nodes_list)
602 std::vector<dof_id_type> node_ids(4);
603 for (
unsigned int i = 0; i < 4; i++)
604 node_ids[i] = pyramid_nodes[i]->
id();
606 const unsigned int min_node_id_index = std::distance(
607 std::begin(node_ids), std::min_element(std::begin(node_ids), std::end(node_ids)));
612 std::vector<unsigned int> face_rotation;
613 std::vector<unsigned int> rotated_indices;
615 std::vector<const Node *> rotated_pyramid_nodes;
616 for (
unsigned int i = 0; i < 5; i++)
617 rotated_pyramid_nodes.push_back(pyramid_nodes[rotated_indices[i]]);
620 const std::vector<std::vector<unsigned int>> tet_nodes_set = {{0, 1, 2, 4}, {0, 2, 3, 4}};
621 const std::vector<std::vector<unsigned int>> tet_face_indices = {{4, 0, 1, 5}, {4, 5, 2, 3}};
625 for (
const auto & tet_face_index : tet_face_indices)
627 rotated_tet_face_indices.push_back(std::vector<unsigned int>());
628 for (
const auto & face_index : tet_face_index)
631 rotated_tet_face_indices.back().push_back(face_rotation[face_index]);
633 rotated_tet_face_indices.back().push_back(5);
637 for (
const auto & tet_nodes : tet_nodes_set)
639 tet_nodes_list.push_back(std::vector<const Node *>());
640 for (
const auto & tet_node : tet_nodes)
641 tet_nodes_list.back().push_back(rotated_pyramid_nodes[tet_node]);
1082 const std::vector<BoundaryName> & boundary_names,
1083 const unsigned int conversion_element_layer_number,
1084 const bool external_boundaries_checking)
1087 "This method only supports serial meshes. If you are calling this method with a "
1088 "distributed mesh, please serialize it first.");
1093 if (sid_shift_base * 3 > std::numeric_limits<subdomain_id_type>::max())
1100 std::vector<boundary_id_type> boundary_ids;
1101 for (
const auto &
sideset : boundary_names)
1112 std::vector<std::pair<dof_id_type, std::vector<unsigned int>>> elems_list;
1113 std::vector<std::set<dof_id_type>> layered_elems_list;
1114 layered_elems_list.push_back(std::set<dof_id_type>());
1118 for (
const auto & side_info : side_list)
1120 if (std::get<2>(side_info) == uniform_tmp_bid)
1130 "The provided boundary set contains non-linear side elements, which is not supported.");
1131 const auto side_type =
1132 mesh.
elem_ptr(std::get<0>(side_info))->side_ptr(std::get<1>(side_info))->type();
1133 layered_elems_list.back().emplace(std::get<0>(side_info));
1137 const auto neighbor_ptr =
1138 mesh.
elem_ptr(std::get<0>(side_info))->neighbor_ptr(std::get<1>(side_info));
1141 if (external_boundaries_checking)
1143 "The provided boundary contains non-external sides, which is required when "
1144 "external_boundaries_checking is enabled.");
1146 layered_elems_list.back().emplace(neighbor_ptr->id());
1149 if (conversion_element_layer_number == 1)
1151 if (side_type ==
TRI3)
1153 else if (side_type ==
QUAD4)
1155 auto pit = std::find_if(elems_list.begin(),
1157 [elem_id = std::get<0>(side_info)](
const auto & p)
1158 { return p.first == elem_id; });
1159 if (elems_list.size() && pit != elems_list.end())
1161 pit->second.push_back(std::get<1>(side_info));
1164 elems_list.push_back(std::make_pair(
1165 std::get<0>(side_info), std::vector<unsigned int>({std::get<1>(side_info)})));
1168 auto sit = std::find_if(elems_list.begin(),
1170 [elem_id = neighbor_ptr->id()](
const auto & p)
1171 { return p.first == elem_id; });
1172 if (elems_list.size() && sit != elems_list.end())
1174 sit->second.push_back(
1175 neighbor_ptr->which_neighbor_am_i(
mesh.
elem_ptr(std::get<0>(side_info))));
1179 elems_list.push_back(std::make_pair(
1181 std::vector<unsigned int>(
1182 {neighbor_ptr->which_neighbor_am_i(mesh.elem_ptr(std::get<0>(side_info)))})));
1187 throw MooseException(
"The provided boundary set contains C0POLYGON side elements, which "
1188 "is not supported.");
1191 "Impossible scenario: a linear non-polygon side element that is neither TRI3 "
1197 if (conversion_element_layer_number > 1)
1199 std::set<dof_id_type> total_elems_set(layered_elems_list.back());
1201 while (layered_elems_list.back().size() &&
1202 layered_elems_list.size() < conversion_element_layer_number)
1204 layered_elems_list.push_back(std::set<dof_id_type>());
1205 for (
const auto & elem_id : *(layered_elems_list.end() - 2))
1212 if (total_elems_set.find(neighbor_id) == total_elems_set.end())
1214 layered_elems_list.back().emplace(neighbor_id);
1215 total_elems_set.emplace(neighbor_id);
1224 if (layered_elems_list.back().empty())
1225 layered_elems_list.pop_back();
1227 if (conversion_element_layer_number > layered_elems_list.size())
1228 throw MooseException(
"There is fewer layers of elements in the input mesh than the requested "
1229 "number of layers to convert.");
1231 std::vector<std::pair<dof_id_type, bool>> original_elems;
1234 const unsigned int n_layer_conversion = layered_elems_list.size() - 1;
1235 for (
unsigned int i = 0; i < n_layer_conversion; ++i)
1236 for (
const auto & elem_id : layered_elems_list[i])
1242 original_elems.push_back(std::make_pair(elem_id,
false));
1249 std::vector<dof_id_type> converted_elems_ids_to_track;
1251 mesh, original_elems, converted_elems_ids_to_track, block_id_to_remove,
false);
1256 if (n_layer_conversion)
1258 for (
const auto & elem_id : layered_elems_list[n_layer_conversion])
1263 layered_elems_list[n_layer_conversion - 1].count(
1266 if (elems_list.size() && elems_list.back().first == elem_id)
1267 elems_list.back().second.push_back(i_side);
1269 elems_list.push_back(std::make_pair(elem_id, std::vector<unsigned int>({i_side})));
1276 for (
const auto & elem_info : elems_list)
1279 std::vector<std::vector<boundary_id_type>> elem_side_info(
1281 auto side_range = sideset_map.equal_range(
mesh.
elem_ptr(elem_info.first));
1282 for (
auto i = side_range.first; i != side_range.second; ++i)
1283 elem_side_info[i->second.first].push_back(i->second.second);
1286 mesh, elem_info.first, elem_info.second, elem_side_info, sid_shift_base);
1290 for (
const auto & elem_info : elems_list)
1292 for (
auto elem_it =
mesh.active_subdomain_elements_begin(block_id_to_remove);
1293 elem_it !=
mesh.active_subdomain_elements_end(block_id_to_remove);