https://mooseframework.inl.gov
AssemblyMeshGenerator.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "AssemblyMeshGenerator.h"
11 
13 #include "MooseApp.h"
14 #include "Factory.h"
15 #include "libmesh/elem.h"
16 #include "MooseMeshUtils.h"
17 
19 
22 {
24 
25  params.addRequiredParam<std::vector<MeshGeneratorName>>(
26  "inputs", "The PinMeshGenerators that form the components of the assembly.");
27 
28  params.addRequiredParam<subdomain_id_type>("assembly_type",
29  "The integer ID for this assembly type definition");
30 
31  params.addRequiredParam<std::vector<std::vector<unsigned int>>>(
32  "pattern",
33  "A double-indexed array starting with the upper-left corner where the index"
34  "represents the layout of input pins in the assembly lattice.");
35 
36  params.addRangeCheckedParam<std::vector<Real>>(
37  "duct_halfpitch",
38  "duct_halfpitch>0.0",
39  "Distance(s) from center to duct(s) inner boundaries.");
40 
41  params.addRangeCheckedParam<unsigned int>("background_intervals",
42  "background_intervals>0",
43  "Radial intervals in the assembly peripheral region.");
44 
45  params.addRangeCheckedParam<std::vector<unsigned int>>(
46  "duct_intervals", "duct_intervals>0", "Number of meshing intervals in each enclosing duct.");
47 
48  params.addParam<std::vector<subdomain_id_type>>(
49  "background_region_id",
50  "The region id for the background area between the pins and the ducts to set region_id "
51  "extra-element integer");
52 
53  params.addParam<std::vector<std::vector<subdomain_id_type>>>(
54  "duct_region_ids",
55  "The region id for the ducts from innermost to outermost, to set region_id "
56  "extra-element integer.");
57 
58  params.addParam<std::vector<std::string>>("background_block_name",
59  "The block names for the assembly background regions");
60 
61  params.addParam<std::vector<std::vector<std::string>>>(
62  "duct_block_names",
63  "The block names for the assembly duct regions from innermost to outermost");
64 
65  params.addParam<bool>("extrude",
66  false,
67  "Determines if this is the final step in the geometry construction"
68  " and extrudes the 2D geometry to 3D. If this is true then this mesh "
69  "cannot be used in further mesh building in the Reactor workflow");
70  params.addParamNamesToGroup("background_region_id duct_region_ids assembly_type", "ID assigment");
71  params.addParamNamesToGroup("background_intervals background_region_id",
72  "Background specifications");
73  params.addParamNamesToGroup("duct_intervals duct_region_ids duct_halfpitch",
74  "Duct specifications");
75 
76  params.addClassDescription("This AssemblyMeshGenerator object is designed to generate "
77  "assembly-like structures, with IDs, from a reactor geometry. "
78  "The assembly-like structures must consist of a full pattern of equal "
79  "sized pins from PinMeshGenerator. "
80  "A hexagonal assembly will be placed inside of a bounding hexagon "
81  "consisting of a background region and, optionally,"
82  " duct regions.");
83  // depletion id generation params are added
84  addDepletionIDParams(params);
85 
86  return params;
87 }
88 
90  : ReactorGeometryMeshBuilderBase(parameters),
91  _inputs(getParam<std::vector<MeshGeneratorName>>("inputs")),
92  _assembly_type(getParam<subdomain_id_type>("assembly_type")),
93  _pattern(getParam<std::vector<std::vector<unsigned int>>>("pattern")),
94  _duct_sizes(isParamValid("duct_halfpitch") ? getParam<std::vector<Real>>("duct_halfpitch")
95  : std::vector<Real>()),
96  _background_intervals(
97  isParamValid("background_intervals") ? getParam<unsigned int>("background_intervals") : 0),
98  _duct_intervals(isParamValid("duct_intervals")
99  ? getParam<std::vector<unsigned int>>("duct_intervals")
100  : std::vector<unsigned int>()),
101  _background_region_id(isParamValid("background_region_id")
102  ? getParam<std::vector<subdomain_id_type>>("background_region_id")
103  : std::vector<subdomain_id_type>()),
104  _duct_region_ids(isParamValid("duct_region_ids")
105  ? getParam<std::vector<std::vector<subdomain_id_type>>>("duct_region_ids")
106  : std::vector<std::vector<subdomain_id_type>>()),
107  _extrude(getParam<bool>("extrude"))
108 {
109  MeshGeneratorName reactor_params =
110  MeshGeneratorName(getMeshProperty<std::string>(RGMB::reactor_params_name, _inputs[0]));
111  // Check that MG name for reactor params is consistent across all assemblies
112  for (unsigned int i = 1; i < _inputs.size(); i++)
113  if (getMeshProperty<std::string>(RGMB::reactor_params_name, _inputs[i]) != reactor_params)
114  mooseError("The name of all reactor_params objects should be identical across all input pins "
115  "in the assembly.\n");
116 
117  // Initialize ReactorMeshParams object stored in pin input
118  initializeReactorMeshParams(reactor_params);
119 
120  _geom_type = getReactorParam<std::string>(RGMB::mesh_geometry);
121  _mesh_dimensions = getReactorParam<unsigned int>(RGMB::mesh_dimensions);
122 
123  if (_extrude && _mesh_dimensions != 3)
124  paramError("extrude",
125  "In order to extrude this mesh, ReactorMeshParams/dim needs to be set to 3\n");
126  if (_extrude && (!hasReactorParam<boundary_id_type>(RGMB::top_boundary_id) ||
127  !hasReactorParam<boundary_id_type>(RGMB::bottom_boundary_id)))
128  mooseError("Both top_boundary_id and bottom_boundary_id must be provided in ReactorMeshParams "
129  "if using extruded geometry");
130 
131  Real base_pitch = 0.0;
132 
133  // Check constitutent pins do not have shared pin_type ids
134  std::map<subdomain_id_type, std::string> pin_map_type_to_name;
135  for (const auto i : index_range(_inputs))
136  {
137  auto pin = _inputs[i];
138  if (i == 0)
139  base_pitch = getMeshProperty<Real>(RGMB::pitch, pin);
140  else
141  {
142  auto pitch = getMeshProperty<Real>(RGMB::pitch, pin);
143  if (!MooseUtils::absoluteFuzzyEqual(pitch, base_pitch))
144  mooseError("All pins within an assembly must have the same pitch");
145  }
146  if (getMeshProperty<bool>(RGMB::extruded, pin))
147  mooseError("Pins that have already been extruded cannot be used in AssemblyMeshGenerator "
148  "definition.\n");
149  const auto pin_type = getMeshProperty<subdomain_id_type>(RGMB::pin_type, pin);
150  if (pin_map_type_to_name.find(pin_type) != pin_map_type_to_name.end() &&
151  pin_map_type_to_name[pin_type] != pin)
152  mooseError("Constituent pins have shared pin_type ids but different names. Each uniquely "
153  "defined pin in PinMeshGenerator must have its own pin_type id.");
154  pin_map_type_to_name[pin_type] = pin;
155  }
156  auto assembly_pitch = getReactorParam<Real>(RGMB::assembly_pitch);
157 
158  unsigned int n_axial_levels =
159  (_mesh_dimensions == 3)
160  ? getReactorParam<std::vector<unsigned int>>(RGMB::axial_mesh_intervals).size()
161  : 1;
162  if (_geom_type == "Square")
163  {
164  const auto ny = _pattern.size();
165  const auto nx = _pattern[0].size();
166  if (_background_region_id.size() == 0)
167  {
168  if ((!MooseUtils::absoluteFuzzyEqual(base_pitch * ny, assembly_pitch)) ||
169  (!MooseUtils::absoluteFuzzyEqual(base_pitch * nx, assembly_pitch)))
170  mooseError(
171  "Assembly pitch must be equal to lattice dimension times pin pitch for Cartesian "
172  "assemblies with no background region");
173  if (_background_intervals > 0)
174  mooseError("\"background_region_id\" must be defined if \"background_intervals\" is "
175  "greater than 0");
176  }
177  else
178  {
179  if ((base_pitch * ny > assembly_pitch) || (base_pitch * nx > assembly_pitch))
180  mooseError(
181  "Assembly pitch must be larger than lattice dimension times pin pitch for Cartesian "
182  "assemblies with background region");
183  if (_background_intervals == 0)
184  mooseError("\"background_intervals\" must be greater than 0 if \"background_region_id\" is "
185  "defined");
186  if (_background_region_id.size() != n_axial_levels)
187  mooseError(
188  "The size of background_region_id must be equal to the number of axial levels as "
189  "defined in the ReactorMeshParams object");
190  }
191  }
192  else
193  {
194  if ((_background_region_id.size() == 0) || _background_intervals == 0)
195  mooseError("Hexagonal assemblies must have a background region defined");
196  if (assembly_pitch / std::sin(M_PI / 3.0) < _pattern.size() * base_pitch)
197  mooseError("Hexagonal diameter of assembly must be larger than the number of assembly rows "
198  "times the pin pitch");
199  // Check size of background region id matches number of axial levels
200  if (_background_region_id.size() != n_axial_levels)
201  mooseError("The size of background_region_id must be equal to the number of axial levels as "
202  "defined in the ReactorMeshParams object");
203  }
204 
205  if (_duct_sizes.size() != _duct_intervals.size())
206  mooseError("If ducts are defined then \"duct_intervals\" and \"duct_region_ids\" must also be "
207  "defined and of equal size.");
208 
209  if (_duct_sizes.size() != 0)
210  {
211  // Check size of duct region id matches number of axial levels
212  if (_duct_region_ids.size() != n_axial_levels)
213  mooseError("The size of duct_region_id must be equal to the number of axial levels as "
214  "defined in the ReactorMeshParams object");
215  if (_duct_region_ids[0].size() != _duct_sizes.size())
216  paramError("duct_halfpitch",
217  "If ducts are defined, then \"duct_intervals\" and \"duct_region_ids\" "
218  "must also be defined and of equal size.");
219  }
220 
221  // Check whether block names are defined properly
222  if (isParamValid("background_block_name"))
223  {
224  if (getReactorParam<bool>(RGMB::region_id_as_block_name))
225  paramError("background_block_name",
226  "If ReactorMeshParams/region_id_as_block_name is set, background_block_name "
227  "should not be specified in AssemblyMeshGenerator");
229  _background_block_name = getParam<std::vector<std::string>>("background_block_name");
230  if (_background_region_id.size() != _background_block_name.size())
231  mooseError("The size of background_block_name must match the size of background_region_id");
232  }
233  else
235 
236  if (isParamValid("duct_block_names"))
237  {
238  if (getReactorParam<bool>(RGMB::region_id_as_block_name))
239  paramError("duct_block_names",
240  "If ReactorMeshParams/region_id_as_block_name is set, duct_block_names should not "
241  "be specified in AssemblyMeshGenerator");
242  _has_duct_block_names = true;
243  _duct_block_names = getParam<std::vector<std::vector<std::string>>>("duct_block_names");
244  if (_duct_region_ids.size() != _duct_block_names.size())
245  mooseError("The size of duct_block_names must match the size of duct_region_ids");
246  for (const auto i : index_range(_duct_region_ids))
247  if (_duct_region_ids[i].size() != _duct_block_names[i].size())
248  mooseError("The size of duct_block_names must match the size of duct_region_ids");
249  }
250  else
251  _has_duct_block_names = false;
252 
253  // No subgenerators will be called if option to bypass mesh generators is enabled
254  if (!getReactorParam<bool>(RGMB::bypass_meshgen))
255  {
256  // Declare dependency of inputs to sub generator calls. If mesh generation
257  declareMeshesForSub("inputs");
258 
261 
262  // Call PatternedHexMeshGenerator or PatternedCartesianMeshGenerator to stitch assembly
263  {
264  const auto patterned_mg_name =
265  _geom_type == "Hex" ? "PatternedHexMeshGenerator" : "PatternedCartesianMeshGenerator";
266  auto params = _app.getFactory().getValidParams(patterned_mg_name);
267 
268  if (_geom_type == "Hex")
269  {
270  params.set<Real>("hexagon_size") = getReactorParam<Real>(RGMB::assembly_pitch) / 2.0;
271  params.set<MooseEnum>("hexagon_size_style") = "apothem";
272  }
273  else
274  {
275  if (_background_region_id.size() == 0)
276  params.set<MooseEnum>("pattern_boundary") = "none";
277  else
278  {
279  params.set<MooseEnum>("pattern_boundary") = "expanded";
280  params.set<Real>("square_size") = getReactorParam<Real>(RGMB::assembly_pitch);
281  params.set<bool>("uniform_mesh_on_sides") = true;
282  }
283  }
284 
285  params.set<std::vector<std::string>>("id_name") = {"pin_id"};
286  params.set<std::vector<MooseEnum>>("assign_type") = {
287  MooseEnum("cell", "cell")}; // give elems IDs relative to position in assembly
288  params.set<std::vector<MeshGeneratorName>>("inputs") = _inputs;
289  params.set<std::vector<std::vector<unsigned int>>>("pattern") = _pattern;
290  params.set<bool>("create_outward_interface_boundaries") = false;
291 
292  if (_background_intervals > 0)
293  {
294  params.set<unsigned int>("background_intervals") = _background_intervals;
295  // Initial block id used to define peripheral regions of assembly
296 
297  const auto background_block_name =
298  RGMB::ASSEMBLY_BLOCK_NAME_PREFIX + std::to_string(_assembly_type) + "_R0";
299  const auto background_block_id = RGMB::ASSEMBLY_BLOCK_ID_START;
300  params.set<subdomain_id_type>("background_block_id") = background_block_id;
301  params.set<SubdomainName>("background_block_name") = background_block_name;
302  }
303 
304  if (_duct_sizes.size() > 0)
305  {
306  std::vector<subdomain_id_type> duct_block_ids;
307  std::vector<SubdomainName> duct_block_names;
308  for (const auto duct_it : index_range(_duct_region_ids[0]))
309  {
310  const auto duct_block_name = RGMB::ASSEMBLY_BLOCK_NAME_PREFIX +
311  std::to_string(_assembly_type) + "_R" +
312  std::to_string(duct_it + 1);
313  const auto duct_block_id = RGMB::ASSEMBLY_BLOCK_ID_START + duct_it + 1;
314  duct_block_ids.push_back(duct_block_id);
315  duct_block_names.push_back(duct_block_name);
316  }
317 
318  params.set<std::vector<Real>>("duct_sizes") = _duct_sizes;
319  params.set<std::vector<subdomain_id_type>>("duct_block_ids") = duct_block_ids;
320  params.set<std::vector<SubdomainName>>("duct_block_names") = duct_block_names;
321  params.set<std::vector<unsigned int>>("duct_intervals") = _duct_intervals;
322  }
323 
324  params.set<boundary_id_type>("external_boundary_id") = _assembly_boundary_id;
325  params.set<BoundaryName>("external_boundary_name") = _assembly_boundary_name;
326 
327  addMeshSubgenerator(patterned_mg_name, name() + "_pattern", params);
328 
329  // Pass mesh meta-data defined in subgenerator constructor to this MeshGenerator
330  copyMeshProperty<bool>("is_control_drum_meta", name() + "_pattern");
331  copyMeshProperty<std::vector<Point>>("control_drum_positions", name() + "_pattern");
332  copyMeshProperty<std::vector<Real>>("control_drum_angles", name() + "_pattern");
333  copyMeshProperty<std::vector<std::vector<Real>>>("control_drums_azimuthal_meta",
334  name() + "_pattern");
335  copyMeshProperty<std::string>("position_file_name", name() + "_pattern");
336  copyMeshProperty<Real>("pattern_pitch_meta", name() + "_pattern");
337  }
338 
339  std::string build_mesh_name = name() + "_delbds";
340 
341  // Remove outer pin sidesets created by PolygonConcentricCircleMeshGenerator
342  {
343  // Get outer boundaries of all constituent pins based on pin_type
344  std::vector<BoundaryName> boundaries_to_delete = {};
345  for (const auto & pattern_x : _pattern)
346  {
347  for (const auto & pattern_idx : pattern_x)
348  {
349  const auto pin_name = _inputs[pattern_idx];
350  const auto pin_id = getMeshProperty<subdomain_id_type>(RGMB::pin_type, pin_name);
351  const BoundaryName boundary_name =
352  RGMB::PIN_BOUNDARY_NAME_PREFIX + std::to_string(pin_id);
353  if (!std::count(boundaries_to_delete.begin(), boundaries_to_delete.end(), boundary_name))
354  boundaries_to_delete.push_back(boundary_name);
355  }
356  }
357  auto params = _app.getFactory().getValidParams("BoundaryDeletionGenerator");
358 
359  params.set<MeshGeneratorName>("input") = name() + "_pattern";
360  params.set<std::vector<BoundaryName>>("boundary_names") = boundaries_to_delete;
361 
362  addMeshSubgenerator("BoundaryDeletionGenerator", build_mesh_name, params);
363  }
364 
365  // Modify outermost mesh interval to enable flexible assembly stitching
366  const auto use_flexible_stitching = getReactorParam<bool>(RGMB::flexible_assembly_stitching);
367  if (use_flexible_stitching)
368  {
370  build_mesh_name = name() + "_fpg_delbds";
371  }
372 
373  for (auto pinMG : _inputs)
374  {
375  std::map<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>> region_id_map =
376  getMeshProperty<std::map<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>>(
377  RGMB::pin_region_ids, pinMG);
378  _pin_region_id_map.insert(
379  std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
380  region_id_map.begin()->first, region_id_map.begin()->second));
381  subdomain_id_type pin_type_id = getMeshProperty<subdomain_id_type>(RGMB::pin_type, pinMG);
382  std::vector<std::vector<std::string>> pin_block_names =
383  getMeshProperty<std::vector<std::vector<std::string>>>(RGMB::pin_block_names, pinMG);
384  _pin_block_name_map.insert(
385  std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(pin_type_id,
386  pin_block_names));
387  }
388 
389  if (_extrude && _mesh_dimensions == 3)
390  build_mesh_name = callExtrusionMeshSubgenerators(build_mesh_name);
391 
392  // Store final mesh subgenerator
393  _build_mesh = &getMeshByName(build_mesh_name);
394  }
395  // If mesh generation should be bypassed, call getMeshes to resolve MeshGeneratorSystem
396  // dependencies
397  else
398  auto input_meshes = getMeshes("inputs");
399 
401 }
402 
403 void
405 {
406  // Declare metadata for use in downstream mesh generators
408  declareMeshProperty(RGMB::pitch, getReactorParam<Real>(RGMB::assembly_pitch));
418  // Following metadata is only relevant if an output mesh is generated by RGMB
419  if (!getReactorParam<bool>(RGMB::bypass_meshgen))
420  {
423  }
424 
425  // Determine constituent pin names and define lattice as metadata
426  std::vector<std::vector<int>> pin_name_lattice;
427  std::vector<std::string> input_pin_names;
428  for (const auto i : index_range(_pattern))
429  {
430  std::vector<int> pin_name_idx(_pattern[i].size());
431  for (const auto j : index_range(_pattern[i]))
432  {
433  const auto input_pin_name = _inputs[_pattern[i][j]];
434  const auto it = std::find(input_pin_names.begin(), input_pin_names.end(), input_pin_name);
435  if (it == input_pin_names.end())
436  {
437  pin_name_idx[j] = input_pin_names.size();
438  input_pin_names.push_back(input_pin_name);
439  }
440  else
441  pin_name_idx[j] = it - input_pin_names.begin();
442  }
443  pin_name_lattice.push_back(pin_name_idx);
444  }
445  declareMeshProperty(RGMB::pin_names, input_pin_names);
446  declareMeshProperty(RGMB::pin_lattice, pin_name_lattice);
447 }
448 
449 void
451 {
452  // Assemblies that invoke this method have constituent pin lattice, delete outermost background or
453  // duct region (if present)
454  SubdomainName block_to_delete = "";
455  if (_background_region_id.size() == 0)
456  mooseError("Attempting to use flexible stitching on assembly " + name() +
457  " that does not have a background region. This is not yet supported.");
458  const auto radial_index = _duct_region_ids.size() == 0 ? 0 : _duct_region_ids[0].size();
459  block_to_delete = RGMB::ASSEMBLY_BLOCK_NAME_PREFIX + std::to_string(_assembly_type) + "_R" +
460  std::to_string(radial_index);
461 
462  {
463  // Invoke BlockDeletionGenerator to delete outermost mesh interval of assembly
464  auto params = _app.getFactory().getValidParams("BlockDeletionGenerator");
465 
466  params.set<std::vector<SubdomainName>>("block") = {block_to_delete};
467  params.set<MeshGeneratorName>("input") = name() + "_delbds";
468 
469  addMeshSubgenerator("BlockDeletionGenerator", name() + "_del_outer", params);
470  }
471  {
472  // Invoke FlexiblePatternGenerator to triangulate deleted mesh region
473  auto params = _app.getFactory().getValidParams("FlexiblePatternGenerator");
474 
475  params.set<std::vector<MeshGeneratorName>>("inputs") = {name() + "_del_outer"};
476  params.set<std::vector<libMesh::Point>>("extra_positions") = {libMesh::Point(0, 0, 0)};
477  params.set<std::vector<unsigned int>>("extra_positions_mg_indices") = {0};
478  params.set<bool>("use_auto_area_func") = true;
479  params.set<MooseEnum>("boundary_type") = (_geom_type == "Hex") ? "HEXAGON" : "CARTESIAN";
480  params.set<unsigned int>("boundary_sectors") =
481  getReactorParam<unsigned int>(RGMB::num_sectors_flexible_stitching);
482  params.set<Real>("boundary_size") = getReactorParam<Real>(RGMB::assembly_pitch);
483  params.set<boundary_id_type>("external_boundary_id") = _assembly_boundary_id;
484  params.set<BoundaryName>("external_boundary_name") = _assembly_boundary_name;
485  params.set<SubdomainName>("background_subdomain_name") =
486  block_to_delete + RGMB::TRI_BLOCK_NAME_SUFFIX;
487  params.set<bool>("verify_holes") = false;
488  params.set<unsigned short>("background_subdomain_id") = RGMB::ASSEMBLY_BLOCK_ID_TRI_FLEXIBLE;
489 
490  addMeshSubgenerator("FlexiblePatternGenerator", name() + "_fpg", params);
491  }
492  {
493  // Delete extra boundary created by FlexiblePatternGenerator
494  auto params = _app.getFactory().getValidParams("BoundaryDeletionGenerator");
495 
496  params.set<MeshGeneratorName>("input") = name() + "_fpg";
497  params.set<std::vector<BoundaryName>>("boundary_names") = {std::to_string(1)};
498 
499  addMeshSubgenerator("BoundaryDeletionGenerator", name() + "_fpg_delbds", params);
500  }
501 }
502 
503 std::unique_ptr<MeshBase>
505 {
506  // Must be called to free the ReactorMeshParams mesh
508 
509  // If bypass_mesh is true, return a null mesh. In this mode, an output mesh is not
510  // generated and only metadata is defined on the generator, so logic related to
511  // generation of output mesh will not be called
512  if (getReactorParam<bool>(RGMB::bypass_meshgen))
513  {
514  auto null_mesh = nullptr;
515  return null_mesh;
516  }
517 
518  // Update metadata at this point since values for these metadata only get set by PCCMG
519  // at generate() stage
520  if (hasMeshProperty<Real>("pattern_pitch_meta", name() + "_pattern"))
521  {
522  const auto pattern_pitch_meta =
523  getMeshProperty<Real>("pattern_pitch_meta", name() + "_pattern");
524  setMeshProperty("pattern_pitch_meta", pattern_pitch_meta);
525  }
526 
527  // This generate() method will be called once the subgenerators that we depend on are
528  // called. This is where we reassign subdomain ids/name in case they were merged when
529  // stitching pins into an assembly. This is also where we set region_id and
530  // assembly_type_id element integers.
531 
532  // Define all extra element names and integers
533  std::string plane_id_name = "plane_id";
534  std::string region_id_name = "region_id";
535  std::string pin_type_id_name = "pin_type_id";
536  std::string assembly_type_id_name = "assembly_type_id";
537  std::string radial_id_name = "radial_id";
538  const std::string default_block_name =
540 
541  auto pin_type_id_int = getElemIntegerFromMesh(*(*_build_mesh), pin_type_id_name, true);
542  auto region_id_int = getElemIntegerFromMesh(*(*_build_mesh), region_id_name, true);
543  auto radial_id_int = getElemIntegerFromMesh(*(*_build_mesh), radial_id_name, true);
544 
545  auto assembly_type_id_int = getElemIntegerFromMesh(*(*_build_mesh), assembly_type_id_name);
546 
547  unsigned int plane_id_int = 0;
548  if (_extrude)
549  plane_id_int = getElemIntegerFromMesh(*(*_build_mesh), plane_id_name, true);
550 
551  // Get next free block ID in mesh in case subdomain ids need to be remapped
552  auto next_block_id = MooseMeshUtils::getNextFreeSubdomainID(*(*(_build_mesh)));
553  std::map<std::string, SubdomainID> rgmb_name_id_map;
554 
555  // Loop through all mesh elements and set region ids and reassign block IDs/names
556  // if they were merged during pin stitching
557  for (auto & elem : (*_build_mesh)->active_element_ptr_range())
558  {
559  elem->set_extra_integer(assembly_type_id_int, _assembly_type);
560  const dof_id_type pin_type_id = elem->get_extra_integer(pin_type_id_int);
561  const dof_id_type z_id = _extrude ? elem->get_extra_integer(plane_id_int) : 0;
562 
563  // Element is part of a pin mesh
564  if (_pin_region_id_map.find(pin_type_id) != _pin_region_id_map.end())
565  {
566  // Get region ID from pin_type, z_id, and radial_idx
567  const dof_id_type radial_idx = elem->get_extra_integer(radial_id_int);
568  const auto elem_rid = _pin_region_id_map[pin_type_id][z_id][radial_idx];
569  elem->set_extra_integer(region_id_int, elem_rid);
570 
571  // Set element block name and block id
572  bool has_block_names = !_pin_block_name_map[pin_type_id].empty();
573  auto elem_block_name = default_block_name;
574  if (has_block_names)
575  elem_block_name += "_" + _pin_block_name_map[pin_type_id][z_id][radial_idx];
576  else if (getReactorParam<bool>(RGMB::region_id_as_block_name))
577  elem_block_name += "_REG" + std::to_string(elem_rid);
578  if (elem->type() == TRI3 || elem->type() == PRISM6)
579  elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
581  *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
582  }
583  else
584  {
585  // Assembly peripheral element (background / duct), set subdomains according
586  // to user preferences and set pin type id to RGMB::MAX_PIN_TYPE_ID - peripheral index
587  // Region id is inferred from z_id and peripheral_idx
588  const auto base_block_id = elem->subdomain_id();
589  const auto base_block_name = (*_build_mesh)->subdomain_name(base_block_id);
590 
591  // Check if block name has correct prefix
592  std::string prefix = RGMB::ASSEMBLY_BLOCK_NAME_PREFIX + std::to_string(_assembly_type) + "_R";
593  if (!(base_block_name.find(prefix, 0) == 0))
594  continue;
595  // Peripheral index is integer value of substring after prefix
596  const unsigned int peripheral_idx = std::stoi(base_block_name.substr(prefix.length()));
597 
598  bool is_background_region = peripheral_idx == 0;
599 
601  elem->set_extra_integer(pin_type_id_int, pin_type);
602 
603  const auto elem_rid = (is_background_region ? _background_region_id[z_id]
604  : _duct_region_ids[z_id][peripheral_idx - 1]);
605  elem->set_extra_integer(region_id_int, elem_rid);
606 
607  // Set element block name and block id
608  auto elem_block_name = default_block_name;
609  if (getReactorParam<bool>(RGMB::region_id_as_block_name))
610  elem_block_name += "_REG" + std::to_string(elem_rid);
611  else if (is_background_region && _has_background_block_name)
612  elem_block_name += "_" + _background_block_name[z_id];
613  else if (!is_background_region && _has_duct_block_names)
614  elem_block_name += "_" + _duct_block_names[z_id][peripheral_idx - 1];
615  if (elem->type() == TRI3 || elem->type() == PRISM6)
616  elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
618  *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
619  }
620  }
621 
622  if (getParam<bool>("generate_depletion_id"))
623  {
624  const MooseEnum option = getParam<MooseEnum>("depletion_id_type");
626  }
627 
628  // Mark mesh as not prepared, as block IDs were re-assigned in this method
629  (*_build_mesh)->set_isnt_prepared();
630 
631  return std::move(*_build_mesh);
632 }
registerMooseObject("ReactorApp", AssemblyMeshGenerator)
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
static void addDepletionIDParams(InputParameters &parameters)
const SubdomainName ASSEMBLY_BLOCK_NAME_PREFIX
void updateElementBlockNameId(MeshBase &input_mesh, Elem *elem, std::map< std::string, SubdomainID > &name_id_map, std::string elem_block_name, SubdomainID &next_free_id)
Updates the block names and ids of the element in an input mesh according to a map of block name to b...
bool _has_duct_block_names
Whether block names for assembly duct elements have been provided by user.
static const std::string duct_block_names
static const std::string background_region_id
T & setMeshProperty(const std::string &data_name, Args &&... args)
static const std::string assembly_type
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
const subdomain_id_type ASSEMBLY_BLOCK_ID_START
static const std::string region_id_as_block_name
const unsigned int _background_intervals
The number of divisions in the mesh outside of the pins and inside of the ducts.
static const std::string is_single_pin
const subdomain_id_type _assembly_type
The id number for the type of the assembly.
std::unique_ptr< MeshBase > generate() override
const std::vector< Real > _duct_sizes
The inner apothem of any ducts around the assembly.
unsigned int getElemIntegerFromMesh(MeshBase &input_mesh, std::string extra_int_name, bool should_exist=false)
Initializes extra element integer from id name for a given mesh and throws an error if it should exis...
bool _has_background_block_name
Whether block names for assembly background elements have been provided by user.
T & set(const std::string &name, bool quiet_mode=false)
static const std::string reactor_params_name
static constexpr boundary_id_type ASSEMBLY_BOUNDARY_ID_START
static const std::string mesh_geometry
void initializeReactorMeshParams(const std::string reactor_param_name)
Initializes and checks validity of ReactorMeshParams mesh generator object.
InputParameters getValidParams(const std::string &name) const
std::vector< std::vector< subdomain_id_type > > _duct_region_ids
2-D vector (axial outer indexing, radial inner indexing) used to set the "region_id" extra-element in...
static const std::string background_block_name
std::unique_ptr< MeshBase > * _build_mesh
The final mesh that is generated by the subgenerators; This mesh is generated by the subgenerators wi...
void addDepletionId(MeshBase &input_mesh, const MooseEnum &option, const DepletionIDGenerationLevel generation_level, const bool extrude)
add depletion IDs
static const std::string assembly_pitch
static const std::string pin_type
std::map< subdomain_id_type, std::vector< std::vector< subdomain_id_type > > > _pin_region_id_map
A mapping from pin-type IDs to region IDs used when assigning region IDs during the pin stitching sta...
const SubdomainName TRI_BLOCK_NAME_SUFFIX
virtual const std::string & name() const
Factory & getFactory()
TRI3
static InputParameters validParams()
static const std::string pin_region_id_map
const BoundaryName PIN_BOUNDARY_NAME_PREFIX
bool isParamValid(const std::string &name) const
std::vector< subdomain_id_type > _background_region_id
Vector used to set the "region_id" extra-element integer of the assembly background elements...
static const std::string extruded
const T & getReactorParam(const std::string &param_name)
Returns reference of parameter in ReactorMeshParams object.
static const std::string duct_halfpitches
int8_t boundary_id_type
static const std::string mesh_dimensions
const subdomain_id_type ASSEMBLY_BLOCK_ID_TRI_FLEXIBLE
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
MeshGeneratorName callExtrusionMeshSubgenerators(const MeshGeneratorName input_mesh_name)
Calls mesh subgenerators related to extrusion, renaming of top / bottom boundaries, and defining plane IDs.
static const std::string pitch
const std::vector< unsigned int > _duct_intervals
The number of divisions in the meshes of the ducts.
static const std::string top_boundary_id
std::vector< std::unique_ptr< MeshBase > *> getMeshes(const std::string &param_name)
void paramError(const std::string &param, Args... args) const
std::vector< std::vector< std::string > > _duct_block_names
Optional 2-D vector (axial outer indexing, radial inner indexing) used to set the block names of the ...
static const std::string is_homogenized
static const std::string is_control_drum
unsigned int _mesh_dimensions
The number of dimensions the mesh is ultimately going to have (2 or 3, declared in the ReactorMeshPar...
static const std::string pin_region_ids
static const std::string flexible_assembly_stitching
static const std::string pin_lattice
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MooseApp & _app
const std::vector< std::vector< unsigned int > > _pattern
The 2D pin-by-pin layout of the assembly mapping indices into _inputs.
std::string _geom_type
The type of geometry that is being described (Square or Hex, declared in the ReactorMeshParams object...
static const std::string pin_block_names
AssemblyMeshGenerator(const InputParameters &parameters)
boundary_id_type _assembly_boundary_id
The ID of the assembly outer boundary, equal to the assembly type ID + 2000.
static const std::string axial_mesh_intervals
const std::vector< MeshGeneratorName > _inputs
The names of the pins that compose the Assembly.
A base class that contains common members for Reactor Geometry Mesh Builder mesh generators.
const BoundaryName ASSEMBLY_BOUNDARY_NAME_PREFIX
void mooseError(Args &&... args) const
void freeReactorMeshParams()
Releases the mesh obtained in _reactor_params_mesh.
T & declareMeshProperty(const std::string &data_name, Args &&... args)
std::vector< std::string > _background_block_name
Optional vector used to set the block names of the assembly background elements.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string bypass_meshgen
static const std::string pin_names
PRISM6
std::map< subdomain_id_type, std::vector< std::vector< std::string > > > _pin_block_name_map
A mapping from pin-type IDs to block names used when assigning block names during the pin stitching s...
void declareMeshesForSub(const std::string &param_name)
SubdomainID getNextFreeSubdomainID(MeshBase &input_mesh)
const bool _extrude
Whether this mesh should be extruded to 3-D, making it the final structure in the reactor mesh...
static const std::string num_sectors_flexible_stitching
static const std::string duct_region_ids
BoundaryName _assembly_boundary_name
The name of the assembly outer boundary, equal to the concatenation of "outer_assembly_" and the asse...
void ErrorVector unsigned int
const subdomain_id_type MAX_PIN_TYPE_ID
auto index_range(const T &sizable)
static const std::string bottom_boundary_id
static const std::string pin_block_name_map
uint8_t dof_id_type
Mesh generator for defining a reactor assembly using a Cartesian or hexagonal lattice with the option...