14 #include "libmesh/boundary_info.h" 15 #include "libmesh/function_base.h" 16 #include "libmesh/cell_prism6.h" 17 #include "libmesh/cell_prism18.h" 18 #include "libmesh/cell_prism21.h" 19 #include "libmesh/cell_hex8.h" 20 #include "libmesh/cell_hex20.h" 21 #include "libmesh/cell_hex27.h" 22 #include "libmesh/edge_edge2.h" 23 #include "libmesh/edge_edge3.h" 24 #include "libmesh/edge_edge4.h" 25 #include "libmesh/face_quad4.h" 26 #include "libmesh/face_quad8.h" 27 #include "libmesh/face_quad9.h" 28 #include "libmesh/face_tri3.h" 29 #include "libmesh/face_tri6.h" 30 #include "libmesh/face_tri7.h" 31 #include "libmesh/libmesh_logging.h" 32 #include "libmesh/mesh_communication.h" 33 #include "libmesh/mesh_modification.h" 34 #include "libmesh/mesh_tools.h" 35 #include "libmesh/parallel.h" 36 #include "libmesh/remote_elem.h" 37 #include "libmesh/string_to_enum.h" 38 #include "libmesh/unstructured_mesh.h" 39 #include "libmesh/point.h" 45 FancyExtruderGenerator,
57 "Extrudes a 1D mesh into 2D, or a 2D mesh into 3D, can have a variable height for each " 58 "elevation, variable number of layers within each elevation, variable growth factors of " 59 "axial element sizes within each elevation and remap subdomain_ids, boundary_ids and element " 60 "extra integers within each elevation as well as interface boundaries between neighboring " 63 params.
addRequiredParam<std::vector<Real>>(
"heights",
"The height of each elevation");
66 "biases",
"biases>0.0",
"The axial growth factor used for mesh biasing for each elevation.");
69 "num_layers",
"The number of layers for each elevation - must be num_elevations in length!");
71 params.
addParam<std::vector<std::vector<subdomain_id_type>>>(
74 "For each row, every two entries are interpreted as a pair of " 75 "'from' and 'to' to remap the subdomains for that elevation");
77 params.
addParam<std::vector<std::vector<boundary_id_type>>>(
80 "For each row, every two entries are interpreted as a pair of " 81 "'from' and 'to' to remap the boundaries for that elevation");
83 params.
addParam<std::vector<std::string>>(
84 "elem_integer_names_to_swap",
86 "Array of element extra integer names that need to be swapped during extrusion.");
88 params.
addParam<std::vector<std::vector<std::vector<dof_id_type>>>>(
89 "elem_integers_swaps",
91 "For each row, every two entries are interpreted as a pair of 'from' and 'to' to remap the " 92 "element extra integer for that elevation. If multiple element extra integers need to be " 93 "swapped, the enties are stacked based on the order provided in " 94 "'elem_integer_names_to_swap' to form the third dimension.");
98 "A vector that points in the direction to extrude (note, this will be " 99 "normalized internally - so don't worry about it here)");
103 "The boundary name to set on the top boundary. If omitted an ID will be generated.");
107 "The boundary name to set on the bottom boundary. If omitted an ID will be generated.");
109 params.
addParam<std::vector<std::vector<subdomain_id_type>>>(
110 "upward_boundary_source_blocks",
"Block ids used to generate upward interface boundaries.");
112 params.
addParam<std::vector<std::vector<boundary_id_type>>>(
"upward_boundary_ids",
113 "Upward interface boundary ids.");
115 params.
addParam<std::vector<std::vector<subdomain_id_type>>>(
116 "downward_boundary_source_blocks",
117 "Block ids used to generate downward interface boundaries.");
119 params.
addParam<std::vector<std::vector<boundary_id_type>>>(
"downward_boundary_ids",
120 "Downward interface boundary ids.");
122 "top_boundary bottom_boundary upward_boundary_source_blocks upward_boundary_ids " 123 "downward_boundary_source_blocks downward_boundary_ids",
124 "Boundary Assignment");
126 "subdomain_swaps boundary_swaps elem_integer_names_to_swap elem_integers_swaps",
"ID Swap");
129 "Pitch for helicoidal extrusion around an axis going through the origin " 130 "following the direction vector");
136 _input(getMesh(
"input")),
137 _heights(getParam<
std::vector<
Real>>(
"heights")),
138 _biases(isParamValid(
"biases") ? getParam<
std::vector<
Real>>(
"biases")
139 :
std::vector<
Real>(_heights.size(), 1.0)),
140 _num_layers(getParam<
std::vector<unsigned
int>>(
"num_layers")),
143 _elem_integer_names_to_swap(getParam<
std::vector<
std::string>>(
"elem_integer_names_to_swap")),
144 _elem_integers_swaps(
146 _direction(getParam<Point>(
"direction")),
147 _has_top_boundary(isParamValid(
"top_boundary")),
148 _top_boundary(isParamValid(
"top_boundary") ? getParam<BoundaryName>(
"top_boundary") :
"0"),
149 _has_bottom_boundary(isParamValid(
"bottom_boundary")),
150 _bottom_boundary(isParamValid(
"bottom_boundary") ? getParam<BoundaryName>(
"bottom_boundary")
152 _upward_boundary_source_blocks(
153 isParamValid(
"upward_boundary_source_blocks")
157 _upward_boundary_ids(
158 isParamValid(
"upward_boundary_ids")
162 _downward_boundary_source_blocks(isParamValid(
"downward_boundary_source_blocks")
164 "downward_boundary_source_blocks")
167 _downward_boundary_ids(
168 isParamValid(
"downward_boundary_ids")
172 _twist_pitch(getParam<
Real>(
"twist_pitch"))
175 paramError(
"direction",
"Must have some length!");
180 const auto num_elevations =
_heights.size();
183 paramError(
"heights",
"The length of 'heights' and 'num_layers' must be the same in ",
name());
187 "If specified, 'subdomain_swaps' (" + std::to_string(
_subdomain_swaps.size()) +
188 ") must be the same length as 'heights' (" + std::to_string(num_elevations) +
204 "If specified, 'boundary_swaps' (" + std::to_string(
_boundary_swaps.size()) +
205 ") must be the same length as 'heights' (" + std::to_string(num_elevations) +
222 "If specified, 'elem_integers_swaps' must have the same length as the length of " 223 "'elem_integer_names_to_swap'.");
226 if (unit_elem_integers_swaps.size() != num_elevations)
228 "If specified, each element of 'elem_integers_swaps' must have the same length as " 229 "the length of 'heights'.");
244 bool has_negative_entry =
false;
245 bool has_positive_entry =
false;
249 has_positive_entry =
true;
251 has_negative_entry =
true;
254 if (has_negative_entry && has_positive_entry)
255 paramError(
"heights",
"Cannot have both positive and negative heights!");
257 paramError(
"biases",
"Size of this parameter, if provided, must be the same as heights.");
262 "This parameter must have the same length (" +
264 ") as upward_boundary_source_blocks (" +
266 std::to_string(num_elevations) +
")");
270 "Every element of this parameter must have the same length as the corresponding " 271 "element of upward_boundary_source_blocks.");
276 "This parameter must have the same length (" +
278 ") as downward_boundary_source_blocks (" +
280 std::to_string(num_elevations) +
")");
284 "Every element of this parameter must have the same length as the corresponding " 285 "element of downward_boundary_source_blocks.");
288 std::unique_ptr<MeshBase>
296 mesh->set_mesh_dimension(
_input->mesh_dimension() + 1);
307 " of 'elem_integer_names_to_swap' in is not a valid extra element integer of the " 311 const unsigned int num_extra_elem_integers =
_input->n_elem_integers();
312 std::vector<std::string> id_names;
314 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
316 id_names.push_back(
_input->get_elem_integer_name(i));
317 if (!
mesh->has_elem_integer(id_names[i]))
318 mesh->add_elem_integer(id_names[i]);
322 const auto & input_subdomain_map =
_input->get_subdomain_name_map();
323 const auto & input_sideset_map =
_input->get_boundary_info().get_sideset_name_map();
324 const auto & input_nodeset_map =
_input->get_boundary_info().get_nodeset_name_map();
330 paramError(
"subdomain_swaps",
"The block '",
swap[i],
"' was not found within the mesh");
336 paramError(
"boundary_swaps",
"The boundary '",
swap[i],
"' was not found within the mesh");
340 for (
const auto bid : layer_vec)
343 "upward_boundary_source_blocks",
"The block '", bid,
"' was not found within the mesh");
345 for (
const auto bid : layer_vec)
350 "' was not found within the mesh");
352 std::unique_ptr<MeshBase> input = std::move(
_input);
356 if (!input->is_serial())
357 mesh->delete_remote_elements();
361 auto total_num_elevations =
_heights.size();
366 #ifdef LIBMESH_ENABLE_UNIQUE_ID 370 unsigned int order = 1;
372 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
373 const BoundaryInfo & input_boundary_info = input->get_boundary_info();
376 std::vector<BoundaryName> new_boundary_names;
381 std::vector<boundary_id_type> new_boundary_ids =
383 const auto user_bottom_boundary_id =
385 const auto user_top_boundary_id =
389 mesh->reserve_elem(total_num_layers * orig_elem);
393 bool extruding_quad_eights =
false;
394 std::vector<ElemType> types;
395 MeshTools::elem_types(*input, types);
396 for (
const auto elem_type : types)
398 if (higher_orders.count(elem_type))
400 if (elem_type ==
QUAD8)
401 extruding_quad_eights =
true;
403 mesh->comm().max(order);
404 mesh->comm().max(extruding_quad_eights);
407 mesh->reserve_nodes((order * total_num_layers + 1) * orig_nodes);
410 std::vector<boundary_id_type> ids_to_copy;
413 Point current_distance;
416 for (
const auto & node : input->node_ptr_range())
418 unsigned int current_node_layer = 0;
423 for (
unsigned int e = 0; e < total_num_elevations; e++)
432 for (
unsigned int k = 0; k < order * num_layers + (e == 0 ? 1 : 0); ++k)
435 if (e == 0 && k == 0)
436 current_distance.zero();
441 auto layer_index = (k - (e == 0 ? 1 : 0)) / order + 1;
444 ? height / (
Real)num_layers / (
Real)order
449 current_distance = old_distance +
_direction * step_size;
458 twist1 /= twist1.
norm();
468 current_distance += twist;
472 Node * new_node =
mesh->add_point(*node + current_distance,
473 node->id() + (current_node_layer * orig_nodes),
474 node->processor_id());
476 #ifdef LIBMESH_ENABLE_UNIQUE_ID 483 (current_node_layer - 1) * (orig_nodes + orig_elem) +
486 new_node->set_unique_id(uid);
489 input_boundary_info.boundary_ids(node, ids_to_copy);
491 boundary_info.add_node(new_node, ids_to_copy);
493 for (
const auto & id_to_copy : ids_to_copy)
495 boundary_info.add_node(new_node,
501 old_distance = current_distance;
502 current_node_layer++;
507 const auto & side_ids = input_boundary_info.get_side_boundary_ids();
510 side_ids.empty() ? 0 : cast_int<boundary_id_type>(*side_ids.rbegin() + 1);
515 input->comm().max(next_side_id);
517 for (
const auto & elem : input->element_ptr_range())
519 const ElemType etype = elem->type();
524 unsigned int current_layer = 0;
526 for (
unsigned int e = 0; e != total_num_elevations; e++)
530 for (
unsigned int k = 0; k != num_layers; ++k)
532 std::unique_ptr<Elem> new_elem;
533 bool is_flipped(
false);
538 new_elem = std::make_unique<Quad4>();
540 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
542 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
544 2,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
546 3,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
549 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
551 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
557 new_elem = std::make_unique<Quad9>();
559 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
561 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
564 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
567 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
569 4,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
572 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
575 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
578 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
581 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
584 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
586 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
592 new_elem = std::make_unique<Prism6>();
594 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
596 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
598 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * orig_nodes)));
600 3,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
602 4,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
604 5,
mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer + 1) * orig_nodes)));
607 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
609 new_elem->set_neighbor(2, const_cast<RemoteElem *>(
remote_elem));
611 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
613 if (new_elem->volume() < 0.0)
625 new_elem = std::make_unique<Prism18>();
627 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
629 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
631 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
634 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
637 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
640 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
642 6,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
644 7,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
646 8,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
649 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
652 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
655 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
658 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
661 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
664 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
667 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
670 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
673 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
676 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
678 new_elem->set_neighbor(2, const_cast<RemoteElem *>(
remote_elem));
680 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
682 if (new_elem->volume() < 0.0)
697 new_elem = std::make_unique<Prism21>();
699 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
701 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
703 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
706 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
709 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
712 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
714 6,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
716 7,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
718 8,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
721 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
724 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
727 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
730 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
733 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
736 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
739 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
742 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
745 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
747 18,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
750 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
753 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 1) * orig_nodes)));
756 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
758 new_elem->set_neighbor(2, const_cast<RemoteElem *>(
remote_elem));
760 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
762 if (new_elem->volume() < 0.0)
778 new_elem = std::make_unique<Hex8>();
780 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * orig_nodes)));
782 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * orig_nodes)));
784 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * orig_nodes)));
786 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (current_layer * orig_nodes)));
788 4,
mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer + 1) * orig_nodes)));
790 5,
mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer + 1) * orig_nodes)));
792 6,
mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer + 1) * orig_nodes)));
794 7,
mesh->node_ptr(elem->node_ptr(3)->id() + ((current_layer + 1) * orig_nodes)));
797 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
799 new_elem->set_neighbor(2, const_cast<RemoteElem *>(
remote_elem));
801 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
803 new_elem->set_neighbor(4, const_cast<RemoteElem *>(
remote_elem));
805 if (new_elem->volume() < 0.0)
818 new_elem = std::make_unique<Hex20>();
820 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
822 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
824 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
826 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
829 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
832 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
835 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
838 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
840 8,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
842 9,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
844 10,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
846 11,
mesh->node_ptr(elem->node_ptr(7)->id() + (2 * current_layer * orig_nodes)));
849 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
852 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
855 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
858 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
861 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
864 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
867 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
870 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 2) * orig_nodes)));
873 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
875 new_elem->set_neighbor(2, const_cast<RemoteElem *>(
remote_elem));
877 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
879 new_elem->set_neighbor(4, const_cast<RemoteElem *>(
remote_elem));
881 if (new_elem->volume() < 0.0)
898 new_elem = std::make_unique<Hex27>();
900 0,
mesh->node_ptr(elem->node_ptr(0)->id() + (2 * current_layer * orig_nodes)));
902 1,
mesh->node_ptr(elem->node_ptr(1)->id() + (2 * current_layer * orig_nodes)));
904 2,
mesh->node_ptr(elem->node_ptr(2)->id() + (2 * current_layer * orig_nodes)));
906 3,
mesh->node_ptr(elem->node_ptr(3)->id() + (2 * current_layer * orig_nodes)));
909 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 2) * orig_nodes)));
912 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 2) * orig_nodes)));
915 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 2) * orig_nodes)));
918 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 2) * orig_nodes)));
920 8,
mesh->node_ptr(elem->node_ptr(4)->id() + (2 * current_layer * orig_nodes)));
922 9,
mesh->node_ptr(elem->node_ptr(5)->id() + (2 * current_layer * orig_nodes)));
924 10,
mesh->node_ptr(elem->node_ptr(6)->id() + (2 * current_layer * orig_nodes)));
926 11,
mesh->node_ptr(elem->node_ptr(7)->id() + (2 * current_layer * orig_nodes)));
929 mesh->node_ptr(elem->node_ptr(0)->id() + ((2 * current_layer + 1) * orig_nodes)));
932 mesh->node_ptr(elem->node_ptr(1)->id() + ((2 * current_layer + 1) * orig_nodes)));
935 mesh->node_ptr(elem->node_ptr(2)->id() + ((2 * current_layer + 1) * orig_nodes)));
938 mesh->node_ptr(elem->node_ptr(3)->id() + ((2 * current_layer + 1) * orig_nodes)));
941 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 2) * orig_nodes)));
944 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 2) * orig_nodes)));
947 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 2) * orig_nodes)));
950 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 2) * orig_nodes)));
952 20,
mesh->node_ptr(elem->node_ptr(8)->id() + (2 * current_layer * orig_nodes)));
955 mesh->node_ptr(elem->node_ptr(4)->id() + ((2 * current_layer + 1) * orig_nodes)));
958 mesh->node_ptr(elem->node_ptr(5)->id() + ((2 * current_layer + 1) * orig_nodes)));
961 mesh->node_ptr(elem->node_ptr(6)->id() + ((2 * current_layer + 1) * orig_nodes)));
964 mesh->node_ptr(elem->node_ptr(7)->id() + ((2 * current_layer + 1) * orig_nodes)));
967 mesh->node_ptr(elem->node_ptr(8)->id() + ((2 * current_layer + 2) * orig_nodes)));
970 mesh->node_ptr(elem->node_ptr(8)->id() + ((2 * current_layer + 1) * orig_nodes)));
973 new_elem->set_neighbor(1, const_cast<RemoteElem *>(
remote_elem));
975 new_elem->set_neighbor(2, const_cast<RemoteElem *>(
remote_elem));
977 new_elem->set_neighbor(3, const_cast<RemoteElem *>(
remote_elem));
979 new_elem->set_neighbor(4, const_cast<RemoteElem *>(
remote_elem));
981 if (new_elem->volume() < 0.0)
1001 new_elem->set_id(elem->id() + (current_layer * orig_elem));
1002 new_elem->processor_id() = elem->processor_id();
1004 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1011 (current_layer - 1) * (orig_nodes + orig_elem) +
1012 orig_nodes + elem->id();
1014 new_elem->set_unique_id(uid);
1018 new_elem->subdomain_id() = elem->subdomain_id();
1021 if (k == num_layers - 1)
1024 const unsigned short top_id =
1025 new_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1030 boundary_info.add_side(
1036 const unsigned short top_id =
1037 new_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1040 boundary_info.add_side(
1049 auto new_id_it = elevation_swap_pairs.find(elem->subdomain_id());
1051 if (new_id_it != elevation_swap_pairs.end())
1052 new_elem->subdomain_id() = new_id_it->second;
1055 Elem * added_elem =
mesh->add_elem(std::move(new_elem));
1058 for (
unsigned int i = 0; i < num_extra_elem_integers; i++)
1059 added_elem->set_extra_integer(i, elem->get_extra_integer(i));
1067 auto new_extra_id_it = elevation_extra_swap_pairs.find(
1070 if (new_extra_id_it != elevation_extra_swap_pairs.end())
1072 new_extra_id_it->second);
1077 for (
auto s : elem->side_index_range())
1079 input_boundary_info.boundary_ids(elem, s, ids_to_copy);
1081 if (added_elem->dim() == 3)
1088 boundary_info.add_side(added_elem, cast_int<unsigned short>(s + 1), ids_to_copy);
1090 for (
const auto & id_to_copy : ids_to_copy)
1091 boundary_info.add_side(added_elem,
1092 cast_int<unsigned short>(s + 1),
1103 libmesh_assert_less(s, 2);
1104 const unsigned short sidemap[2] = {3, 1};
1106 boundary_info.add_side(added_elem, sidemap[s], ids_to_copy);
1108 for (
const auto & id_to_copy : ids_to_copy)
1109 boundary_info.add_side(added_elem,
1118 if (current_layer == 0)
1120 const unsigned short top_id =
1121 added_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1125 "We should have retrieved a proper boundary ID");
1126 boundary_info.add_side(added_elem, is_flipped ?
top_id : 0, user_bottom_boundary_id);
1129 boundary_info.add_side(added_elem, is_flipped ?
top_id : 0, next_side_id);
1132 if (current_layer == total_num_layers - 1)
1137 const unsigned short top_id =
1138 added_elem->dim() == 3 ? cast_int<unsigned short>(elem->n_sides() + 1) : 2;
1143 "We should have retrieved a proper boundary ID");
1144 boundary_info.add_side(added_elem, is_flipped ? 0 :
top_id, user_top_boundary_id);
1147 boundary_info.add_side(
1148 added_elem, is_flipped ? 0 :
top_id, cast_int<boundary_id_type>(next_side_id + 1));
1156 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1159 unsigned int total_new_node_layers = total_num_layers * order;
1160 unsigned int new_unique_ids = orig_unique_ids + (total_new_node_layers - 1) * orig_elem +
1161 total_new_node_layers * orig_nodes;
1162 mesh->set_next_unique_id(new_unique_ids);
1166 if (!input_subdomain_map.empty())
1167 mesh->set_subdomain_name_map().insert(input_subdomain_map.begin(), input_subdomain_map.end());
1168 if (!input_sideset_map.empty())
1169 mesh->get_boundary_info().set_sideset_name_map().insert(input_sideset_map.begin(),
1170 input_sideset_map.end());
1171 if (!input_nodeset_map.empty())
1172 mesh->get_boundary_info().set_nodeset_name_map().insert(input_nodeset_map.begin(),
1173 input_nodeset_map.end());
1176 boundary_info.sideset_name(new_boundary_ids.front()) = new_boundary_names.front();
1178 boundary_info.sideset_name(new_boundary_ids.back()) = new_boundary_names.back();
1180 mesh->set_isnt_prepared();
1183 if (extruding_quad_eights)
1184 mesh->prepare_for_use();
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
Swap two nodes within an element.
std::vector< std::unordered_map< boundary_id_type, boundary_id_type > > _boundary_swap_pairs
Easier to work with version of _boundary_swaps.
std::unique_ptr< MeshBase > & _input
Mesh that comes from another generator.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
virtual const char * what() const
Get out the error message.
auto norm() const -> decltype(std::norm(Real()))
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
void swap(std::vector< T > &data, const std::size_t idx0, const std::size_t idx1, const libMesh::Parallel::Communicator &comm)
Swap function for serial or distributed vector of data.
std::vector< unsigned int > _elem_integer_indices_to_swap
Point _direction
The direction of the extrusion.
const std::vector< Real > & _heights
Height of each elevation.
AdvancedExtruderGenerator(const InputParameters ¶meters)
bool hasBoundaryID(const MeshBase &input_mesh, const BoundaryID id)
Whether a particular boundary ID exists in the mesh.
const Real _twist_pitch
Axial pitch for a full rotation.
const BoundaryName _bottom_boundary
const std::vector< std::vector< subdomain_id_type > > _downward_boundary_source_blocks
The list of input mesh's blocks that need to be assigned downward boundary interfaces for each layer ...
virtual const std::string & name() const
Get the name of the class.
const BoundaryName _top_boundary
const std::vector< std::vector< boundary_id_type > > _upward_boundary_ids
Upward boundary interfaces for each layer of elevation.
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh.
Extrudes a mesh to another dimension.
static const boundary_id_type invalid_id
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
const std::vector< std::vector< boundary_id_type > > _downward_boundary_ids
Downward boundary interfaces for each layer of elevation.
void idSwapParametersProcessor(const std::string &class_name, const std::string &id_name, const std::vector< std::vector< T >> &id_swaps, std::vector< std::unordered_map< T, T >> &id_swap_pairs, const unsigned int row_index_shift=0)
Reprocess the swap related input parameters to make pairs out of them to ease further processing...
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
std::vector< std::unordered_map< subdomain_id_type, subdomain_id_type > > _subdomain_swap_pairs
Easier to work with version of _sudomain_swaps.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
static InputParameters validParams()
std::string stringify(const T &t)
conversion to string
const std::vector< std::vector< subdomain_id_type > > & _subdomain_swaps
Subdomains to swap out for each elevation.
registerMooseObjectRenamed("MooseApp", FancyExtruderGenerator, "02/18/2023 24:00", AdvancedExtruderGenerator)
const std::vector< std::vector< boundary_id_type > > & _boundary_swaps
Boundaries to swap out for each elevation.
const boundary_id_type top_id
Provides a way for users to bail out of the current solve.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< std::vector< std::vector< dof_id_type > > > & _elem_integers_swaps
Extra element integers to swap out for each elevation and each element interger name.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
const bool _has_bottom_boundary
const std::vector< Real > _biases
Bias growth factor of each elevation.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
registerMooseObject("MooseApp", AdvancedExtruderGenerator)
const std::vector< std::vector< subdomain_id_type > > _upward_boundary_source_blocks
The list of input mesh's blocks that need to be assigned upward boundary interfaces for each layer of...
const std::vector< unsigned int > & _num_layers
Number of layers in each elevation.
void extraElemIntegerSwapParametersProcessor(const std::string &class_name, const unsigned int num_sections, const unsigned int num_integers, const std::vector< std::vector< std::vector< dof_id_type >>> &elem_integers_swaps, std::vector< std::unordered_map< dof_id_type, dof_id_type >> &elem_integers_swap_pairs)
Reprocess the elem_integers_swaps into maps so they are easier to use.
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Build a MeshBase object whose underlying type will be determined by the Mesh input file block...
static InputParameters validParams()
const bool _has_top_boundary
const std::vector< std::string > & _elem_integer_names_to_swap
Names and indices of extra element integers to swap.
MooseUnits pow(const MooseUnits &, int)
MeshGenerators are objects that can modify or add to an existing mesh.
void ErrorVector unsigned int
auto index_range(const T &sizable)
std::vector< std::unordered_map< dof_id_type, dof_id_type > > _elem_integers_swap_pairs
Easier to work with version of _elem_integers_swaps.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template pow< 2 >(tan(_arg))+1.0) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(sqrt
const RemoteElem * remote_elem