26 "inputs",
"The names of the meshes forming the pattern.");
30 "A two-dimensional cartesian (square-shaped) array starting with the upper-left corner." 31 "It is composed of indexes into the inputs vector");
32 MooseEnum cartesian_pattern_boundary(
"none expanded",
"expanded");
34 "pattern_boundary", cartesian_pattern_boundary,
"The boundary shape of the patterned mesh.");
36 "generate_core_metadata",
38 "A Boolean parameter that controls whether the core related metadata " 39 "is generated for other MOOSE objects such as 'MultiControlDrumFunction' or not.");
42 "background_intervals>0",
43 "Radial intervals in the assembly peripheral region.");
47 "Size (side length) of the outmost square boundary to be generated; this is " 48 "required only when pattern type is 'expanded'.");
50 "duct_sizes",
"duct_sizes>0.0",
"Distance(s) from center to duct(s) inner boundaries.");
51 MooseEnum duct_sizes_style(
"apothem radius",
"apothem");
54 "Style in which square center to duct distance(s) is given (apothem " 55 "= center-to-face, radius = center-to-vertex).");
57 "duct_intervals",
"duct_intervals>0",
"Number of meshing intervals in each enclosing duct.");
58 params.
addParam<
bool>(
"uniform_mesh_on_sides",
60 "Whether the side elements are reorganized to have a uniform size.");
61 params.
addParam<
bool>(
"generate_control_drum_positions_file",
63 "Whether a positions file is generated in the core mesh mode.");
64 params.
addParam<
bool>(
"assign_control_drum_id",
66 "Whether control drum id is assigned to the mesh as an extra integer.");
67 std::string position_file_default =
"positions_meta.data";
69 "position_file", position_file_default,
"Data file name to store control drum positions.");
75 "Rotate the entire patterned mesh by a certain degrees that is defined here.");
77 "background_block_id",
78 "Optional customized block id for the background block in 'assembly' mode; must be provided " 79 "along with 'duct_block_ids' if 'duct_sizes' is provided.");
81 "background_block_name",
82 "Optional customized block name for the background block in 'assembly' mode; must be " 83 "provided along with 'duct_block_names' if 'duct_sizes' is provided.");
84 params.
addParam<std::vector<subdomain_id_type>>(
86 "Optional customized block ids for each duct geometry block in 'assembly' mode; must be " 87 "provided along with 'background_block_id'.");
88 params.
addParam<std::vector<SubdomainName>>(
90 std::vector<SubdomainName>(),
91 "Optional customized block names for each duct geometry block in 'assembly' mode; must be " 92 "provided along with 'background_block_name'.");
94 "external_boundary_id>0",
95 "Optional customized external boundary id.");
96 params.
addParam<
bool>(
"create_inward_interface_boundaries",
98 "Whether the inward interface boundary sidesets are created.");
99 params.
addParam<
bool>(
"create_outward_interface_boundaries",
101 "Whether the outward interface boundary sidesets are created.");
103 "stitching_boundary_name",
105 "Name of the boundary used for stitching pins togethers and with the background region");
107 "external_boundary_name", BoundaryName(),
"Optional customized external boundary name.");
108 params.
addParam<
bool>(
"deform_non_circular_region",
110 "Whether the non-circular region (outside the rings) can be deformed.");
111 params.
addParam<std::vector<std::string>>(
"id_name",
"List of extra integer ID set names");
112 params.
addParam<std::vector<MeshGeneratorName>>(
113 "exclude_id",
"Name of input meshes to be excluded in ID generation");
114 std::vector<MooseEnum> option = {
MooseEnum(
"cell pattern manual",
"cell")};
115 params.
addParam<std::vector<MooseEnum>>(
116 "assign_type", option,
"List of integer ID assignment types");
117 params.
addParam<std::vector<std::vector<std::vector<dof_id_type>>>>(
119 "User-defined element IDs. A double-indexed array starting with the upper-left corner. When " 120 "providing multiple patterns, each pattern should be separated using '|'");
121 params.
addParam<std::vector<std::vector<boundary_id_type>>>(
122 "interface_boundary_id_shift_pattern",
123 "User-defined shift values for each pattern cell. A double-indexed array starting with the " 124 "upper-left corner.");
125 MooseEnum quad_elem_type(
"QUAD4 QUAD8 QUAD9",
"QUAD4");
127 "boundary_region_element_type",
129 "Type of the quadrilateral elements to be generated in the boundary region.");
131 "allow_unused_inputs",
133 "Whether additional input assemblies can be part of inputs without being used in lattice");
137 "Whether to output the number of nodes stitched when stitching pin and background meshes");
140 "pattern_boundary background_block_id background_block_name duct_block_ids duct_block_names " 141 "external_boundary_id external_boundary_name create_inward_interface_boundaries " 142 "create_outward_interface_boundaries boundary_region_element_type",
143 "Customized Subdomain/Boundary");
145 "generate_control_drum_positions_file assign_control_drum_id position_file",
"Control Drum");
147 "background_intervals duct_intervals uniform_mesh_on_sides deform_non_circular_region",
151 "This PatternedCartesianMeshGenerator source code assembles square meshes into a square " 153 "and optionally forces the outer boundary to be square and/or adds a duct.");
160 _mesh_ptrs(getMeshes(
"inputs")),
161 _input_names(getParam<
std::vector<MeshGeneratorName>>(
"inputs")),
162 _pattern(getParam<
std::vector<
std::vector<unsigned
int>>>(
"pattern")),
163 _pattern_boundary(getParam<
MooseEnum>(
"pattern_boundary")),
164 _generate_core_metadata(getParam<bool>(
"generate_core_metadata")),
165 _background_intervals(getParam<unsigned
int>(
"background_intervals")),
166 _has_assembly_duct(isParamValid(
"duct_sizes")),
167 _duct_sizes(isParamValid(
"duct_sizes") ? getParam<
std::vector<
Real>>(
"duct_sizes")
170 _duct_intervals(isParamValid(
"duct_intervals")
171 ? getParam<
std::vector<unsigned
int>>(
"duct_intervals")
172 :
std::vector<unsigned
int>()),
173 _uniform_mesh_on_sides(getParam<bool>(
"uniform_mesh_on_sides")),
174 _generate_control_drum_positions_file(getParam<bool>(
"generate_control_drum_positions_file")),
175 _assign_control_drum_id(getParam<bool>(
"assign_control_drum_id")),
176 _rotate_angle(getParam<
Real>(
"rotate_angle")),
177 _duct_block_ids(isParamValid(
"duct_block_ids")
180 _duct_block_names(getParam<
std::vector<SubdomainName>>(
"duct_block_names")),
181 _stitching_boundary_name(getParam<BoundaryName>(
"stitching_boundary_name")),
182 _external_boundary_id(isParamValid(
"external_boundary_id")
185 _external_boundary_name(getParam<BoundaryName>(
"external_boundary_name")),
186 _create_inward_interface_boundaries(getParam<bool>(
"create_inward_interface_boundaries")),
187 _create_outward_interface_boundaries(getParam<bool>(
"create_outward_interface_boundaries")),
188 _deform_non_circular_region(getParam<bool>(
"deform_non_circular_region")),
189 _use_reporting_id(isParamValid(
"id_name")),
190 _use_exclude_id(isParamValid(
"exclude_id")),
191 _use_interface_boundary_id_shift(isParamValid(
"interface_boundary_id_shift_pattern")),
192 _boundary_quad_elem_type(
194 _allow_unused_inputs(getParam<bool>(
"allow_unused_inputs")),
195 _verbose_stitching(getParam<bool>(
"verbose_stitching"))
199 declareMeshProperty<bool>(
"is_control_drum_meta",
false);
200 declareMeshProperty<std::vector<Point>>(
"control_drum_positions", std::vector<Point>());
201 declareMeshProperty<std::vector<Real>>(
"control_drum_angles", std::vector<Real>());
202 declareMeshProperty<std::vector<std::vector<Real>>>(
"control_drums_azimuthal_meta",
203 std::vector<std::vector<Real>>());
204 declareMeshProperty<std::string>(
"position_file_name", getParam<std::string>(
"position_file"));
206 declareMeshProperty<bool>(
"square_center_trimmability",
true);
207 declareMeshProperty<bool>(
"peripheral_modifier_compatible",
_pattern_boundary ==
"expanded");
209 const unsigned int n_pattern_layers =
_pattern.size();
211 if (n_pattern_layers == 1)
212 paramError(
"pattern",
"The length (layer number) of this parameter must be larger than unity.");
214 std::vector<unsigned int> pattern_max_array;
215 std::vector<unsigned int> pattern_1d;
216 std::set<unsigned int> pattern_elem_size;
217 for (
const auto & pattern_elem :
_pattern)
219 if (pattern_elem.empty())
221 "The element of the two-dimensional array parameter pattern must not be empty.");
222 pattern_elem_size.emplace(pattern_elem.size());
223 pattern_max_array.push_back(*std::max_element(pattern_elem.begin(), pattern_elem.end()));
224 pattern_1d.insert(pattern_1d.end(), pattern_elem.begin(), pattern_elem.end());
226 if (pattern_elem_size.size() > 1 || *pattern_elem_size.begin() !=
_pattern.size())
228 "The two-dimensional array parameter pattern must have a correct square shape.");
230 if (*std::max_element(pattern_max_array.begin(), pattern_max_array.end()) >=
_input_names.size())
233 "Elements of this parameter must be smaller than the length of inputs (0-indexing).");
234 if (std::set<unsigned int>(pattern_1d.begin(), pattern_1d.end()).size() <
_input_names.size() &&
237 "All the meshes provided in inputs must be used in the lattice pattern. To bypass " 238 "this requirement, set 'allow_unused_inputs = true'");
248 "This parameter and duct_block_ids must be " 249 "provided simultaneously.");
258 "This parameter and duct_block_names must be provided simultaneously.");
262 for (
unsigned int i = 1; i <
_duct_sizes.size(); i++)
264 paramError(
"duct_sizes",
"This parameter must be strictly ascending.");
267 "This parameter, if provided, must have a length equal to length of duct_sizes.");
271 "This parameter, if provided, must have a length equal to length of duct_sizes.");
274 "This parameter must be provided when pattern_boundary is expanded.");
280 "This parameter and background_block_name must not be set when the " 281 "pattern_boundary is none.");
284 "This parameter must not be provided when pattern_boundary is none.");
291 getParam<std::vector<std::vector<boundary_id_type>>>(
"interface_boundary_id_shift_pattern");
294 std::string shape_pattern =
295 "(" + std::to_string(
_pattern.size()) +
", " + std::to_string(
_pattern[0].size()) +
") ";
296 paramError(
"interface_boundary_id_shift_pattern",
297 "This parameter, if provided, should have the same two-dimensional array shape " +
300 "the 'pattern' parameter. First dimension '" +
302 "' does not match.");
307 std::string shape_pattern =
"(" + std::to_string(
_pattern.size()) +
", " +
308 std::to_string(
_pattern[0].size()) +
") ";
310 "interface_boundary_id_shift_pattern",
311 "This parameter, if provided, should have the same two-dimensional array shape " +
314 "the 'pattern' parameter. Second dimension '" +
316 "' does not match.");
320 declareMeshProperty<bool>(
"interface_boundaries",
false);
321 declareMeshProperty<std::set<boundary_id_type>>(
"interface_boundary_ids", {});
329 const auto input_assign_types = getParam<std::vector<MooseEnum>>(
"assign_type");
330 if (input_assign_types.size() != num_reporting_ids)
331 paramError(
"assign_type",
"This parameter must have a length equal to length of id_name.");
333 std::vector<std::string> manual_ids;
334 for (
const auto i :
make_range(num_reporting_ids))
337 input_assign_types[i].getEnum<ReportingIDGeneratorUtils::AssignType>());
342 if (manual_ids.size() > 0 && !
isParamValid(
"id_pattern"))
343 paramError(
"id_pattern",
"required when 'manual' is defined in \"assign_type\"");
346 const auto input_id_patterns =
347 getParam<std::vector<std::vector<std::vector<dof_id_type>>>>(
"id_pattern");
348 if (input_id_patterns.size() != manual_ids.size())
350 "The number of patterns must be equal to the number of 'manual' types defined " 351 "in \"assign_type\".");
352 for (
unsigned int i = 0; i < manual_ids.size(); ++i)
361 std::vector<MeshGeneratorName> exclude_id_name =
362 getParam<std::vector<MeshGeneratorName>>(
"exclude_id");
366 for (
auto input_name : exclude_id_name)
380 std::unique_ptr<MeshBase>
383 std::vector<std::unique_ptr<ReplicatedMesh>> meshes(
_input_names.size());
391 if (hasMeshProperty<bool>(
"flat_side_up",
_input_names[i]))
392 if (!getMeshProperty<bool>(
"flat_side_up",
_input_names[i]))
396 "' does not have a flat side facing up, which is not supported.");
399 std::vector<Real> pitch_array;
400 std::vector<unsigned int> num_sectors_per_side_array;
401 std::vector<unsigned int> num_sectors_per_side_array_tmp;
402 std::vector<std::vector<Real>> control_drum_azimuthal_array;
403 std::vector<unsigned int> background_intervals_array;
404 std::vector<dof_id_type> node_id_background_array;
405 std::vector<Real> max_radius_array;
406 std::vector<bool> is_control_drum_array;
407 Real max_radius_global(0.0);
408 std::vector<Real> pattern_pitch_array;
416 if (!hasMeshProperty<Real>(
"pattern_pitch_meta",
_input_names[i]))
418 "In PatternedCartesianMeshGenerator ",
420 ": the unit square input mesh does not contain appropriate meta data " 421 "required for generating a core mesh. Involved input mesh: ",
423 "; metadata issue: 'pattern_pitch_meta' is missing. Note that " 424 "'generate_core_metadata' is set to true, which" 425 "means that the mesh generator is producing a core mesh by stitching the input " 426 "assembly meshes together. Therefore," 427 "the input meshes must contain the metadata of assembly meshes, which can " 428 "usually be either automatically assigned " 429 "by using another PatternedCartesianMeshGenerator with 'generate_core_metadata' set as " 430 "false or manually assigned by AddMetaDataGenerator.");
431 pattern_pitch_array.push_back(getMeshProperty<Real>(
"pattern_pitch_meta",
_input_names[i]));
433 if (pattern_pitch_array.back() == 0.0)
435 "In PatternedCartesianMeshGenerator ",
437 ": the unit square input mesh does not contain appropriate meta data " 438 "required for generating a core mesh. Involved input mesh: ",
440 "; metadata issue: 'pattern_pitch_meta' is zero. Note that " 441 "'generate_core_metadata' is set to true, which" 442 "means that the mesh generator is producing a core mesh by stitching the input " 443 "assembly meshes together. Therefore," 444 "the input meshes must contain the metadata of assembly meshes, which can " 445 "usually be either automatically assigned " 446 "by using another PatternedCartesianMeshGenerator with 'generate_core_metadata' set as " 447 "false or manually assigned by AddMetaDataGenerator.");
448 is_control_drum_array.push_back(
449 getMeshProperty<bool>(
"is_control_drum_meta",
_input_names[i]));
450 control_drum_azimuthal_array.push_back(
451 getMeshProperty<bool>(
"is_control_drum_meta",
_input_names[i])
453 : std::vector<Real>());
456 *std::max_element(pattern_pitch_array.begin(), pattern_pitch_array.end()),
457 *std::min_element(pattern_pitch_array.begin(), pattern_pitch_array.end())))
459 "In PatternedCartesianMeshGenerator ",
461 ": pattern_pitch metadata values of all input mesh generators must be identical when " 462 "pattern_boundary is 'none' and generate_core_metadata is true. Please check the " 463 "parameters of the mesh generators that produce the input meshes. " 464 "Note that some of these mesh generator, such as " 465 "CartesianConcentricCircleAdaptiveBoundaryMeshGenerator and FlexiblePatternGenerator," 466 "may have different definitions of square size in their input parameters. Please refer " 467 "to the documentation of these mesh generators.",
483 if (!hasMeshProperty<Real>(
"pitch_meta",
_input_names[i]))
484 mooseError(
"In PatternedCartesianMeshGenerator ",
486 ": the unit square input mesh does not contain appropriate meta data " 487 "required for generating an assembly. Involved input mesh: ",
489 "; metadata issue: 'pitch_meta' is missing");
490 pitch_array.push_back(getMeshProperty<Real>(
"pitch_meta",
_input_names[i]));
492 num_sectors_per_side_array_tmp =
493 getMeshProperty<std::vector<unsigned int>>(
"num_sectors_per_side_meta",
_input_names[i]);
494 if (*std::max_element(num_sectors_per_side_array_tmp.begin(),
495 num_sectors_per_side_array_tmp.end()) !=
496 *std::min_element(num_sectors_per_side_array_tmp.begin(),
497 num_sectors_per_side_array_tmp.end()))
498 mooseError(
"In PatternedCartesianMeshGenerator ",
500 ": num_sectors_per_side metadata values of all four sides of each input mesh " 501 "generator must be identical.");
502 num_sectors_per_side_array.push_back(*num_sectors_per_side_array_tmp.begin());
503 background_intervals_array.push_back(
504 getMeshProperty<unsigned int>(
"background_intervals_meta",
_input_names[i]));
505 node_id_background_array.push_back(
506 getMeshProperty<dof_id_type>(
"node_id_background_meta",
_input_names[i]));
507 max_radius_array.push_back(getMeshProperty<Real>(
"max_radius_meta",
_input_names[i]));
509 max_radius_global = *max_element(max_radius_array.begin(), max_radius_array.end());
511 *std::min_element(pitch_array.begin(), pitch_array.end())))
512 mooseError(
"In PatternedCartesianMeshGenerator ",
514 ": pitch metadata values of all input mesh generators must be identical. Please " 515 "check the parameters of the mesh generators that produce the input meshes.",
518 if (*std::max_element(num_sectors_per_side_array.begin(), num_sectors_per_side_array.end()) !=
519 *std::min_element(num_sectors_per_side_array.begin(), num_sectors_per_side_array.end()))
521 "In PatternedCartesianMeshGenerator ",
523 ": num_sectors_per_side metadata values of all input mesh generators must be identical.");
529 std::vector<Real> extra_dist;
530 Real extra_dist_shift(0.0);
536 std::vector<unsigned int> peripheral_duct_intervals;
541 for (
unsigned int i = 0; i <
_duct_sizes.size(); i++)
546 extra_dist.push_back(0.5 * (
_duct_sizes[i] * 2.0 - pitch_array.front() *
_pattern.size()));
551 "The duct sizes should not exceed the size of the square boundary.");
564 if (extra_dist.front() <= extra_dist_tol)
566 extra_dist_shift = extra_dist_shift_0 - extra_dist.front();
567 for (
Real &
d : extra_dist)
568 d += extra_dist_shift;
572 : (pitch_array.front() / 2.0);
573 y_max_0 = pitch_array.front() / 2.0 + extra_dist.front();
574 y_max_n = y_max_0 - extra_dist_shift;
575 if (y_max_n <= y_min)
576 mooseError(
"In PatternedCartesianMeshGenerator ",
578 ": the assembly is cut off so much that the internal structure that should not " 579 "be altered is compromised.");
587 std::vector<std::set<boundary_id_type>> input_interface_boundary_ids;
588 input_interface_boundary_ids.resize(
_input_names.size());
593 if (!hasMeshProperty<bool>(
"interface_boundaries",
_input_names[i]))
594 mooseError(
"Metadata 'interface_boundaries' could not be found on the input mesh: ",
596 if (!getMeshProperty<bool>(
"interface_boundaries",
_input_names[i]))
597 mooseError(
"Interface boundary ids were not constructed in the input mesh",
600 mooseError(
"Metadata 'interface_boundary_ids' could not be found on the input mesh: ",
606 input_interface_boundary_ids[i] =
610 ? pitch_array.front()
612 std::vector<Real> control_drum_positions_x;
613 std::vector<Real> control_drum_positions_y;
614 std::vector<std::vector<Real>> control_drum_azimuthals;
616 std::unique_ptr<ReplicatedMesh> out_mesh;
618 for (
unsigned i = 0; i <
_pattern.size(); i++)
620 const Real deltax = 0.0;
621 Real deltay = -(
Real)(i)*input_pitch;
623 for (
unsigned int j = 0;
j <
_pattern[i].size();
j++)
626 ReplicatedMesh & pattern_mesh = *meshes[pattern];
634 control_drum_positions_x.push_back(deltax +
j * input_pitch);
635 control_drum_positions_y.push_back(deltay);
636 control_drum_azimuthals.push_back(control_drum_azimuthal_array[pattern]);
639 if (
j == 0 && i == 0)
643 out_mesh->add_elem_integer(
646 is_control_drum_array[pattern] ? control_drum_azimuthals.size() : 0);
651 input_interface_boundary_ids[pattern]);
658 Real rotation_angle = std::numeric_limits<Real>::max();
659 Real orientation = std::numeric_limits<Real>::max();
660 unsigned int mesh_type = std::numeric_limits<unsigned int>::max();
661 bool on_periphery =
true;
663 if (
j == 0 && i == 0)
665 rotation_angle = 90.;
669 else if (
j == 0 && i ==
_pattern.size() - 1)
671 rotation_angle = 180.;
675 else if (
j ==
_pattern[i].size() - 1 && i == 0)
683 rotation_angle = -90.;
695 rotation_angle = 180.;
701 rotation_angle = 90.;
707 rotation_angle = -90.;
712 on_periphery =
false;
721 num_sectors_per_side_array,
722 peripheral_duct_intervals,
726 if (extra_dist_shift != 0)
728 *tmp_peripheral_mesh, orientation, y_max_0, y_max_n, y_min, mesh_type, 90.0);
734 input_interface_boundary_ids[pattern]);
736 if (i == 0 &&
j == 0)
737 out_mesh = std::move(tmp_peripheral_mesh);
742 const auto & increment_subdomain_map = tmp_peripheral_mesh->get_subdomain_name_map();
743 out_mesh->set_subdomain_name_map().insert(increment_subdomain_map.begin(),
744 increment_subdomain_map.end());
746 const auto stitching_boundary_id_base =
748 const auto stitching_boundary_id_periph =
751 MeshTools::Modification::translate(
752 *tmp_peripheral_mesh, deltax +
j * input_pitch, deltay, 0);
753 out_mesh->stitch_meshes(*tmp_peripheral_mesh,
754 stitching_boundary_id_base,
755 stitching_boundary_id_periph,
766 pattern_mesh.add_elem_integer(
769 is_control_drum_array[pattern] ? control_drum_azimuthals.size() : 0);
772 MeshTools::Modification::translate(pattern_mesh, deltax +
j * input_pitch, deltay, 0);
775 auto & main_subdomain_map = out_mesh->set_subdomain_name_map();
778 const auto & increment_subdomain_map = pattern_mesh.get_subdomain_name_map();
779 main_subdomain_map.insert(increment_subdomain_map.begin(), increment_subdomain_map.end());
781 std::set<SubdomainName> main_subdomain_map_name_list;
782 for (
auto const & id_name_pair : main_subdomain_map)
783 main_subdomain_map_name_list.emplace(id_name_pair.second);
784 if (main_subdomain_map.size() != main_subdomain_map_name_list.size())
785 paramError(
"inputs",
"The input meshes contain subdomain name maps with conflicts.");
790 input_interface_boundary_ids[pattern]);
792 const auto stitching_boundary_id_1 =
794 const auto stitching_boundary_id_2 =
796 out_mesh->stitch_meshes(pattern_mesh,
797 stitching_boundary_id_1,
798 stitching_boundary_id_2,
805 MeshTools::Modification::translate(pattern_mesh, -(deltax +
j * input_pitch), -deltay, 0);
810 input_interface_boundary_ids[pattern],
816 auto side_list = out_mesh->get_boundary_info().build_side_list();
817 const auto stitching_boundary_id =
819 for (
auto & sl : side_list)
822 if (std::get<2>(sl) == stitching_boundary_id)
823 if (out_mesh->elem_ptr(std::get<0>(sl))->neighbor_ptr(std::get<1>(sl)) !=
nullptr)
824 out_mesh->get_boundary_info().remove_side(
825 out_mesh->elem_ptr(std::get<0>(sl)), std::get<1>(sl), std::get<2>(sl));
828 out_mesh->get_boundary_info().clear_boundary_node_ids();
830 out_mesh->get_boundary_info().build_node_list_from_side_list();
831 const auto node_list = out_mesh->get_boundary_info().build_node_list();
833 std::vector<Real> bd_x_list;
834 std::vector<Real> bd_y_list;
835 std::vector<std::pair<Real, dof_id_type>> node_azi_list;
837 const Real origin_x = origin_pt(0);
838 const Real origin_y = origin_pt(1);
840 MeshTools::Modification::translate(*out_mesh, -origin_x, -origin_y, 0);
844 MeshTools::Modification::rotate(*out_mesh, -45.0, 0.0, 0.0);
845 const Real azi_tol = 1E-8;
846 for (
unsigned int i = 0; i < node_list.size(); ++i)
848 if (std::get<1>(node_list[i]) == stitching_boundary_id)
850 node_azi_list.push_back(
851 std::make_pair(atan2(out_mesh->node_ref(std::get<0>(node_list[i]))(1),
852 out_mesh->node_ref(std::get<0>(node_list[i]))(0)) *
854 std::get<0>(node_list[i])));
856 if (node_azi_list.back().first + 180.0 <= azi_tol)
857 node_azi_list.back().first = 180;
860 std::sort(node_azi_list.begin(), node_azi_list.end());
861 const unsigned int side_intervals = node_azi_list.size() /
SQUARE_NUM_SIDES;
864 for (
unsigned int j = 1;
j <= side_intervals;
j++)
866 Real azi_corr_tmp = atan2((
Real)
j * 2.0 / (
Real)side_intervals - 1.0, 1.0);
868 Real y_tmp = x_tmp * std::tan(azi_corr_tmp);
870 Point p_tmp = Point(x_tmp, y_tmp, 0.0);
871 out_mesh->add_point(p_tmp, node_azi_list[i * side_intervals +
j - 1].second);
881 MeshTools::Modification::rotate(*out_mesh, 45.0, 0.0, 0.0);
884 MeshTools::Modification::rotate(*out_mesh,
_rotate_angle, 0.0, 0.0);
890 const Real azi_tol = 1E-8;
891 std::vector<std::tuple<Real, Point, std::vector<Real>,
dof_id_type>> control_drum_tmp;
892 std::vector<dof_id_type> control_drum_id_sorted;
893 for (
unsigned int i = 0; i < control_drum_positions_x.size(); ++i)
895 control_drum_positions_x[i] -= origin_x;
896 control_drum_positions_y[i] -= origin_y;
898 Real cd_angle = atan2(control_drum_positions_y[i], control_drum_positions_x[i]);
900 for (
unsigned int j = 0;
j < control_drum_azimuthals[i].size();
j++)
903 control_drum_azimuthals[i][
j] =
904 atan2(std::sin(control_drum_azimuthals[i][
j] / 180.0 * M_PI),
905 std::cos(control_drum_azimuthals[i][
j] / 180.0 * M_PI)) /
908 std::sort(control_drum_azimuthals[i].begin(), control_drum_azimuthals[i].end());
910 if (std::abs(cd_angle) < azi_tol)
912 else if (cd_angle < 0.0)
913 cd_angle += 2 * M_PI;
914 control_drum_tmp.push_back(
915 std::make_tuple(cd_angle,
916 Point(control_drum_positions_x[i], control_drum_positions_y[i], 0.0),
917 control_drum_azimuthals[i],
920 std::sort(control_drum_tmp.begin(), control_drum_tmp.end());
921 std::vector<Point> control_drum_positions;
922 std::vector<Real> control_drum_angles;
923 std::vector<std::vector<Real>> control_drums_azimuthal_meta;
924 for (
unsigned int i = 0; i < control_drum_tmp.size(); ++i)
926 control_drum_positions.push_back(std::get<1>(control_drum_tmp[i]));
927 control_drum_angles.push_back(std::get<0>(control_drum_tmp[i]));
928 control_drums_azimuthal_meta.push_back(std::get<2>(control_drum_tmp[i]));
929 control_drum_id_sorted.push_back(std::get<3>(control_drum_tmp[i]));
933 setMeshProperty(
"control_drums_azimuthal_meta", control_drums_azimuthal_meta);
937 unsigned int drum_integer_index = out_mesh->get_elem_integer_index(
"control_drum_id");
938 for (
const auto & elem : out_mesh->element_ptr_range())
940 dof_id_type unsorted_control_drum_id = elem->get_extra_integer(drum_integer_index);
941 if (unsorted_control_drum_id != 0)
943 auto sorted_iter = std::find(control_drum_id_sorted.begin(),
944 control_drum_id_sorted.end(),
945 unsorted_control_drum_id);
946 elem->set_extra_integer(drum_integer_index,
947 std::distance(control_drum_id_sorted.begin(), sorted_iter) + 1);
954 std::string position_file_name = getMeshProperty<std::string>(
"position_file_name",
name());
955 std::ofstream pos_file(position_file_name);
956 for (
unsigned int i = 0; i < control_drum_positions.size(); ++i)
957 pos_file << control_drum_positions[i](0) <<
" " << control_drum_positions[i](1) <<
" 0.0\n";
969 for (
const auto & elem : out_mesh->active_element_ptr_range())
972 if (elem->subdomain_id() == i)
1000 auto & new_sideset_map = out_mesh->get_boundary_info().set_sideset_name_map();
1001 auto & new_nodeset_map = out_mesh->get_boundary_info().set_nodeset_name_map();
1002 for (
unsigned int i = 0; i < meshes.size(); i++)
1004 const auto input_sideset_map = meshes[i]->get_boundary_info().get_sideset_name_map();
1005 new_sideset_map.insert(input_sideset_map.begin(), input_sideset_map.end());
1006 const auto input_nodeset_map = meshes[i]->get_boundary_info().get_nodeset_name_map();
1007 new_nodeset_map.insert(input_nodeset_map.begin(), input_nodeset_map.end());
1011 const std::set<boundary_id_type> boundary_ids = out_mesh->get_boundary_info().get_boundary_ids();
1016 input_interface_boundary_ids,
1020 if (interface_boundary_ids.size() > 0)
1026 out_mesh->set_isnt_prepared();
1033 ReplicatedMesh & mesh,
1034 const unsigned int pattern,
1036 const std::vector<Real> & extra_dist,
1037 const std::vector<unsigned int> & num_sectors_per_side_array,
1038 const std::vector<unsigned int> & peripheral_duct_intervals,
1039 const Real rotation_angle,
1040 const unsigned int mesh_type)
1042 std::vector<std::pair<Real, Real>> positions_inner;
1043 std::vector<std::pair<Real, Real>> d_positions_outer;
1045 std::vector<std::vector<unsigned int>> peripheral_point_index;
1046 std::vector<std::pair<Real, Real>> sub_positions_inner;
1047 std::vector<std::pair<Real, Real>> sub_d_positions_outer;
1055 peripheral_point_index = {{0, 1, 2}, {2, 3, 4}};
1058 peripheral_point_index = {{0, 1, 5}};
1062 for (
unsigned int i = 0; i < extra_dist.size(); i++)
1067 positions_inner, d_positions_outer, i == 0 ? 0.0 : extra_dist[i - 1], extra_dist[i],
pitch);
1070 for (
unsigned int peripheral_index = 0; peripheral_index < peripheral_point_index.size();
1074 for (
unsigned int vector_index = 0; vector_index < 3; vector_index++)
1076 sub_positions_inner.push_back(
1077 positions_inner[peripheral_point_index[peripheral_index][vector_index]]);
1078 sub_d_positions_outer.push_back(
1079 d_positions_outer[peripheral_point_index[peripheral_index][vector_index]]);
1082 peripheral_duct_intervals[i],
1083 sub_positions_inner,
1084 sub_d_positions_outer,
1088 (i != extra_dist.size() - 1) &&
1092 meshp0->prepare_for_use();
1095 MeshTools::Modification::rotate(*meshp0, rotation_angle, 0, 0);
1098 sub_positions_inner.resize(0);
1099 sub_d_positions_outer.resize(0);
1106 std::vector<std::pair<Real, Real>> & positions_inner,
1107 std::vector<std::pair<Real, Real>> & d_positions_outer,
1108 const Real extra_dist_in,
1109 const Real extra_dist_out,
1110 const Real
pitch)
const 1112 positions_inner.resize(0);
1113 d_positions_outer.resize(0);
1138 positions_inner.push_back(std::make_pair(-
pitch / 2.0,
pitch / 2.0 + extra_dist_in));
1139 positions_inner.push_back(std::make_pair(0.0,
pitch / 2.0 + extra_dist_in));
1140 positions_inner.push_back(
1141 std::make_pair(
pitch / 2.0 + extra_dist_in,
pitch / 2.0 + extra_dist_in));
1142 positions_inner.push_back(std::make_pair(
pitch / 2.0 + extra_dist_in, 0.0));
1143 positions_inner.push_back(std::make_pair(
pitch / 2.0 + extra_dist_in, -
pitch / 2.0));
1144 positions_inner.push_back(std::make_pair(
pitch / 2.0,
pitch / 2.0 + extra_dist_in));
1148 d_positions_outer.push_back(std::make_pair(0.0, extra_dist_out - extra_dist_in));
1149 d_positions_outer.push_back(std::make_pair(0.0, extra_dist_out - extra_dist_in));
1150 d_positions_outer.push_back(
1151 std::make_pair(extra_dist_out - extra_dist_in, extra_dist_out - extra_dist_in));
1152 d_positions_outer.push_back(std::make_pair(extra_dist_out - extra_dist_in, 0.0));
1153 d_positions_outer.push_back(std::make_pair(extra_dist_out - extra_dist_in, 0.0));
1154 d_positions_outer.push_back(std::make_pair(0.0, extra_dist_out - extra_dist_in));
1159 MeshBase & mesh,
const std::vector<std::unique_ptr<ReplicatedMesh>> & from_meshes)
const 1162 for (
unsigned int i = 0; i < num_reporting_ids; ++i)
1165 unsigned int extra_id_index;
1166 if (!
mesh.has_elem_integer(element_id_name))
1167 extra_id_index =
mesh.add_elem_integer(element_id_name);
1170 extra_id_index =
mesh.get_elem_integer_index(element_id_name);
1172 "id_name",
"An element integer with the name '", element_id_name,
"' already exists");
1178 std::set<subdomain_id_type> background_block_ids =
1180 : std::set<subdomain_id_type>();
1182 const bool using_manual_id =
1190 background_block_ids,
1195 : std::vector<std::vector<dof_id_type>>());
const bool _deform_non_circular_region
Whether the non-circular region (outside the rings) can be deformed.
const std::vector< std::vector< unsigned int > > & _pattern
2D vector of the square pattern
const bool _use_interface_boundary_id_shift
whether the interface boundary ids from input meshes are shifted, using a user-defined pattern of val...
T & setMeshProperty(const std::string &data_name, Args &&... args)
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void assignReportingIDs(MeshBase &mesh, const unsigned int extra_id_index, const ReportingIDGeneratorUtils::AssignType assign_type, const bool use_exclude_id, const std::vector< bool > &exclude_ids, const bool has_assembly_boundary, const std::set< subdomain_id_type > background_block_ids, const std::vector< std::unique_ptr< libMesh::ReplicatedMesh >> &input_meshes, const std::vector< std::vector< unsigned int >> &pattern, const std::vector< std::vector< dof_id_type >> &id_pattern)
assign the reporting IDs to the output mesh from the cartesian or hexagonal patterned mesh generator ...
assign IDs based on user-defined mapping
const bool _uniform_mesh_on_sides
Whether the nodes on the external boundary are uniformly distributed.
const bool _use_reporting_id
Whether reporting ID is added to mesh.
std::vector< std::vector< boundary_id_type > > _interface_boundary_id_shift_pattern
hold user-defined shift values for each pattern cell
const BoundaryName _stitching_boundary_name
Name of the boundary used for stitching.
void positionSetup(std::vector< std::pair< Real, Real >> &positions_inner, std::vector< std::pair< Real, Real >> &d_positions_outer, const Real extra_dist_in, const Real extra_dist_out, const Real pitch) const
Computes the inner and outer node positions of the peripheral region for a single layer...
const std::vector< MeshGeneratorName > & _input_names
Names of input meshes.
const bool _generate_control_drum_positions_file
Whether a text file containing control drum positions is generated.
const std::vector< SubdomainName > _duct_block_names
Subdomain Names of the duct layers.
const bool _has_assembly_duct
Whether the square pattern has external duct(s)
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
QUAD_ELEM_TYPE _boundary_quad_elem_type
Type of quadrilateral elements to be generated in the periphery region.
std::vector< SubdomainName > _peripheral_block_names
Subdomain Names of the peripheral regions.
void changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
std::map< std::string, std::vector< std::vector< dof_id_type > > > _id_patterns
hold ID patterns for each manual reporting ID. Individual ID pattern contains ID values for each patt...
virtual const std::string & name() const
This PatternedCartesianMeshGenerator source code assembles square meshes into a rectangular grid and ...
void nodeCoordRotate(Real &x, Real &y, const Real theta) const
Calculates x and y coordinates after rotating by theta angle.
std::unique_ptr< MeshBase > generate() override
bool isParamValid(const std::string &name) const
Real _pattern_pitch
Pitch size of the input assembly mesh.
const bool _create_outward_interface_boundaries
Whether outward interface boundaries are created.
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
const BoundaryName _external_boundary_name
Boundary name of mesh's external boundary.
const bool _use_exclude_id
flag to indicate if exclude_id is defined
void adjustPeripheralQuadraticElements(MeshBase &out_mesh, const QUAD_ELEM_TYPE boundary_quad_elem_type) const
Adjusts the mid-edge node locations in boundary regions when using quadratic elements with uniform bo...
const PolygonSizeStyle _duct_sizes_style
Style of the duct size parameter(s)
static InputParameters validParams()
const MooseEnum _pattern_boundary
Type of the external boundary shape.
std::string pitchMetaDataErrorGenerator(const std::vector< MeshGeneratorName > &input_names, const std::vector< Real > &metadata_vals, const std::string &metadata_name) const
Generate a string that contains the detailed metadata information for inconsistent input mesh metadat...
PatternedCartesianMeshGenerator(const InputParameters ¶meters)
static const std::string pitch
static InputParameters validParams()
std::vector< ReportingIDGeneratorUtils::AssignType > _assign_types
reporting ID assignment type
void addPeripheralMesh(ReplicatedMesh &mesh, const unsigned int pattern, const Real pitch, const std::vector< Real > &extra_dist, const std::vector< unsigned int > &num_sectors_per_side_array, const std::vector< unsigned int > &peripheral_duct_intervals, const Real rotation_angle, const unsigned int mesh_type)
Adds background and duct region mesh to each part outer part of stitched square meshes.
const unsigned int _background_intervals
Number of radial intervals in the background region.
void paramError(const std::string ¶m, Args... args) const
std::vector< std::string > _reporting_id_names
names of reporting ID
const std::vector< std::unique_ptr< MeshBase > * > _mesh_ptrs
The input meshes.
const bool _create_inward_interface_boundaries
Whether inward interface boundaries are created.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
registerMooseObject("ReactorApp", PatternedCartesianMeshGenerator)
A base class that contains common members for Reactor module mesh generators.
const Real _rotate_angle
The mesh rotation angle after mesh generation.
const bool _generate_core_metadata
Whether a reactor core mesh with core metadata is generated.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
std::vector< Real > _duct_sizes
Size parameter(s) of duct(s)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void addReportingIDs(MeshBase &mesh, const std::vector< std::unique_ptr< ReplicatedMesh >> &from_meshes) const
Adds the reporting IDs onto the input mesh.
std::vector< bool > _exclude_ids
vector indicating which ids in the pattern to exclude (true at pattern positions to exclude) ...
void paramWarning(const std::string ¶m, Args... args) const
Point meshCentroidCalculator(const MeshBase &mesh)
const boundary_id_type _external_boundary_id
Boundary ID of mesh's external boundary.
const std::vector< subdomain_id_type > _duct_block_ids
Subdomain IDs of the duct layers.
const bool _allow_unused_inputs
Whether to allow additional assembly types to be passed to "inputs" parameter without being used in l...
void reassignBoundaryIDs(MeshBase &mesh, const boundary_id_type id_shift, const std::set< boundary_id_type > &boundary_ids, const bool reverse=false)
reassign interface boundary IDs on the input mesh by applying the boundary ID shift ...
std::vector< subdomain_id_type > _peripheral_block_ids
Subdomain IDs of the peripheral regions.
void ErrorVector unsigned int
auto index_range(const T &sizable)
const bool _assign_control_drum_id
Wheter control drum IDs are assigned as an extra element integer.
std::unique_ptr< ReplicatedMesh > buildSimplePeripheral(const unsigned int num_sectors_per_side, const unsigned int peripheral_invervals, const std::vector< std::pair< Real, Real >> &position_inner, const std::vector< std::pair< Real, Real >> &d_position_outer, const subdomain_id_type id_shift, const QUAD_ELEM_TYPE quad_elem_type, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true)
Creates peripheral area mesh for the patterned hexagon mesh.
const bool _verbose_stitching
Whether the mesh stitching should be verbose.
const std::vector< unsigned int > _duct_intervals
Number(s) of radial intervals of duct layer(s)
PolygonSizeStyle
An enum class for style of input polygon size.
std::set< boundary_id_type > getInterfaceBoundaryIDs(const std::vector< std::vector< unsigned int >> &pattern, const std::vector< std::vector< boundary_id_type >> &interface_boundary_id_shift_pattern, const std::set< boundary_id_type > &boundary_ids, const std::vector< std::set< boundary_id_type >> &input_interface_boundary_ids, const bool use_interface_boundary_id_shift, const bool create_interface_boundary_id, const unsigned int num_extra_layers) const
returns a list of interface boundary IDs on the mesh generated by this mesh generator ...
void cutOffPolyDeform(MeshBase &mesh, const Real orientation, const Real y_max_0, const Real y_max_n, const Real y_min, const unsigned int mesh_type, const Real unit_angle=60.0, const Real tols=1E-5) const
Deforms peripheral region when the external side of a polygon assembly of stitched meshes cuts off th...