414 mesh->set_mesh_dimension(
_input->mesh_dimension() + 1);
425 " of 'elem_integer_names_to_swap' in is not a valid extra element integer of the "
429 const unsigned int num_extra_elem_integers =
_input->n_elem_integers();
430 std::vector<std::string> id_names;
432 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
434 id_names.push_back(
_input->get_elem_integer_name(i));
435 if (!
mesh->has_elem_integer(id_names[i]))
436 mesh->add_elem_integer(id_names[i]);
440 if (!
_input->preparation().has_cached_elem_data)
441 _input->cache_elem_data();
442 const auto & input_subdomain_map =
_input->get_subdomain_name_map();
443 const auto & input_sideset_map =
_input->get_boundary_info().get_sideset_name_map();
444 const auto & input_nodeset_map =
_input->get_boundary_info().get_nodeset_name_map();
448 for (
const auto i : index_range(swap))
450 paramError(
"subdomain_swaps",
"The block '", swap[i],
"' was not found within the mesh");
454 for (
const auto i : index_range(swap))
456 paramError(
"boundary_swaps",
"The boundary '", swap[i],
"' was not found within the mesh");
460 for (
const auto bid : layer_vec)
463 "upward_boundary_source_blocks",
"The block '", bid,
"' was not found within the mesh");
465 for (
const auto bid : layer_vec)
470 "' was not found within the mesh");
473 std::unique_ptr<MeshBase> input = std::move(
_input);
474 std::unique_ptr<MeshBase> extrusion_curve;
479 std::unique_ptr<libMesh::MeshSerializer> serializer;
481 serializer = std::make_unique<libMesh::MeshSerializer>(*extrusion_curve);
485 if (!input->is_serial())
487 input->delete_remote_elements();
489 mesh->delete_remote_elements();
492 if (input->n_nodes() != input->max_node_id())
493 input->renumber_nodes_and_elements();
495 if (input->n_nodes() != input->max_node_id())
497 "You must allow renumbering, because the extruded mesh should be contiguously numbered. "
498 "Alternatively, you can use a separate mesh generator (MeshRepairGenerator with the "
499 "renumber_contiguously parameter for example) to renumber the nodes contiguously.");
501 unsigned int total_num_layers;
502 unsigned int total_num_elevations;
506 total_num_elevations =
_heights.size();
510 total_num_layers = extrusion_curve->n_elem();
511 total_num_elevations = 1;
514 dof_id_type orig_elem = input->n_elem();
515 dof_id_type orig_nodes = input->n_nodes();
517#ifdef LIBMESH_ENABLE_UNIQUE_ID
518 unique_id_type orig_unique_ids = input->parallel_max_unique_id();
519 bool has_poly_midnodes =
false;
522 bool has_polygons =
false;
523 unsigned int order = 1;
525 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
526 const BoundaryInfo & input_boundary_info = input->get_boundary_info();
529 std::vector<BoundaryName> new_boundary_names;
534 std::vector<boundary_id_type> new_boundary_ids =
536 const auto user_bottom_boundary_id =
538 const auto user_top_boundary_id =
542 mesh->reserve_elem(total_num_layers * orig_elem);
545 std::set<ElemType> higher_orders = {EDGE3, EDGE4, TRI6, TRI7, QUAD8, QUAD9};
546 bool extruding_quad_eights =
false;
547 std::vector<ElemType> types;
549 for (
const auto elem_type : types)
551 if (higher_orders.count(elem_type))
553 if (elem_type == QUAD8)
554 extruding_quad_eights =
true;
556 mesh->comm().max(order);
557 mesh->comm().max(extruding_quad_eights);
560 mesh->reserve_nodes((order * total_num_layers + 1) * orig_nodes);
563 std::vector<boundary_id_type> ids_to_copy;
566 Real start_radial_extent = 0;
567 Point reference_point;
569 reference_point = *(extrusion_curve->node_ptr(0));
570 else if (!MooseUtils::absoluteFuzzyEqual(
_twist_pitch, 0.))
572 reference_point = Point(0, 0, 0);
580 RealVectorValue reference_direction;
582 reference_direction =
586 (*(extrusion_curve->node_ptr(1)) - *(extrusion_curve->node_ptr(0))).unit());
591 start_radial_extent =
596 Real total_extrusion_distance_at_axis;
599 if (!extrusion_curve->is_prepared())
600 extrusion_curve->prepare_for_use();
604 total_extrusion_distance_at_axis = std::accumulate(
_heights.begin(),
_heights.end(), 0);
607 for (
const auto & node : input->node_ptr_range())
609 unsigned int current_node_layer = 0;
610 Point orig_node_to_previous;
611 Point orig_node_to_current;
612 Real sum_step_sizes = 0.;
613 Real sum_step_sizes_at_axis = 0.;
615 Real start_node_radius = (*node - reference_point).norm();
618 for (
const auto e : make_range(total_num_elevations))
621 Real height = std::numeric_limits<Real>::max(), bias = std::numeric_limits<Real>::max();
624 num_layers = extrusion_curve->n_elem();
634 unsigned int num_heights_at_elevation = order * num_layers + (e == 0 ? 1 : 0);
639 for (
const auto k : make_range(num_heights_at_elevation))
643 if (e == 0 && k == 0)
644 orig_node_to_current.
zero();
652 Real step_size_at_axis = 0;
656 const Node * P_current = extrusion_curve->node_ptr(k);
658 const Node * P_prev = extrusion_curve->node_ptr(k - 1);
661 const auto old_node = orig_node_to_previous + *node;
662 RealVectorValue b_vec = old_node - *P_prev;
663 Real node_distance_to_curve = b_vec.norm();
669 RealVectorValue intersecting_plane_normal_vec;
674 const auto P_next = extrusion_curve->node_ptr(k + 1);
675 intersecting_plane_normal_vec =
678 else if (k < order * num_layers - 1)
680 const auto P_next = extrusion_curve->node_ptr(k + 1);
682 intersecting_plane_normal_vec = *P_next - *P_prev;
688 : RealVectorValue(*P_current - *P_prev);
690 intersecting_plane_normal_vec /= intersecting_plane_normal_vec.norm();
692 Point new_node_point;
695 if (MooseUtils::absoluteFuzzyEqual(
696 prev_intersecting_plane_normal_vec.cross(intersecting_plane_normal_vec)
699 new_node_point = old_node + *P_current - *P_prev;
707 auto axis = prev_intersecting_plane_normal_vec.cross(intersecting_plane_normal_vec);
708 const auto sin_th = axis.norm();
710 Real cos_th = prev_intersecting_plane_normal_vec * intersecting_plane_normal_vec;
712 const auto new_v = cos_th * b_vec + axis.cross(b_vec) * sin_th +
713 axis * (axis * b_vec) * (1. - cos_th);
715 mooseAssert(MooseUtils::absoluteFuzzyEqual(new_v.norm(), b_vec.norm()),
716 "Radial extent be conserved");
717 new_node_point = *P_current + new_v;
720 orig_node_to_current = new_node_point - *node;
722 step_size = (orig_node_to_current - orig_node_to_previous).norm();
723 step_size_at_axis = (*P_current - *P_prev).norm();
724 prev_intersecting_plane_normal_vec = intersecting_plane_normal_vec;
732 "Norm of direction vector is not 1!");
737 step_size = ((*P_current - (orig_node_to_previous + *node)) *
_direction);
738 step_size_at_axis = step_size;
739 orig_node_to_current = orig_node_to_previous +
_direction * step_size;
747 auto layer_index = (k - (e == 0 ? 1 : 0)) / order + 1;
748 step_size = MooseUtils::absoluteFuzzyEqual(bias, 1.0)
749 ? height / (Real)num_layers / (Real)order
750 : height *
std::pow(bias, (Real)(layer_index - 1)) * (1.0 - bias) /
751 (1.0 -
std::pow(bias, (Real)(num_layers))) / (Real)order;
752 step_size_at_axis = step_size;
753 orig_node_to_current =
754 orig_node_to_previous +
759 sum_step_sizes += step_size;
760 sum_step_sizes_at_axis += step_size_at_axis;
768 (sum_step_sizes_at_axis - step_size_at_axis) / total_extrusion_distance_at_axis;
769 Real t = sum_step_sizes_at_axis / total_extrusion_distance_at_axis;
772 RealVectorValue node_to_extrusion_axis;
774 node_to_extrusion_axis =
775 *node + orig_node_to_current - *(extrusion_curve->node_ptr(k));
777 else if (!MooseUtils::absoluteFuzzyEqual(
_twist_pitch, 0.))
778 node_to_extrusion_axis =
779 *node + orig_node_to_current - (reference_point +
_direction * sum_step_sizes);
783 node_to_extrusion_axis = *node - reference_point;
786 const auto radius_scaling = start_node_radius / start_radial_extent;
792 orig_node_to_current += (start_radial_extent * (radial_ratio_m1 - radial_ratio) +
794 radius_scaling * node_to_extrusion_axis.unit();
803 if (!MooseUtils::absoluteFuzzyEqual(twist1.norm(), .0))
804 twist1 /= twist1.norm();
821 Point extrusion_axis_at_elevation;
822 Point prev_extrusion_axis_at_elevation;
825 extrusion_axis_at_elevation = *extrusion_curve->node_ptr(k);
826 prev_extrusion_axis_at_elevation = *extrusion_curve->node_ptr(k - 1);
831 extrusion_axis_at_elevation = reference_point +
_direction * sum_step_sizes;
832 prev_extrusion_axis_at_elevation =
833 reference_point +
_direction * (sum_step_sizes - step_size);
837 twist *= (*node + orig_node_to_current - extrusion_axis_at_elevation).norm();
840 if (!MooseUtils::absoluteFuzzyEqual(twist1.norm(), .0))
841 orig_node_to_current += twist;
846 Node * new_node =
mesh->add_point(*node + orig_node_to_current,
847 node->id() + (current_node_layer * orig_nodes),
848 node->processor_id());
850#ifdef LIBMESH_ENABLE_UNIQUE_ID
854 const unique_id_type uid = (current_node_layer == 0)
857 (current_node_layer - 1) * (orig_elem + orig_nodes) +
859 new_node->set_unique_id(uid);
863 input_boundary_info.boundary_ids(node, ids_to_copy);
865 boundary_info.add_node(new_node, ids_to_copy);
867 for (
const auto & id_to_copy : ids_to_copy)
869 boundary_info.add_node(new_node,
875 orig_node_to_previous = orig_node_to_current;
876 current_node_layer++;
881 const auto & side_ids = input_boundary_info.get_side_boundary_ids();
883 boundary_id_type next_side_id =
884 side_ids.empty() ? 0 : cast_int<boundary_id_type>(*side_ids.rbegin() + 1);
889 input->comm().max(next_side_id);
892 std::map<std::array<unsigned int, 3>, std::shared_ptr<libMesh::Polygon>> poly_extruded_sides;
895 for (
const auto & elem : input->element_ptr_range())
897 const ElemType etype = elem->type();
900 libmesh_assert(!elem->parent());
902 unsigned int current_layer = 0;
904 for (
unsigned int e = 0; e != total_num_elevations; e++)
908 for (
unsigned int k = 0; k != num_layers; ++k)
910 std::unique_ptr<Elem> new_elem;
911 bool is_flipped(
false);
916 new_elem = std::make_unique<Quad4>();
918 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
920 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
922 2,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
924 3,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
926 if (elem->neighbor_ptr(0) == remote_elem)
927 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
928 if (elem->neighbor_ptr(1) == remote_elem)
929 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
935 new_elem = std::make_unique<Quad9>();
937 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
939 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
942 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
945 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
947 4,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
950 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
953 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
956 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
959 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
961 if (elem->neighbor_ptr(0) == remote_elem)
962 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
963 if (elem->neighbor_ptr(1) == remote_elem)
964 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
970 new_elem = std::make_unique<Prism6>();
972 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
974 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
976 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * orig_nodes)));
978 3,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
980 4,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
982 5,
mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer + 1) * orig_nodes)));
984 if (elem->neighbor_ptr(0) == remote_elem)
985 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
986 if (elem->neighbor_ptr(1) == remote_elem)
987 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
988 if (elem->neighbor_ptr(2) == remote_elem)
989 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
991 if (new_elem->volume() < 0.0)
1003 new_elem = std::make_unique<Prism18>();
1005 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1007 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1009 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1012 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1015 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1018 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1020 6,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1022 7,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1024 8,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1027 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1030 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1033 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1036 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1039 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1042 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1045 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1048 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
1051 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
1053 if (elem->neighbor_ptr(0) == remote_elem)
1054 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1055 if (elem->neighbor_ptr(1) == remote_elem)
1056 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1057 if (elem->neighbor_ptr(2) == remote_elem)
1058 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1060 if (new_elem->volume() < 0.0)
1075 new_elem = std::make_unique<Prism21>();
1077 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1079 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1081 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1084 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1087 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1090 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1092 6,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1094 7,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1096 8,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1099 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1102 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1105 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1108 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1111 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1114 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1117 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1120 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
1123 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
1125 18,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
1128 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
1131 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 1) * orig_nodes)));
1133 if (elem->neighbor_ptr(0) == remote_elem)
1134 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1135 if (elem->neighbor_ptr(1) == remote_elem)
1136 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1137 if (elem->neighbor_ptr(2) == remote_elem)
1138 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1140 if (new_elem->volume() < 0.0)
1156 new_elem = std::make_unique<Hex8>();
1158 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
1160 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
1162 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * orig_nodes)));
1164 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (current_layer * orig_nodes)));
1166 4,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
1168 5,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
1170 6,
mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer + 1) * orig_nodes)));
1172 7,
mesh->node_ptr(elem->node_ptr(3)->id() + ((current_layer + 1) * orig_nodes)));
1174 if (elem->neighbor_ptr(0) == remote_elem)
1175 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1176 if (elem->neighbor_ptr(1) == remote_elem)
1177 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1178 if (elem->neighbor_ptr(2) == remote_elem)
1179 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1180 if (elem->neighbor_ptr(3) == remote_elem)
1181 new_elem->set_neighbor(4,
const_cast<RemoteElem *
>(remote_elem));
1183 if (new_elem->volume() < 0.0)
1196 new_elem = std::make_unique<Hex20>();
1198 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1200 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1202 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1204 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1207 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1210 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1213 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1216 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1218 8,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1220 9,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1222 10,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
1224 11,
mesh->node_ptr(elem->node_ptr(7)->id() + (2 * current_layer * orig_nodes)));
1227 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1230 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1233 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1236 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1239 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1242 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1245 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
1248 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 2) * orig_nodes)));
1250 if (elem->neighbor_ptr(0) == remote_elem)
1251 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1252 if (elem->neighbor_ptr(1) == remote_elem)
1253 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1254 if (elem->neighbor_ptr(2) == remote_elem)
1255 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1256 if (elem->neighbor_ptr(3) == remote_elem)
1257 new_elem->set_neighbor(4,
const_cast<RemoteElem *
>(remote_elem));
1259 if (new_elem->volume() < 0.0)
1276 new_elem = std::make_unique<Hex27>();
1278 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1280 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1282 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1284 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1287 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1290 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1293 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1296 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1298 8,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1300 9,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1302 10,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
1304 11,
mesh->node_ptr(elem->node_ptr(7)->id() + (2 * current_layer * orig_nodes)));
1307 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1310 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1313 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1316 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1319 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1322 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1325 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
1328 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 2) * orig_nodes)));
1330 20,
mesh->node_ptr(elem->node_ptr(8)->id() + (2 * current_layer * orig_nodes)));
1333 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
1336 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
1339 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 1) * orig_nodes)));
1342 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 1) * orig_nodes)));
1345 mesh->node_ptr(elem->node_ptr(8)->id() + ((2 * current_layer + 2) * orig_nodes)));
1348 mesh->node_ptr(elem->node_ptr(8)->id() + ((2 * current_layer + 1) * orig_nodes)));
1350 if (elem->neighbor_ptr(0) == remote_elem)
1351 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1352 if (elem->neighbor_ptr(1) == remote_elem)
1353 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1354 if (elem->neighbor_ptr(2) == remote_elem)
1355 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1356 if (elem->neighbor_ptr(3) == remote_elem)
1357 new_elem->set_neighbor(4,
const_cast<RemoteElem *
>(remote_elem));
1359 if (new_elem->volume() < 0.0)
1377 has_polygons =
true;
1378 const auto num_sides = elem->n_sides();
1379 std::vector<std::shared_ptr<libMesh::Polygon>>
sides;
1380 sides.reserve(2 + num_sides);
1382 mooseError(
"Too many nodes in polygons to extrude it. Max number of the prism "
1383 "polyhedral nodes after extrusion: " +
1386 auto new_ptr = std::make_shared<libMesh::C0Polygon>(num_sides);
1387 for (
const auto node_i : make_range(elem->n_nodes()))
1393 mesh->node_ptr(elem->node_ptr(node_i)->id() + (current_layer * orig_nodes)));
1395 sides.push_back(new_ptr);
1397 auto translated_side = std::make_shared<libMesh::C0Polygon>(num_sides);
1398 for (
const auto node_i : make_range(elem->n_nodes()))
1399 translated_side->set_node(node_i,
1400 mesh->node_ptr(elem->node_ptr(node_i)->id() +
1401 ((current_layer + 1) * orig_nodes)));
1402 sides.push_back(translated_side);
1405 for (
const auto side_i : make_range(num_sides))
1408 std::array<unsigned int, 3> side_key = {
1410 static_cast<unsigned int>(
1411 std::min(elem->node_ptr(side_i)->id(),
1412 elem->node_ptr((side_i + 1) % num_sides)->id())),
1413 static_cast<unsigned int>(
1414 std::max(elem->node_ptr(side_i)->id(),
1415 elem->node_ptr((side_i + 1) % num_sides)->id()))};
1416 if (poly_extruded_sides.count(side_key))
1418 sides.push_back(poly_extruded_sides[side_key]);
1423 auto vert_side = std::make_shared<libMesh::C0Polygon>(4);
1424 vert_side->set_node(
1425 0,
mesh->node_ptr(elem->node_ptr(side_i)->id() + (current_layer * orig_nodes)));
1426 vert_side->set_node(1,
1427 mesh->node_ptr(elem->node_ptr((side_i + 1) % num_sides)->id() +
1428 (current_layer * orig_nodes)));
1429 vert_side->set_node(2,
1430 mesh->node_ptr(elem->node_ptr((side_i + 1) % num_sides)->id() +
1431 ((current_layer + 1) * orig_nodes)));
1432 vert_side->set_node(3,
1433 mesh->node_ptr(elem->node_ptr(side_i)->id() +
1434 ((current_layer + 1) * orig_nodes)));
1435 sides.push_back(vert_side);
1437 poly_extruded_sides.insert(std::make_pair(side_key, vert_side));
1439 mooseAssert(
sides.size() == 2 + num_sides,
"Unexpected size of side vector");
1442 std::unique_ptr<libMesh::Node> mid_elem_node;
1443 new_elem = std::make_unique<libMesh::C0Polyhedron>(
sides, mid_elem_node);
1446#ifdef LIBMESH_ENABLE_UNIQUE_ID
1449 unsigned int total_new_node_layers = total_num_layers * order;
1450 unsigned int last_uid = orig_unique_ids + (total_new_node_layers - 1) * orig_elem +
1451 total_new_node_layers * orig_nodes + elem->unique_id();
1452 mid_elem_node->set_unique_id(last_uid);
1453 has_poly_midnodes =
true;
1455 mesh->add_node(std::move(mid_elem_node));
1464 new_elem->set_id(elem->id() + (current_layer * orig_elem));
1465 new_elem->processor_id() = elem->processor_id();
1467#ifdef LIBMESH_ENABLE_UNIQUE_ID
1471 const unique_id_type uid = (current_layer == 0)
1474 (current_layer - 1) * (orig_elem + orig_nodes) +
1475 orig_nodes + elem->id();
1477 new_elem->set_unique_id(uid);
1481 new_elem->subdomain_id() = elem->subdomain_id();
1484 if (k == num_layers - 1)
1487 const unsigned short top_id =
1488 new_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1494 boundary_info.add_side(
1500 const unsigned short top_id =
1501 new_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1505 boundary_info.add_side(
1514 auto new_id_it = elevation_swap_pairs.find(elem->subdomain_id());
1516 if (new_id_it != elevation_swap_pairs.end())
1517 new_elem->subdomain_id() = new_id_it->second;
1520 Elem * added_elem =
mesh->add_elem(std::move(new_elem));
1523 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
1524 added_elem->set_extra_integer(i, elem->get_extra_integer(i));
1532 auto new_extra_id_it = elevation_extra_swap_pairs.find(
1535 if (new_extra_id_it != elevation_extra_swap_pairs.end())
1537 new_extra_id_it->second);
1542 for (
auto s : elem->side_index_range())
1544 input_boundary_info.boundary_ids(elem, s, ids_to_copy);
1546 if (added_elem->dim() == 3)
1553 boundary_info.add_side(added_elem, cast_int<unsigned short>(s + 1), ids_to_copy);
1555 for (
const auto & id_to_copy : ids_to_copy)
1556 boundary_info.add_side(added_elem,
1557 cast_int<unsigned short>(s + 1),
1568 libmesh_assert_less(s, 2);
1569 const unsigned short sidemap[2] = {3, 1};
1571 boundary_info.add_side(added_elem, sidemap[s], ids_to_copy);
1573 for (
const auto & id_to_copy : ids_to_copy)
1574 boundary_info.add_side(added_elem,
1583 if (current_layer == 0)
1585 const unsigned short top_id =
1586 added_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1590 "We should have retrieved a proper boundary ID");
1591 boundary_info.add_side(added_elem, is_flipped ?
top_id : 0, user_bottom_boundary_id);
1594 boundary_info.add_side(added_elem, is_flipped ?
top_id : 0, next_side_id);
1597 if (current_layer == total_num_layers - 1)
1602 const unsigned short top_id =
1603 added_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1608 "We should have retrieved a proper boundary ID");
1609 boundary_info.add_side(added_elem, is_flipped ? 0 :
top_id, user_top_boundary_id);
1612 boundary_info.add_side(
1613 added_elem, is_flipped ? 0 :
top_id, cast_int<boundary_id_type>(next_side_id + 1));
1621 if (has_polygons && !input->is_serial())
1622 mooseError(
"Distributed meshes are not supported when extruding polygons at this time.");
1624#ifdef LIBMESH_ENABLE_UNIQUE_ID
1627 unsigned int total_new_node_layers = total_num_layers * order;
1628 unsigned int new_unique_ids = orig_unique_ids + (total_new_node_layers - 1) * orig_elem +
1629 total_new_node_layers * orig_nodes;
1631 if (has_poly_midnodes)
1632 new_unique_ids += orig_elem;
1633 mesh->set_next_unique_id(new_unique_ids);
1637 if (!input_subdomain_map.empty())
1638 mesh->set_subdomain_name_map().insert(input_subdomain_map.begin(), input_subdomain_map.end());
1639 if (!input_sideset_map.empty())
1640 mesh->get_boundary_info().set_sideset_name_map().insert(input_sideset_map.begin(),
1641 input_sideset_map.end());
1642 if (!input_nodeset_map.empty())
1643 mesh->get_boundary_info().set_nodeset_name_map().insert(input_nodeset_map.begin(),
1644 input_nodeset_map.end());
1647 boundary_info.sideset_name(new_boundary_ids.front()) = new_boundary_names.front();
1649 boundary_info.sideset_name(new_boundary_ids.back()) = new_boundary_names.back();
1651 mesh->unset_is_prepared();
1654 if (extruding_quad_eights)
1655 mesh->prepare_for_use();