420 mesh->set_mesh_dimension(
_input->mesh_dimension() + 1);
431 " of 'elem_integer_names_to_swap' in is not a valid extra element integer of the "
435 const unsigned int num_extra_elem_integers =
_input->n_elem_integers();
436 std::vector<std::string> id_names;
438 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
440 id_names.push_back(
_input->get_elem_integer_name(i));
441 if (!
mesh->has_elem_integer(id_names[i]))
442 mesh->add_elem_integer(id_names[i]);
446 if (!
_input->preparation().has_cached_elem_data)
447 _input->cache_elem_data();
448 const auto & input_subdomain_map =
_input->get_subdomain_name_map();
449 const auto & input_sideset_map =
_input->get_boundary_info().get_sideset_name_map();
450 const auto & input_nodeset_map =
_input->get_boundary_info().get_nodeset_name_map();
454 for (
const auto i : index_range(swap))
456 paramError(
"subdomain_swaps",
"The block '", swap[i],
"' was not found within the mesh");
460 for (
const auto i : index_range(swap))
462 paramError(
"boundary_swaps",
"The boundary '", swap[i],
"' was not found within the mesh");
466 for (
const auto bid : layer_vec)
469 "upward_boundary_source_blocks",
"The block '", bid,
"' was not found within the mesh");
471 for (
const auto bid : layer_vec)
476 "' was not found within the mesh");
479 std::unique_ptr<MeshBase> input = std::move(
_input);
480 std::unique_ptr<MeshBase> extrusion_curve;
485 std::unique_ptr<libMesh::MeshSerializer> serializer;
487 serializer = std::make_unique<libMesh::MeshSerializer>(*extrusion_curve);
491 input->find_neighbors();
495 if (!input->is_serial())
497 input->delete_remote_elements();
499 mesh->delete_remote_elements();
502 if (input->n_nodes() != input->max_node_id())
503 input->renumber_nodes_and_elements();
505 if (input->n_nodes() != input->max_node_id())
507 "You must allow renumbering, because the extruded mesh should be contiguously numbered. "
508 "Alternatively, you can use a separate mesh generator (MeshRepairGenerator with the "
509 "renumber_contiguously parameter for example) to renumber the nodes contiguously.");
511 unsigned int total_num_layers;
512 unsigned int total_num_elevations;
516 total_num_elevations =
_heights.size();
520 total_num_layers = extrusion_curve->n_elem();
521 total_num_elevations = 1;
524 dof_id_type orig_elem = input->n_elem();
525 dof_id_type orig_nodes = input->n_nodes();
527#ifdef LIBMESH_ENABLE_UNIQUE_ID
528 unique_id_type orig_unique_ids = input->parallel_max_unique_id();
529 bool has_poly_midnodes =
false;
532 bool has_polygons =
false;
533 unsigned int order = 1;
535 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
536 const BoundaryInfo & input_boundary_info = input->get_boundary_info();
539 std::vector<BoundaryName> new_boundary_names;
546 std::vector<boundary_id_type> new_boundary_ids =
550 for (
const auto i : index_range(new_boundary_names))
551 for (
const auto j : make_range(i))
552 if (new_boundary_names[i] == new_boundary_names[j])
553 new_boundary_ids[i] = new_boundary_ids[j];
554 const auto user_bottom_boundary_id =
559 const auto user_side_boundary_id =
563 mesh->reserve_elem(total_num_layers * orig_elem);
566 std::set<ElemType> higher_orders = {EDGE3, EDGE4, TRI6, TRI7, QUAD8, QUAD9};
567 bool extruding_quad_eights =
false;
568 std::vector<ElemType> types;
570 for (
const auto elem_type : types)
572 if (higher_orders.count(elem_type))
574 if (elem_type == QUAD8)
575 extruding_quad_eights =
true;
577 mesh->comm().max(order);
578 mesh->comm().max(extruding_quad_eights);
581 mesh->reserve_nodes((order * total_num_layers + 1) * orig_nodes);
584 std::vector<boundary_id_type> ids_to_copy;
587 Real start_radial_extent = 0;
588 Point reference_point;
590 reference_point = *(extrusion_curve->node_ptr(0));
591 else if (!MooseUtils::absoluteFuzzyEqual(
_twist_pitch, 0.))
593 reference_point = Point(0, 0, 0);
601 RealVectorValue reference_direction;
603 reference_direction =
607 (*(extrusion_curve->node_ptr(1)) - *(extrusion_curve->node_ptr(0))).unit());
612 start_radial_extent =
617 Real total_extrusion_distance_at_axis;
620 if (!extrusion_curve->is_prepared())
621 extrusion_curve->prepare_for_use();
625 total_extrusion_distance_at_axis = std::accumulate(
_heights.begin(),
_heights.end(), 0);
628 for (
const auto & node : input->node_ptr_range())
630 unsigned int current_node_layer = 0;
631 Point orig_node_to_previous;
632 Point orig_node_to_current;
633 Real sum_step_sizes = 0.;
634 Real sum_step_sizes_at_axis = 0.;
636 Real start_node_radius = (*node - reference_point).norm();
639 for (
const auto e : make_range(total_num_elevations))
642 Real height = std::numeric_limits<Real>::max(), bias = std::numeric_limits<Real>::max();
645 num_layers = extrusion_curve->n_elem();
655 unsigned int num_heights_at_elevation = order * num_layers + (e == 0 ? 1 : 0);
660 for (
const auto k : make_range(num_heights_at_elevation))
664 if (e == 0 && k == 0)
665 orig_node_to_current.
zero();
673 Real step_size_at_axis = 0;
677 const Node * P_current = extrusion_curve->node_ptr(k);
679 const Node * P_prev = extrusion_curve->node_ptr(k - 1);
682 const auto old_node = orig_node_to_previous + *node;
683 RealVectorValue b_vec = old_node - *P_prev;
684 Real node_distance_to_curve = b_vec.norm();
690 RealVectorValue intersecting_plane_normal_vec;
695 const auto P_next = extrusion_curve->node_ptr(k + 1);
696 intersecting_plane_normal_vec =
699 else if (k < order * num_layers - 1)
701 const auto P_next = extrusion_curve->node_ptr(k + 1);
703 intersecting_plane_normal_vec = *P_next - *P_prev;
709 : RealVectorValue(*P_current - *P_prev);
711 intersecting_plane_normal_vec /= intersecting_plane_normal_vec.norm();
713 Point new_node_point;
716 if (MooseUtils::absoluteFuzzyEqual(
717 prev_intersecting_plane_normal_vec.cross(intersecting_plane_normal_vec)
720 new_node_point = old_node + *P_current - *P_prev;
728 auto axis = prev_intersecting_plane_normal_vec.cross(intersecting_plane_normal_vec);
729 const auto sin_th = axis.norm();
731 Real cos_th = prev_intersecting_plane_normal_vec * intersecting_plane_normal_vec;
733 const auto new_v = cos_th * b_vec + axis.cross(b_vec) * sin_th +
734 axis * (axis * b_vec) * (1. - cos_th);
736 mooseAssert(MooseUtils::absoluteFuzzyEqual(new_v.norm(), b_vec.norm()),
737 "Radial extent be conserved");
738 new_node_point = *P_current + new_v;
741 orig_node_to_current = new_node_point - *node;
743 step_size = (orig_node_to_current - orig_node_to_previous).norm();
744 step_size_at_axis = (*P_current - *P_prev).norm();
745 prev_intersecting_plane_normal_vec = intersecting_plane_normal_vec;
753 "Norm of direction vector is not 1!");
758 step_size = ((*P_current - (orig_node_to_previous + *node)) *
_direction);
759 step_size_at_axis = step_size;
760 orig_node_to_current = orig_node_to_previous +
_direction * step_size;
768 auto layer_index = (k - (e == 0 ? 1 : 0)) / order + 1;
769 step_size = MooseUtils::absoluteFuzzyEqual(bias, 1.0)
770 ? height / (Real)num_layers / (Real)order
771 : height *
std::pow(bias, (Real)(layer_index - 1)) * (1.0 - bias) /
772 (1.0 -
std::pow(bias, (Real)(num_layers))) / (Real)order;
773 step_size_at_axis = step_size;
774 orig_node_to_current =
775 orig_node_to_previous +
780 sum_step_sizes += step_size;
781 sum_step_sizes_at_axis += step_size_at_axis;
789 (sum_step_sizes_at_axis - step_size_at_axis) / total_extrusion_distance_at_axis;
790 Real t = sum_step_sizes_at_axis / total_extrusion_distance_at_axis;
793 RealVectorValue node_to_extrusion_axis;
795 node_to_extrusion_axis =
796 *node + orig_node_to_current - *(extrusion_curve->node_ptr(k));
798 else if (!MooseUtils::absoluteFuzzyEqual(
_twist_pitch, 0.))
799 node_to_extrusion_axis =
800 *node + orig_node_to_current - (reference_point +
_direction * sum_step_sizes);
804 node_to_extrusion_axis = *node - reference_point;
807 const auto radius_scaling = start_node_radius / start_radial_extent;
813 orig_node_to_current += (start_radial_extent * (radial_ratio_m1 - radial_ratio) +
815 radius_scaling * node_to_extrusion_axis.unit();
824 if (!MooseUtils::absoluteFuzzyEqual(twist1.norm(), .0))
825 twist1 /= twist1.norm();
842 Point extrusion_axis_at_elevation;
843 Point prev_extrusion_axis_at_elevation;
846 extrusion_axis_at_elevation = *extrusion_curve->node_ptr(k);
847 prev_extrusion_axis_at_elevation = *extrusion_curve->node_ptr(k - 1);
852 extrusion_axis_at_elevation = reference_point +
_direction * sum_step_sizes;
853 prev_extrusion_axis_at_elevation =
854 reference_point +
_direction * (sum_step_sizes - step_size);
858 twist *= (*node + orig_node_to_current - extrusion_axis_at_elevation).norm();
861 if (!MooseUtils::absoluteFuzzyEqual(twist1.norm(), .0))
862 orig_node_to_current += twist;
867 Node * new_node =
mesh->add_point(*node + orig_node_to_current,
868 node->id() + (current_node_layer * orig_nodes),
869 node->processor_id());
871#ifdef LIBMESH_ENABLE_UNIQUE_ID
875 const unique_id_type uid = (current_node_layer == 0)
878 (current_node_layer - 1) * (orig_elem + orig_nodes) +
880 new_node->set_unique_id(uid);
884 input_boundary_info.boundary_ids(node, ids_to_copy);
886 boundary_info.add_node(new_node, ids_to_copy);
888 for (
const auto & id_to_copy : ids_to_copy)
890 boundary_info.add_node(new_node,
896 orig_node_to_previous = orig_node_to_current;
897 current_node_layer++;
902 const auto & side_ids = input_boundary_info.get_side_boundary_ids();
904 boundary_id_type next_side_id =
905 side_ids.empty() ? 0 : cast_int<boundary_id_type>(*side_ids.rbegin() + 1);
910 input->comm().max(next_side_id);
915 while (user_side_boundary_id == next_side_id || user_side_boundary_id == next_side_id + 1)
919 std::map<std::array<unsigned int, 3>, std::shared_ptr<libMesh::Polygon>> poly_extruded_sides;
922 for (
const auto & elem : input->element_ptr_range())
924 const ElemType etype = elem->type();
927 libmesh_assert(!elem->parent());
929 unsigned int current_layer = 0;
931 for (
unsigned int e = 0; e != total_num_elevations; e++)
935 for (
unsigned int k = 0; k != num_layers; ++k)
937 std::unique_ptr<Elem> new_elem;
938 bool is_flipped(
false);
943 new_elem = std::make_unique<Quad4>();
945 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
947 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
949 2,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
951 3,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
953 if (elem->neighbor_ptr(0) == remote_elem)
954 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
955 if (elem->neighbor_ptr(1) == remote_elem)
956 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
962 new_elem = std::make_unique<Quad9>();
964 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
966 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
969 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
972 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
974 4,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
977 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
980 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
983 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
986 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
988 if (elem->neighbor_ptr(0) == remote_elem)
989 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
990 if (elem->neighbor_ptr(1) == remote_elem)
991 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
997 new_elem = std::make_unique<Prism6>();
999 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
1001 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
1003 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * orig_nodes)));
1005 3,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
1007 4,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
1009 5,
mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer + 1) * orig_nodes)));
1011 if (elem->neighbor_ptr(0) == remote_elem)
1012 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1013 if (elem->neighbor_ptr(1) == remote_elem)
1014 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1015 if (elem->neighbor_ptr(2) == remote_elem)
1016 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1018 if (new_elem->volume() < 0.0)
1030 new_elem = std::make_unique<Prism18>();
1032 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1034 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1036 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1039 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1042 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1045 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1047 6,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1049 7,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1051 8,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1054 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1057 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1060 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1063 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1066 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1069 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1072 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1075 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
1078 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
1080 if (elem->neighbor_ptr(0) == remote_elem)
1081 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1082 if (elem->neighbor_ptr(1) == remote_elem)
1083 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1084 if (elem->neighbor_ptr(2) == remote_elem)
1085 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1087 if (new_elem->volume() < 0.0)
1102 new_elem = std::make_unique<Prism21>();
1104 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1106 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1108 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1111 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1114 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1117 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1119 6,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1121 7,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1123 8,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1126 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1129 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1132 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1135 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1138 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1141 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1144 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1147 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
1150 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
1152 18,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
1155 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
1158 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 1) * orig_nodes)));
1160 if (elem->neighbor_ptr(0) == remote_elem)
1161 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1162 if (elem->neighbor_ptr(1) == remote_elem)
1163 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1164 if (elem->neighbor_ptr(2) == remote_elem)
1165 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1167 if (new_elem->volume() < 0.0)
1183 new_elem = std::make_unique<Hex8>();
1185 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
1187 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
1189 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * orig_nodes)));
1191 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (current_layer * orig_nodes)));
1193 4,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
1195 5,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
1197 6,
mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer + 1) * orig_nodes)));
1199 7,
mesh->node_ptr(elem->node_ptr(3)->id() + ((current_layer + 1) * orig_nodes)));
1201 if (elem->neighbor_ptr(0) == remote_elem)
1202 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1203 if (elem->neighbor_ptr(1) == remote_elem)
1204 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1205 if (elem->neighbor_ptr(2) == remote_elem)
1206 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1207 if (elem->neighbor_ptr(3) == remote_elem)
1208 new_elem->set_neighbor(4,
const_cast<RemoteElem *
>(remote_elem));
1210 if (new_elem->volume() < 0.0)
1223 new_elem = std::make_unique<Hex20>();
1225 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1227 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1229 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1231 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1234 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1237 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1240 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1243 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1245 8,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1247 9,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1249 10,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
1251 11,
mesh->node_ptr(elem->node_ptr(7)->id() + (2 * current_layer * orig_nodes)));
1254 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1257 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1260 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1263 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1266 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1269 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1272 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
1275 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 2) * orig_nodes)));
1277 if (elem->neighbor_ptr(0) == remote_elem)
1278 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1279 if (elem->neighbor_ptr(1) == remote_elem)
1280 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1281 if (elem->neighbor_ptr(2) == remote_elem)
1282 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1283 if (elem->neighbor_ptr(3) == remote_elem)
1284 new_elem->set_neighbor(4,
const_cast<RemoteElem *
>(remote_elem));
1286 if (new_elem->volume() < 0.0)
1303 new_elem = std::make_unique<Hex27>();
1305 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
1307 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
1309 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
1311 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
1314 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
1317 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
1320 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
1323 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
1325 8,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
1327 9,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
1329 10,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
1331 11,
mesh->node_ptr(elem->node_ptr(7)->id() + (2 * current_layer * orig_nodes)));
1334 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
1337 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
1340 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
1343 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
1346 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
1349 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
1352 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
1355 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 2) * orig_nodes)));
1357 20,
mesh->node_ptr(elem->node_ptr(8)->id() + (2 * current_layer * orig_nodes)));
1360 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
1363 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
1366 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 1) * orig_nodes)));
1369 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 1) * orig_nodes)));
1372 mesh->node_ptr(elem->node_ptr(8)->id() + ((2 * current_layer + 2) * orig_nodes)));
1375 mesh->node_ptr(elem->node_ptr(8)->id() + ((2 * current_layer + 1) * orig_nodes)));
1377 if (elem->neighbor_ptr(0) == remote_elem)
1378 new_elem->set_neighbor(1,
const_cast<RemoteElem *
>(remote_elem));
1379 if (elem->neighbor_ptr(1) == remote_elem)
1380 new_elem->set_neighbor(2,
const_cast<RemoteElem *
>(remote_elem));
1381 if (elem->neighbor_ptr(2) == remote_elem)
1382 new_elem->set_neighbor(3,
const_cast<RemoteElem *
>(remote_elem));
1383 if (elem->neighbor_ptr(3) == remote_elem)
1384 new_elem->set_neighbor(4,
const_cast<RemoteElem *
>(remote_elem));
1386 if (new_elem->volume() < 0.0)
1404 has_polygons =
true;
1405 const auto num_sides = elem->n_sides();
1406 std::vector<std::shared_ptr<libMesh::Polygon>>
sides;
1407 sides.reserve(2 + num_sides);
1409 mooseError(
"Too many nodes in polygons to extrude it. Max number of the prism "
1410 "polyhedral nodes after extrusion: " +
1413 auto new_ptr = std::make_shared<libMesh::C0Polygon>(num_sides);
1414 for (
const auto node_i : make_range(elem->n_nodes()))
1420 mesh->node_ptr(elem->node_ptr(node_i)->id() + (current_layer * orig_nodes)));
1422 sides.push_back(new_ptr);
1424 auto translated_side = std::make_shared<libMesh::C0Polygon>(num_sides);
1425 for (
const auto node_i : make_range(elem->n_nodes()))
1426 translated_side->set_node(node_i,
1427 mesh->node_ptr(elem->node_ptr(node_i)->id() +
1428 ((current_layer + 1) * orig_nodes)));
1429 sides.push_back(translated_side);
1432 for (
const auto side_i : make_range(num_sides))
1435 std::array<unsigned int, 3> side_key = {
1437 static_cast<unsigned int>(
1438 std::min(elem->node_ptr(side_i)->id(),
1439 elem->node_ptr((side_i + 1) % num_sides)->id())),
1440 static_cast<unsigned int>(
1441 std::max(elem->node_ptr(side_i)->id(),
1442 elem->node_ptr((side_i + 1) % num_sides)->id()))};
1443 if (poly_extruded_sides.count(side_key))
1445 sides.push_back(poly_extruded_sides[side_key]);
1450 auto vert_side = std::make_shared<libMesh::C0Polygon>(4);
1451 vert_side->set_node(
1452 0,
mesh->node_ptr(elem->node_ptr(side_i)->id() + (current_layer * orig_nodes)));
1453 vert_side->set_node(1,
1454 mesh->node_ptr(elem->node_ptr((side_i + 1) % num_sides)->id() +
1455 (current_layer * orig_nodes)));
1456 vert_side->set_node(2,
1457 mesh->node_ptr(elem->node_ptr((side_i + 1) % num_sides)->id() +
1458 ((current_layer + 1) * orig_nodes)));
1459 vert_side->set_node(3,
1460 mesh->node_ptr(elem->node_ptr(side_i)->id() +
1461 ((current_layer + 1) * orig_nodes)));
1462 sides.push_back(vert_side);
1464 poly_extruded_sides.insert(std::make_pair(side_key, vert_side));
1466 mooseAssert(
sides.size() == 2 + num_sides,
"Unexpected size of side vector");
1469 std::unique_ptr<libMesh::Node> mid_elem_node;
1470 new_elem = std::make_unique<libMesh::C0Polyhedron>(
sides, mid_elem_node);
1473#ifdef LIBMESH_ENABLE_UNIQUE_ID
1476 unsigned int total_new_node_layers = total_num_layers * order;
1477 unsigned int last_uid = orig_unique_ids + (total_new_node_layers - 1) * orig_elem +
1478 total_new_node_layers * orig_nodes + elem->unique_id();
1479 mid_elem_node->set_unique_id(last_uid);
1480 has_poly_midnodes =
true;
1482 mesh->add_node(std::move(mid_elem_node));
1491 new_elem->set_id(elem->id() + (current_layer * orig_elem));
1492 new_elem->processor_id() = elem->processor_id();
1494#ifdef LIBMESH_ENABLE_UNIQUE_ID
1498 const unique_id_type uid = (current_layer == 0)
1501 (current_layer - 1) * (orig_elem + orig_nodes) +
1502 orig_nodes + elem->id();
1504 new_elem->set_unique_id(uid);
1508 new_elem->subdomain_id() = elem->subdomain_id();
1511 if (k == num_layers - 1)
1514 const unsigned short top_id =
1515 new_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1521 boundary_info.add_side(
1527 const unsigned short top_id =
1528 new_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1532 boundary_info.add_side(
1541 auto new_id_it = elevation_swap_pairs.find(elem->subdomain_id());
1543 if (new_id_it != elevation_swap_pairs.end())
1544 new_elem->subdomain_id() = new_id_it->second;
1547 Elem * added_elem =
mesh->add_elem(std::move(new_elem));
1550 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
1551 added_elem->set_extra_integer(i, elem->get_extra_integer(i));
1559 auto new_extra_id_it = elevation_extra_swap_pairs.find(
1562 if (new_extra_id_it != elevation_extra_swap_pairs.end())
1564 new_extra_id_it->second);
1569 for (
auto s : elem->side_index_range())
1571 input_boundary_info.boundary_ids(elem, s, ids_to_copy);
1573 if (added_elem->dim() == 3)
1580 boundary_info.add_side(added_elem, cast_int<unsigned short>(s + 1), ids_to_copy);
1582 for (
const auto & id_to_copy : ids_to_copy)
1583 boundary_info.add_side(added_elem,
1584 cast_int<unsigned short>(s + 1),
1595 libmesh_assert_less(s, 2);
1596 const unsigned short sidemap[2] = {3, 1};
1598 boundary_info.add_side(added_elem, sidemap[s], ids_to_copy);
1600 for (
const auto & id_to_copy : ids_to_copy)
1601 boundary_info.add_side(added_elem,
1611 const unsigned short new_side =
1612 added_elem->dim() == 3 ? cast_int<unsigned short>(s + 1) : (s == 0 ? 3 : 1);
1613 boundary_info.add_side(added_elem, new_side, user_side_boundary_id);
1614 for (
const auto n : added_elem->nodes_on_side(new_side))
1615 boundary_info.add_node(added_elem->node_ptr(n), user_side_boundary_id);
1620 if (current_layer == 0)
1622 const unsigned short top_id =
1623 added_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1627 "We should have retrieved a proper boundary ID");
1628 boundary_info.add_side(added_elem, is_flipped ?
top_id : 0, user_bottom_boundary_id);
1631 boundary_info.add_side(added_elem, is_flipped ?
top_id : 0, next_side_id);
1634 if (current_layer == total_num_layers - 1)
1639 const unsigned short top_id =
1640 added_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1645 "We should have retrieved a proper boundary ID");
1646 boundary_info.add_side(added_elem, is_flipped ? 0 :
top_id, user_top_boundary_id);
1649 boundary_info.add_side(
1650 added_elem, is_flipped ? 0 :
top_id, cast_int<boundary_id_type>(next_side_id + 1));
1658 if (has_polygons && !input->is_serial())
1659 mooseError(
"Distributed meshes are not supported when extruding polygons at this time.");
1661#ifdef LIBMESH_ENABLE_UNIQUE_ID
1664 unsigned int total_new_node_layers = total_num_layers * order;
1665 unsigned int new_unique_ids = orig_unique_ids + (total_new_node_layers - 1) * orig_elem +
1666 total_new_node_layers * orig_nodes;
1668 if (has_poly_midnodes)
1669 new_unique_ids += orig_elem;
1670 mesh->set_next_unique_id(new_unique_ids);
1674 if (!input_subdomain_map.empty())
1675 mesh->set_subdomain_name_map().insert(input_subdomain_map.begin(), input_subdomain_map.end());
1676 if (!input_sideset_map.empty())
1677 mesh->get_boundary_info().set_sideset_name_map().insert(input_sideset_map.begin(),
1678 input_sideset_map.end());
1679 if (!input_nodeset_map.empty())
1680 mesh->get_boundary_info().set_nodeset_name_map().insert(input_nodeset_map.begin(),
1681 input_nodeset_map.end());
1683 for (
const auto i : index_range(new_boundary_names))
1684 boundary_info.sideset_name(new_boundary_ids[i]) = new_boundary_names[i];
1686 boundary_info.nodeset_name(user_side_boundary_id) =
_side_boundary;
1688 mesh->unset_is_prepared();
1691 if (extruding_quad_eights)
1692 mesh->prepare_for_use();