216 if (
_input->mesh_dimension() > 2)
217 paramError(
"input",
"This mesh generator only works for 1D and 2D input meshes.");
230 " of 'elem_integer_names_to_swap' is not a valid extra element integer of the "
234 const unsigned int num_extra_elem_integers =
_input->n_elem_integers();
235 std::vector<std::string> id_names;
237 for (
const auto i :
make_range(num_extra_elem_integers))
239 id_names.push_back(
_input->get_elem_integer_name(i));
245 const auto & input_subdomain_map =
_input->get_subdomain_name_map();
246 const auto & input_sideset_map =
_input->get_boundary_info().get_sideset_name_map();
247 const auto & input_nodeset_map =
_input->get_boundary_info().get_nodeset_name_map();
249 std::unique_ptr<MeshBase> input = std::move(
_input);
253 if (!input->is_serial())
257 if (!input->preparation().has_cached_elem_data)
258 input->cache_elem_data();
261 std::set<subdomain_id_type>
blocks;
262 input->subdomain_ids(
blocks,
true);
264 for (
const auto & [bid, tbid] : swap_map)
267 if (
blocks.count(bid) == 0)
269 "Source subdomain " + std::to_string(bid) +
" was not found in the mesh");
272 std::set<subdomain_id_type> subdomain_ids_set;
273 input->subdomain_ids(subdomain_ids_set);
276 std::max((
int)max_subdomain_id, 1) + 1;
278 std::max((
int)max_subdomain_id, 1) * 2 + 1;
279 const subdomain_id_type quad_to_prism_subdomain_id_shift = std::max((
int)max_subdomain_id, 1) + 1;
281 std::max((
int)max_subdomain_id, 1) * 2 + 1;
283 std::max((
int)max_subdomain_id, 1) * 3 + 1;
284 const subdomain_id_type edge_to_tri_subdomain_id_shift = std::max((
int)max_subdomain_id, 1) + 1;
290 if (MooseUtils::absoluteFuzzyEqual(axis_centroid_cross.
norm(), 0.0))
291 mooseError(
"The input mesh is either across the axis or overlapped with the axis!");
293 Real inner_product_1d(0.0);
294 bool inner_product_1d_initialized(
false);
296 std::vector<dof_id_type> node_ids_on_axis;
297 for (
const auto & node : input->node_ptr_range())
301 if (!MooseUtils::absoluteFuzzyEqual(axis_node_cross.
norm(), 0.0))
303 if (MooseUtils::absoluteFuzzyLessThan(axis_node_cross * axis_centroid_cross, 0.0))
304 mooseError(
"The input mesh is across the axis.");
305 else if (MooseUtils::absoluteFuzzyLessThan(axis_node_cross * axis_centroid_cross,
306 axis_centroid_cross.
norm() *
307 axis_node_cross.
norm()))
308 mooseError(
"The input mesh is not in the same plane with the rotation axis.");
311 node_ids_on_axis.push_back(node->id());
314 if (input->mesh_dimension() == 1)
317 if (inner_product_1d_initialized)
319 if (!MooseUtils::absoluteFuzzyEqual(temp_inner_product, inner_product_1d))
320 mooseError(
"The 1D input mesh is not perpendicular to the rotation axis.");
324 inner_product_1d_initialized =
true;
325 inner_product_1d = temp_inner_product;
332 if (!node_ids_on_axis.empty())
335 std::sort(node_ids_on_axis.begin(), node_ids_on_axis.end());
337 std::set<subdomain_id_type> converted_quad8_subdomain_ids;
338 for (
const auto & elem : input->element_ptr_range())
340 if (elem->type() ==
QUAD8)
342 std::vector<dof_id_type> elem_vertex_node_ids;
343 for (
unsigned int i = 0; i < 4; i++)
345 elem_vertex_node_ids.push_back(elem->node_id(i));
347 std::sort(elem_vertex_node_ids.begin(), elem_vertex_node_ids.end());
348 std::vector<dof_id_type> common_node_ids;
349 std::set_intersection(node_ids_on_axis.begin(),
350 node_ids_on_axis.end(),
351 elem_vertex_node_ids.begin(),
352 elem_vertex_node_ids.end(),
353 std::back_inserter(common_node_ids));
355 if (common_node_ids.size() == 1)
358 elem->subdomain_id() += quad_to_hi_pyramid_subdomain_id_shift;
359 converted_quad8_subdomain_ids.emplace(elem->subdomain_id());
364 input->all_second_order_range(
365 input->active_subdomain_set_elements_ptr_range(converted_quad8_subdomain_ids));
368 for (
auto elem : input->active_subdomain_set_elements_ptr_range(converted_quad8_subdomain_ids))
369 elem->subdomain_id() -= quad_to_hi_pyramid_subdomain_id_shift;
376#ifdef LIBMESH_ENABLE_UNIQUE_ID
379 unique_id_type orig_unique_ids = input->parallel_max_unique_id() + orig_elem;
385 unsigned int order = 1;
388 const BoundaryInfo & input_boundary_info = input->get_boundary_info();
390 const unsigned int total_num_azimuthal_intervals =
395 const dof_id_type elem_id_shift = total_num_azimuthal_intervals * orig_elem;
399 std::vector<ElemType> types;
401 for (
const auto elem_type : types)
402 if (higher_orders.count(elem_type))
407 std::vector<Real> azi_array;
410 const Real section_start_angle =
411 azi_array.empty() ? 0.0 : (azi_array.back() +
_unit_angles.back());
422 for (
const auto & node : input->node_ptr_range())
431 std::vector<boundary_id_type> ids_to_copy;
434 Point current_distance;
439 [](
auto &
c) { return c * (-1.0) * M_PI / 180.0; });
444 [](
auto &
c) { return c * M_PI / 180.0; });
445 std::vector<dof_id_type> nodes_on_axis;
447 for (
const auto & node : input->node_ptr_range())
452 const bool isOnAxis = MooseUtils::absoluteFuzzyEqual(radius_and_center.first, 0.0);
455 nodes_on_axis.push_back(node->id());
458 unsigned int current_node_layer = 0;
463 for (
unsigned int e = 0; e < num_rotations; e++)
469 const auto base_angle =
473 for (
unsigned int k = 0;
474 k < order * num_layers + (e == 0 ? 1 : 0) -
478 bool is_node_created(
false);
482 if (e == 0 && k == 0)
483 current_distance.
zero();
486 auto layer_index = (k - (e == 0 ? 1 : 0)) + 1;
489 const Point vector_xy =
490 Point(-2.0 * radius_and_center.first *
491 std::sin((base_angle + angle * (
Real)layer_index) / 2.0) *
492 std::sin((base_angle + angle * (
Real)layer_index) / 2.0),
493 2.0 * radius_and_center.first *
494 std::sin((base_angle + angle * (
Real)layer_index) / 2.0) *
495 std::cos((base_angle + angle * (
Real)layer_index) / 2.0),
497 current_distance =
Point(rotation_vectors[0] * vector_xy,
498 rotation_vectors[1] * vector_xy,
499 rotation_vectors[2] * vector_xy);
502 is_node_created =
true;
504 else if (e == 0 && k == 0)
507 current_distance.
zero();
508 is_node_created =
true;
514 node->id() + (current_node_layer * orig_nodes),
515 node->processor_id());
516#ifdef LIBMESH_ENABLE_UNIQUE_ID
521 (current_node_layer == 0)
523 : (orig_unique_ids + (current_node_layer - 1) * (orig_nodes + orig_elem * 2) +
530 boundary_info.
add_node(new_node, ids_to_copy);
532 for (
const auto & id_to_copy : ids_to_copy)
539 current_node_layer++;
544 for (
const auto & elem : input->element_ptr_range())
546 const ElemType etype = elem->type();
549 mooseAssert(!elem->parent(),
"RevolveGenerator only works on coarse meshes.");
551 unsigned int current_layer = 0;
555 for (
unsigned int e = 0; e < num_rotations; e++)
559 for (
unsigned int k = 0; k < num_layers; ++k)
561 std::unique_ptr<Elem> new_elem;
562 std::unique_ptr<Elem> new_elem_1;
563 bool is_flipped(
false);
566 bool is_flipped_additional(
false);
568 std::vector<std::pair<dof_id_type, dof_id_type>> side_pairs;
579 if (nodes_cates.first.empty())
587 total_num_azimuthal_intervals,
600 total_num_azimuthal_intervals,
615 if (nodes_cates.first.empty())
623 total_num_azimuthal_intervals,
636 total_num_azimuthal_intervals,
653 if (nodes_cates.first.empty())
661 total_num_azimuthal_intervals,
665 else if (nodes_cates.first.size() == 1)
674 total_num_azimuthal_intervals,
679 else if (nodes_cates.first.size() == 2)
688 total_num_azimuthal_intervals,
694 mooseError(
"A degenerate TRI3 elements overlapped with the rotation axis cannot be "
710 if (nodes_cates.first.empty())
718 total_num_azimuthal_intervals,
722 else if (nodes_cates.first.size() == 1)
731 total_num_azimuthal_intervals,
736 else if (nodes_cates.first.size() == 3)
745 total_num_azimuthal_intervals,
752 "You either have a degenerate TRI6 element, or the mid-point of the "
753 "on-axis edge is not colinear with the two vertices, which is not supported.");
767 if (nodes_cates.first.empty())
775 total_num_azimuthal_intervals,
779 else if (nodes_cates.first.size() == 1)
788 total_num_azimuthal_intervals,
793 else if (nodes_cates.first.size() == 3)
802 total_num_azimuthal_intervals,
808 mooseError(
"You either have a degenerate TRI6 element, or the mid-point of the "
809 "on-axis edge of the TRI6 element is not colinear with the two vertices, "
810 "which is not supported.");
823 if (nodes_cates.first.empty())
831 total_num_azimuthal_intervals,
835 else if (nodes_cates.first.size() == 1)
846 total_num_azimuthal_intervals,
850 is_flipped_additional);
852 else if (nodes_cates.first.size() == 2)
861 total_num_azimuthal_intervals,
868 mooseError(
"Degenerate QUAD4 element with 3 or more aligned nodes cannot be "
869 "azimuthally revolved");
885 if (nodes_cates.first.empty())
893 total_num_azimuthal_intervals,
897 else if (nodes_cates.first.size() == 3)
906 total_num_azimuthal_intervals,
912 mooseError(
"You either have a degenerate QUAD8 element, or the mid-point of the "
913 "on-axis edge of the QUAD8 element is not colinear with the two vertices, "
914 "which is not supported.");
930 if (nodes_cates.first.empty())
938 total_num_azimuthal_intervals,
942 else if (nodes_cates.first.size() == 1)
953 total_num_azimuthal_intervals,
957 is_flipped_additional);
959 else if (nodes_cates.first.size() == 3)
968 total_num_azimuthal_intervals,
974 mooseError(
"You either have a degenerate QUAD9 element, or the mid-point of the "
975 "on-axis edge of the QUAD9 element is not colinear with the two vertices, "
976 "which is not supported.");
980 mooseError(
"The input mesh contains unsupported element type(s).");
982 new_elem->set_id(elem->id() + (current_layer * orig_elem));
983 new_elem->processor_id() = elem->processor_id();
986 new_elem_1->set_id(elem->id() + (current_layer * orig_elem) + elem_id_shift);
987 new_elem_1->processor_id() = elem->processor_id();
990#ifdef LIBMESH_ENABLE_UNIQUE_ID
997 : (orig_unique_ids + (current_layer - 1) * (orig_nodes + orig_elem * 2) +
998 orig_nodes + elem->id());
1000 new_elem->set_unique_id(uid);
1006 (current_layer == 0)
1007 ? (elem->id() + orig_unique_ids - orig_elem)
1008 : (orig_unique_ids + (current_layer - 1) * (orig_nodes + orig_elem * 2) +
1009 orig_nodes + orig_elem + elem->id());
1011 new_elem_1->set_unique_id(uid_1);
1019 switch (new_elem->type())
1022 new_elem->subdomain_id() = elem->subdomain_id();
1025 new_elem->subdomain_id() = edge_to_tri_subdomain_id_shift + elem->subdomain_id();
1029 "impossible element type generated by revolving an EDGE2 element");
1033 switch (new_elem->type())
1036 new_elem->subdomain_id() = elem->subdomain_id();
1039 new_elem->subdomain_id() = edge_to_tri_subdomain_id_shift + elem->subdomain_id();
1043 "impossible element type generated by revolving an EDGE3 element");
1047 switch (new_elem->type())
1050 new_elem->subdomain_id() = elem->subdomain_id();
1053 new_elem->subdomain_id() = tri_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1056 new_elem->subdomain_id() = tri_to_tet_subdomain_id_shift + elem->subdomain_id();
1059 mooseAssert(
false,
"impossible element type generated by revolving a TRI3 element");
1063 switch (new_elem->type())
1066 new_elem->subdomain_id() = elem->subdomain_id();
1069 new_elem->subdomain_id() = tri_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1072 new_elem->subdomain_id() = tri_to_tet_subdomain_id_shift + elem->subdomain_id();
1075 mooseAssert(
false,
"impossible element type generated by revolving a TRI6 element");
1079 switch (new_elem->type())
1082 new_elem->subdomain_id() = elem->subdomain_id();
1085 new_elem->subdomain_id() = tri_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1088 new_elem->subdomain_id() = tri_to_tet_subdomain_id_shift + elem->subdomain_id();
1091 mooseAssert(
false,
"impossible element type generated by revolving a TRI7 element");
1095 switch (new_elem->type())
1098 new_elem->subdomain_id() = elem->subdomain_id();
1101 new_elem->subdomain_id() = quad_to_prism_subdomain_id_shift + elem->subdomain_id();
1104 new_elem->subdomain_id() =
1105 quad_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1106 new_elem_1->subdomain_id() =
1107 quad_to_prism_subdomain_id_shift + elem->subdomain_id();
1111 "impossible element type generated by revolving a QUAD4 element");
1115 switch (new_elem->type())
1118 new_elem->subdomain_id() = elem->subdomain_id();
1121 new_elem->subdomain_id() = quad_to_prism_subdomain_id_shift + elem->subdomain_id();
1125 "impossible element type generated by revolving a QUAD8 element");
1129 switch (new_elem->type())
1132 new_elem->subdomain_id() = elem->subdomain_id();
1135 new_elem->subdomain_id() =
1136 quad_to_hi_pyramid_subdomain_id_shift + elem->subdomain_id();
1139 new_elem->subdomain_id() =
1140 quad_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1141 new_elem_1->subdomain_id() =
1142 quad_to_hi_pyramid_subdomain_id_shift + elem->subdomain_id();
1146 "impossible element type generated by revolving a QUAD9 element");
1151 "The input mesh contains unsupported element type(s), which should have "
1152 "been checked in prior steps in this code.");
1159 auto new_id_it = revolving_swap_pairs.find(elem->subdomain_id());
1161 if (new_id_it != revolving_swap_pairs.end())
1163 new_elem->subdomain_id() =
1164 new_elem->subdomain_id() - elem->subdomain_id() + new_id_it->second;
1166 new_elem_1->subdomain_id() =
1167 new_elem_1->subdomain_id() - elem->subdomain_id() + new_id_it->second;
1172 Elem * added_elem_1 = NULL;
1178 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
1189 auto & elevation_extra_swap_pairs =
1192 auto new_extra_id_it = elevation_extra_swap_pairs.find(
1195 if (new_extra_id_it != elevation_extra_swap_pairs.end())
1198 new_extra_id_it->second);
1201 new_extra_id_it->second);
1207 for (
auto s : elem->side_index_range())
1209 input_boundary_info.
boundary_ids(elem, s, ids_to_copy);
1210 std::vector<boundary_id_type> ids_to_copy_swapped;
1212 ids_to_copy_swapped = ids_to_copy;
1214 for (
const auto & id_to_copy : ids_to_copy)
1222 switch (added_elem->
type())
1226 added_elem, cast_int<unsigned short>(s == 0 ? 3 : 1), ids_to_copy_swapped);
1229 if (s != axis_node_case)
1231 added_elem, cast_int<unsigned short>(s), ids_to_copy_swapped);
1235 "impossible element type generated by revolving an EDGE2 element");
1239 switch (added_elem->
type())
1243 added_elem, cast_int<unsigned short>(s == 0 ? 3 : 1), ids_to_copy_swapped);
1246 if (s != axis_node_case)
1248 added_elem, cast_int<unsigned short>(s), ids_to_copy_swapped);
1252 "impossible element type generated by revolving an EDGE3 element");
1256 switch (added_elem->
type())
1260 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1263 if ((s + 3 - axis_node_case) % 3 == 0)
1265 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1266 else if ((s + 3 - axis_node_case) % 3 == 1)
1268 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1271 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1274 if ((s + 3 - axis_node_case) % 3 == 0)
1276 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1277 else if ((s + 3 - axis_node_case) % 3 == 2)
1279 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1283 "impossible element type generated by revolving a TRI3 element");
1287 switch (added_elem->
type())
1291 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1294 if ((s + 3 - axis_node_case) % 3 == 0)
1296 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1297 else if ((s + 3 - axis_node_case) % 3 == 1)
1299 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1302 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1305 if ((s + 3 - axis_node_case) % 3 == 0)
1307 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1308 else if ((s + 3 - axis_node_case) % 3 == 2)
1310 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1314 "impossible element type generated by revolving a TRI6 element");
1318 switch (added_elem->
type())
1322 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1325 if ((s + 3 - axis_node_case) % 3 == 0)
1327 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1328 else if ((s + 3 - axis_node_case) % 3 == 1)
1330 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1333 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1336 if ((s + 3 - axis_node_case) % 3 == 0)
1338 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1339 else if ((s + 3 - axis_node_case) % 3 == 2)
1341 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1345 "impossible element type generated by revolving a TRI7 element");
1349 switch (added_elem->
type())
1353 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1356 if ((s + 4 - axis_node_case) % 4 == 1)
1358 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1359 else if ((s + 4 - axis_node_case) % 4 == 2)
1361 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1362 else if ((s + 4 - axis_node_case) % 4 == 3)
1364 added_elem, cast_int<unsigned short>(0), ids_to_copy_swapped);
1367 if ((s + 4 - axis_node_case) % 4 == 3)
1369 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1370 else if ((s + 4 - axis_node_case) % 4 == 0)
1372 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1373 else if ((s + 4 - axis_node_case) % 4 == 1)
1375 added_elem_1, cast_int<unsigned short>(3), ids_to_copy_swapped);
1378 added_elem_1, cast_int<unsigned short>(2), ids_to_copy_swapped);
1382 "impossible element type generated by revolving a QUAD4 element");
1386 switch (added_elem->
type())
1390 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1393 if ((s + 4 - axis_node_case) % 4 == 1)
1395 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1396 else if ((s + 4 - axis_node_case) % 4 == 2)
1398 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1399 else if ((s + 4 - axis_node_case) % 4 == 3)
1401 added_elem, cast_int<unsigned short>(0), ids_to_copy_swapped);
1405 "impossible element type generated by revolving a QUAD8 element");
1409 switch (added_elem->
type())
1413 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1416 if ((s + 4 - axis_node_case) % 4 == 1)
1418 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1419 else if ((s + 4 - axis_node_case) % 4 == 2)
1421 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1422 else if ((s + 4 - axis_node_case) % 4 == 3)
1424 added_elem, cast_int<unsigned short>(0), ids_to_copy_swapped);
1427 if ((s + 4 - axis_node_case) % 4 == 3)
1429 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1430 else if ((s + 4 - axis_node_case) % 4 == 0)
1432 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1433 else if ((s + 4 - axis_node_case) % 4 == 1)
1435 added_elem_1, cast_int<unsigned short>(3), ids_to_copy_swapped);
1438 added_elem_1, cast_int<unsigned short>(2), ids_to_copy_swapped);
1442 "impossible element type generated by revolving a QUAD9 element");
1447 "The input mesh contains unsupported element type(s), which should have "
1448 "been checked in prior steps in this code.");
1455 added_elem, is_flipped ? side_pairs[0].second : side_pairs[0].first,
_start_boundary);
1456 if (side_pairs.size() > 1)
1457 boundary_info.
add_side(added_elem_1,
1458 is_flipped_additional ? side_pairs[1].second
1459 : side_pairs[1].first,
1466 added_elem, is_flipped ? side_pairs[0].first : side_pairs[0].second,
_end_boundary);
1467 if (side_pairs.size() > 1)
1468 boundary_info.
add_side(added_elem_1,
1469 is_flipped_additional ? side_pairs[1].first
1470 : side_pairs[1].second,
1478#ifdef LIBMESH_ENABLE_UNIQUE_ID
1481 unsigned int total_new_node_layers = total_num_azimuthal_intervals * order;
1482 unsigned int new_unique_ids = orig_unique_ids + (total_new_node_layers - 1) * orig_elem * 2 +
1483 total_new_node_layers * orig_nodes;
1488 if (!input_subdomain_map.empty())
1490 if (!input_sideset_map.empty())
1492 input_sideset_map.end());
1493 if (!input_nodeset_map.empty())
1495 input_nodeset_map.end());