https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CoreMeshGenerator.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 "CoreMeshGenerator.h"
11
12#include "MooseApp.h"
13#include "MooseMeshUtils.h"
14#include "Factory.h"
15#include "libmesh/elem.h"
16#include "CSGZCylinder.h"
17
19
22{
24
25 params.addRequiredParam<std::vector<MeshGeneratorName>>(
26 "inputs",
27 "The AssemblyMeshGenerator and ControlDrumMeshGenerator objects that form the components of "
28 "the assembly.");
29
30 params.addParam<std::string>(
31 "dummy_assembly_name",
32 "dummy",
33 "The place holder name in \"inputs\" that indicates an empty position.");
34
35 params.addRequiredParam<std::vector<std::vector<unsigned int>>>(
36 "pattern",
37 "A double-indexed array starting with the upper-left corner where the index"
38 "represents the layout of input assemblies in the core lattice.");
39 params.addParam<bool>(
40 "mesh_periphery", false, "Determines if the core periphery should be meshed.");
41 MooseEnum periphery_mesher("triangle quad_ring", "triangle");
42 params.addParam<MooseEnum>("periphery_generator",
43 periphery_mesher,
44 "The meshgenerator to use when meshing the core boundary.");
45
46 // Periphery meshing interface
47 params.addRangeCheckedParam<Real>(
48 "outer_circle_radius", 0, "outer_circle_radius>=0", "Radius of outer circle boundary.");
49 params.addRangeCheckedParam<unsigned int>(
50 "outer_circle_num_segments",
51 0,
52 "outer_circle_num_segments>=0",
53 "Number of radial segments to subdivide outer circle boundary.");
54 params.addRangeCheckedParam<unsigned int>(
55 "periphery_num_layers",
56 1,
57 "periphery_num_layers>0",
58 "Number of layers to subdivide the periphery boundary.");
59 params.addParam<std::string>(
60 "periphery_block_name", RGMB::CORE_BLOCK_NAME_PREFIX, "Block name for periphery zone.");
61 params.addParam<subdomain_id_type>(
62 "periphery_region_id",
63 -1,
64 "ID for periphery zone for assignment of region_id extra element id.");
65 params.addRangeCheckedParam<Real>(
66 "desired_area",
67 0,
68 "desired_area>=0",
69 "Desired (maximum) triangle area, or 0 to skip uniform refinement");
70 params.addParam<std::string>(
71 "desired_area_func",
72 std::string(),
73 "Desired (local) triangle area as a function of x,y; omit to skip non-uniform refinement");
74 params.addParam<bool>("assign_control_drum_id",
75 true,
76 "Whether control drum id is assigned to the mesh as an extra integer.");
77 params.addParamNamesToGroup("periphery_block_name periphery_region_id outer_circle_radius "
78 "mesh_periphery periphery_generator",
79 "Periphery Meshing");
80 params.addParamNamesToGroup("outer_circle_num_segments desired_area desired_area_func",
81 "Periphery Meshing: PTMG specific");
82 params.addParamNamesToGroup("periphery_num_layers", "Periphery Meshing: PRMG specific");
83 // end meshing interface
84
85 params.addParam<bool>("extrude",
86 false,
87 "Determines if this is the final step in the geometry construction"
88 " and extrudes the 2D geometry to 3D. If this is true then this mesh "
89 "cannot be used in further mesh building in the Reactor workflow");
90
91 params.addClassDescription(
92 "This CoreMeshGenerator object is designed to generate a core-like "
93 "structure, with IDs, from a reactor geometry. "
94 "The core-like structure consists of a pattern of assembly-like "
95 "structures generated with AssemblyMeshGenerator and/or ControlDrumMeshGenerator "
96 "and is permitted to have \"empty\" locations. The size and spacing "
97 "of the assembly-like structures is defined, and "
98 "enforced by declaration in the ReactorMeshParams.");
99 // depletion id generation params are added
100 addDepletionIDParams(params);
101
102 // Declare that this generator has a generateCSG method
104
105 return params;
106}
107
109 : ReactorGeometryMeshBuilderBase(parameters),
110 _inputs(getParam<std::vector<MeshGeneratorName>>("inputs")),
111 _empty_key(getParam<std::string>("dummy_assembly_name")),
112 _pattern(getParam<std::vector<std::vector<unsigned int>>>("pattern")),
113 _extrude(getParam<bool>("extrude")),
114 _mesh_periphery(getParam<bool>("mesh_periphery")),
115 _periphery_meshgenerator(getParam<MooseEnum>("periphery_generator")),
116 _periphery_region_id(getParam<subdomain_id_type>("periphery_region_id")),
117 _outer_circle_radius(getParam<Real>("outer_circle_radius")),
118 _outer_circle_num_segments(getParam<unsigned int>("outer_circle_num_segments")),
119 _periphery_block_name(getParam<std::string>("periphery_block_name")),
120 _periphery_num_layers(getParam<unsigned int>("periphery_num_layers")),
121 _desired_area(getParam<Real>("desired_area")),
122 _desired_area_func(getParam<std::string>("desired_area_func"))
123{
124 // This sets it so that any mesh that is input with the name _empty_key is considered a "null"
125 // mesh, that is, whenever we try to get it with the standard getMesh() API we get a nullptr
126 // mesh instead. In the specific case of the CoreMeshGenerator, we use said "null" mesh to
127 // represent an empty position
129
130 // periphery meshing input checking
131 if (_mesh_periphery)
132 {
133 // missing required input
134 if (!parameters.isParamSetByUser("outer_circle_radius"))
135 {
136 paramError("outer_circle_radius",
137 "Outer circle radius must be specified when using periphery meshing.");
138 }
139 if (!parameters.isParamSetByUser("periphery_region_id"))
140 {
141 paramError("periphery_region_id",
142 "Periphery region id must be specified when using periphery meshing.");
143 }
144 // using PTMG-specific options with PRMG
145 if (_periphery_meshgenerator == "quad_ring")
146 {
147 if (parameters.isParamSetByUser("outer_circle_num_segments"))
148 {
149 paramError("outer_circle_num_segments",
150 "outer_circle_num_segments cannot be used with PRMG periphery mesher.");
151 }
152 if (parameters.isParamSetByUser("extra_circle_radii"))
153 {
154 paramError("extra_circle_radii",
155 "extra_circle_radii cannot be used with PRMG periphery mesher.");
156 }
157 if (parameters.isParamSetByUser("extra_circle_num_segments"))
158 {
159 paramError("extra_circle_num_segments",
160 "extra_circle_num_segments cannot be used with PRMG periphery mesher.");
161 }
162 }
163 // using PRMG-specific options with PTMG
164 else if (_periphery_meshgenerator == "triangle")
165 {
166 if (parameters.isParamSetByUser("periphery_num_layers"))
167 {
168 paramError("periphery_num_layers",
169 "periphery_num_layers cannot be used with PTMG periphery mesher.");
170 }
171 }
172 else
173 paramError("periphery_generator",
174 "Provided periphery meshgenerator has not been implemented.");
175 }
176
177 MeshGeneratorName first_nondummy_assembly = "";
178 MeshGeneratorName reactor_params = "";
179 bool assembly_homogenization = false;
180 bool pin_as_assembly = false;
181 std::map<subdomain_id_type, std::string> global_pin_map_type_to_name;
182 std::map<subdomain_id_type, std::string> assembly_map_type_to_name;
183 // Check that MG name for reactor params and assembly homogenization schemes are
184 // consistent across all assemblies, and there is no overlap in pin_type / assembly_type ids
185 for (const auto i : index_range(_inputs))
186 {
187 // Skip if assembly name is equal to dummy assembly name
188 if (_inputs[i] == _empty_key)
189 continue;
190
191 // Save properties of first non-dummy assembly to compare to other assemblies
192 if (first_nondummy_assembly == "")
193 {
194 first_nondummy_assembly = MeshGeneratorName(_inputs[i]);
195 reactor_params =
196 MeshGeneratorName(getMeshProperty<std::string>(RGMB::reactor_params_name, _inputs[i]));
197 assembly_homogenization = getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]);
198 pin_as_assembly = getMeshProperty<bool>(RGMB::is_single_pin, _inputs[i]);
199 }
200 if (getMeshProperty<std::string>(RGMB::reactor_params_name, _inputs[i]) != reactor_params)
201 mooseError("The name of all reactor_params objects should be identical across all pins in "
202 "the input assemblies.\n");
203 if ((getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]) != assembly_homogenization) &&
204 !getMeshProperty<bool>(RGMB::flexible_assembly_stitching, reactor_params))
205 mooseError("In order to stitch heterogeneous assemblies with homogeneous assemblies in "
206 "CoreMeshGenerator, ReactorMeshParams/flexible_assembly_stitching should be set "
207 "to true\n");
208
209 // Check assembly_types across constituent assemblies are uniquely defined
210 const auto assembly_type = getMeshProperty<subdomain_id_type>(RGMB::assembly_type, _inputs[i]);
211 if (assembly_map_type_to_name.find(assembly_type) != assembly_map_type_to_name.end() &&
212 assembly_map_type_to_name[assembly_type] != _inputs[i])
214 "Constituent assemblies have shared assembly_type ids but different names. Each uniquely "
215 "defined assembly in AssemblyMeshGenerator must have its own assembly_type id.");
216 assembly_map_type_to_name[assembly_type] = _inputs[i];
217
218 // If assembly is composed of pins, check pin_types across all constituent assemblies are
219 // uniquely defined
220 if (hasMeshProperty<std::vector<std::string>>(RGMB::pin_names, _inputs[i]))
221 {
222 const auto pin_names = getMeshProperty<std::vector<std::string>>(RGMB::pin_names, _inputs[i]);
223 for (const auto & input_pin_name : pin_names)
224 {
225 const auto pin_type = getMeshProperty<subdomain_id_type>(RGMB::pin_type, input_pin_name);
226 if (global_pin_map_type_to_name.find(pin_type) != global_pin_map_type_to_name.end() &&
227 global_pin_map_type_to_name[pin_type] != input_pin_name)
229 "Constituent pins within assemblies have shared pin_type ids but different names. "
230 "Each uniquely defined pin in AssemblyMeshGenerator must have its own pin_type id.");
231 global_pin_map_type_to_name[pin_type] = input_pin_name;
232 }
233 }
234 }
235
236 // Check that there is at least one non-dummy assemby defined in lattice
237 if (first_nondummy_assembly == "")
238 paramError("inputs", "At least one non-dummy assembly must be defined in input assembly names");
239
240 // Initialize ReactorMeshParams object stored in pin input
241 initializeReactorMeshParams(reactor_params);
242
243 _geom_type = getReactorParam<std::string>(RGMB::mesh_geometry);
244 _mesh_dimensions = getReactorParam<unsigned int>(RGMB::mesh_dimensions);
245
246 if (_extrude && _mesh_dimensions != 3)
247 paramError("extrude",
248 "In order to extrude this mesh, ReactorMeshParams/dim needs to be set to 3\n");
249 if (_extrude && (!hasReactorParam<boundary_id_type>(RGMB::top_boundary_id) ||
250 !hasReactorParam<boundary_id_type>(RGMB::bottom_boundary_id)))
251 mooseError("Both top_boundary_id and bottom_boundary_id must be provided in ReactorMeshParams "
252 "if using extruded geometry");
253 if (!hasReactorParam<boundary_id_type>(RGMB::radial_boundary_id))
254 mooseError("radial_boundary_id must be provided in ReactorMeshParams for CoreMeshGenerators");
255
256 if (parameters.isParamSetByUser("periphery_block_name") &&
257 getReactorParam<bool>(RGMB::region_id_as_block_name))
258 paramError("periphery_block_name",
259 "If ReactorMeshParams/region_id_as_block_name is set, periphery_block_name should "
260 "not be specified in CoreMeshGenerator");
261
262 std::size_t empty_pattern_loc = 0;
263 bool make_empty = false;
264 for (auto assembly : _inputs)
265 {
266 if (assembly != _empty_key)
267 {
268 ++empty_pattern_loc;
269 if (getMeshProperty<bool>(RGMB::extruded, assembly))
270 mooseError("Assemblies that have already been extruded cannot be used in CoreMeshGenerator "
271 "definition.\n");
272 }
273 else
274 {
275 // Found dummy assembly in input assembly names
276 make_empty = true;
277 for (const auto i : index_range(_pattern))
278 {
279 for (const auto j : index_range(_pattern[i]))
280 {
281 // Found dummy assembly in input lattice definition
282 if (_pattern[i][j] == empty_pattern_loc)
283 _empty_pos = true;
284 }
285 }
286 }
287 }
288
289 // No subgenerators will be called if option to bypass mesh generators is enabled
290 if (!getReactorParam<bool>(RGMB::bypass_meshgen))
291 {
292 // Check whether flexible stitching should be used for constituent assemblies and throw a
293 // warning if flexible stitching option is not enabled
294 if (!getReactorParam<bool>(RGMB::flexible_assembly_stitching) &&
296 mooseWarning("Constituent assemblies do not share the same number of nodes at the outer "
297 "boundary. In order to ensure that output mesh does not having hanging nodes, a "
298 "flexible stitching approach should be used by setting "
299 "ReactorMeshParams/flexible_assembly_stitching = true.");
300
301 // Declare that all of the meshes in the "inputs" parameter are to be used by
302 // a sub mesh generator.
303 declareMeshesForSub("inputs");
304
305 // Stitch assemblies into a hexagonal / Cartesian core lattice
306 {
307 // create a dummy assembly that is a renamed version of one of the inputs
308 if (make_empty)
309 {
310 {
311 if (assembly_homogenization)
312 {
313 auto params = _app.getFactory().getValidParams("SimpleHexagonGenerator");
314
315 params.set<Real>("hexagon_size") = getReactorParam<Real>(RGMB::assembly_pitch) / 2.0;
316 params.set<std::vector<subdomain_id_type>>("block_id") = {
318
319 addMeshSubgenerator("SimpleHexagonGenerator", std::string(_empty_key), params);
320 }
321 else
322 {
323 const auto adaptive_mg_name =
324 _geom_type == "Hex" ? "HexagonConcentricCircleAdaptiveBoundaryMeshGenerator"
325 : "CartesianConcentricCircleAdaptiveBoundaryMeshGenerator";
326 auto params = _app.getFactory().getValidParams(adaptive_mg_name);
327
328 const auto assembly_pitch = getReactorParam<Real>(RGMB::assembly_pitch);
329 if (_geom_type == "Hex")
330 {
331 params.set<Real>("hexagon_size") = assembly_pitch / 2.0;
332 params.set<std::vector<unsigned int>>("num_sectors_per_side") =
333 std::vector<unsigned int>(6, 2);
334 }
335 else
336 {
337 params.set<Real>("square_size") = assembly_pitch;
338 params.set<std::vector<unsigned int>>("num_sectors_per_side") =
339 std::vector<unsigned int>(4, 2);
340 }
341 params.set<std::vector<unsigned int>>("sides_to_adapt") = std::vector<unsigned int>{0};
342 params.set<std::vector<MeshGeneratorName>>("meshes_to_adapt_to") =
343 std::vector<MeshGeneratorName>{first_nondummy_assembly};
344 params.set<std::vector<subdomain_id_type>>("background_block_ids") =
345 std::vector<subdomain_id_type>{RGMB::DUMMY_ASSEMBLY_BLOCK_ID};
346
347 addMeshSubgenerator(adaptive_mg_name, std::string(_empty_key), params);
348 }
349 }
350 }
351 {
352 const auto patterned_mg_name =
353 _geom_type == "Hex" ? "PatternedHexMeshGenerator" : "PatternedCartesianMeshGenerator";
354 auto params = _app.getFactory().getValidParams(patterned_mg_name);
355
356 params.set<std::vector<std::string>>("id_name") = {"assembly_id"};
357 params.set<std::vector<MooseEnum>>("assign_type") = {
358 MooseEnum("cell", "cell")}; // give elems IDs relative to position in assembly
359 params.set<std::vector<MeshGeneratorName>>("inputs") = _inputs;
360 params.set<std::vector<std::vector<unsigned int>>>("pattern") = _pattern;
361 params.set<MooseEnum>("pattern_boundary") = "none";
362 params.set<bool>("generate_core_metadata") = !pin_as_assembly;
363 params.set<bool>("create_outward_interface_boundaries") = false;
364 params.set<bool>("assign_control_drum_id") = getParam<bool>("assign_control_drum_id");
365 if (make_empty)
366 {
367 params.set<std::vector<MeshGeneratorName>>("exclude_id") =
368 std::vector<MeshGeneratorName>{_empty_key};
369 }
370
371 const auto radial_boundary = getReactorParam<boundary_id_type>(RGMB::radial_boundary_id);
372 params.set<boundary_id_type>("external_boundary_id") = radial_boundary;
373 params.set<BoundaryName>("external_boundary_name") = RGMB::CORE_BOUNDARY_NAME;
374 params.set<double>("rotate_angle") = 0.0;
375 params.set<bool>("allow_unused_inputs") = true;
376
377 addMeshSubgenerator(patterned_mg_name, name() + "_pattern", params);
378 }
379 }
380 if (_empty_pos)
381 {
382 auto params = _app.getFactory().getValidParams("BlockDeletionGenerator");
383
384 params.set<std::vector<SubdomainName>>("block") = {
385 std::to_string(RGMB::DUMMY_ASSEMBLY_BLOCK_ID)};
386 params.set<MeshGeneratorName>("input") = name() + "_pattern";
387 params.set<BoundaryName>("new_boundary") = RGMB::CORE_BOUNDARY_NAME;
388
389 addMeshSubgenerator("BlockDeletionGenerator", name() + "_deleted", params);
390 }
391
392 std::string build_mesh_name;
393
394 // Remove outer assembly sidesets created during assembly generation
395 {
396 // Get outer boundaries of all constituent assemblies based on assembly_type,
397 // skipping all dummy assemblies
398 std::vector<BoundaryName> boundaries_to_delete = {};
399 for (const auto & pattern_x : _pattern)
400 {
401 for (const auto & pattern_idx : pattern_x)
402 {
403 const auto assembly_name = _inputs[pattern_idx];
404 if (assembly_name == _empty_key)
405 continue;
406 const auto assembly_id =
407 getMeshProperty<subdomain_id_type>(RGMB::assembly_type, assembly_name);
408 const BoundaryName boundary_name =
409 RGMB::ASSEMBLY_BOUNDARY_NAME_PREFIX + std::to_string(assembly_id);
410 if (!std::count(boundaries_to_delete.begin(), boundaries_to_delete.end(), boundary_name))
411 boundaries_to_delete.push_back(boundary_name);
412 }
413 }
414 auto params = _app.getFactory().getValidParams("BoundaryDeletionGenerator");
415
416 params.set<MeshGeneratorName>("input") =
417 _empty_pos ? name() + "_deleted" : name() + "_pattern";
418 params.set<std::vector<BoundaryName>>("boundary_names") = boundaries_to_delete;
419
420 build_mesh_name = name() + "_delbds";
421 addMeshSubgenerator("BoundaryDeletionGenerator", build_mesh_name, params);
422 }
423
424 for (auto assembly : _inputs)
425 {
426 if (assembly != _empty_key)
427 {
428 subdomain_id_type assembly_type =
429 getMeshProperty<subdomain_id_type>(RGMB::assembly_type, assembly);
430 if (!getMeshProperty<bool>(RGMB::is_control_drum, assembly))
431 {
432 // For assembly structures, store region ID and block names of assembly regions and
433 // constituent pins
434 const auto & pin_region_id_map = getMeshProperty<
435 std::map<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>>(
436 RGMB::pin_region_id_map, assembly);
437 for (auto pin = pin_region_id_map.begin(); pin != pin_region_id_map.end(); ++pin)
438 _pin_region_id_map.insert(
439 std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
440 pin->first, pin->second));
441
442 const auto & pin_block_name_map =
443 getMeshProperty<std::map<subdomain_id_type, std::vector<std::vector<std::string>>>>(
444 RGMB::pin_block_name_map, assembly);
445 for (auto pin = pin_block_name_map.begin(); pin != pin_block_name_map.end(); ++pin)
446 _pin_block_name_map.insert(
447 std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(pin->first,
448 pin->second));
449
450 // Define background and duct region ID map from constituent assemblies
451 if (_background_region_id_map.find(assembly_type) == _background_region_id_map.end())
452 {
453 // Store region ids and block names associated with duct and background regions for each
454 // assembly, in case block names need to be recovered from region ids after
455 // multiple assemblies have been stitched together into a core
456 std::vector<subdomain_id_type> background_region_ids =
457 getMeshProperty<std::vector<subdomain_id_type>>(RGMB::background_region_id,
458 assembly);
459 std::vector<std::vector<subdomain_id_type>> duct_region_ids =
460 getMeshProperty<std::vector<std::vector<subdomain_id_type>>>(RGMB::duct_region_ids,
461 assembly);
463 std::pair<subdomain_id_type, std::vector<subdomain_id_type>>(
464 assembly_type, background_region_ids));
465 _duct_region_id_map.insert(
466 std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
467 assembly_type, duct_region_ids));
468
469 std::vector<std::string> background_block_names =
470 getMeshProperty<std::vector<std::string>>(RGMB::background_block_name, assembly);
471 std::vector<std::vector<std::string>> duct_block_names =
472 getMeshProperty<std::vector<std::vector<std::string>>>(RGMB::duct_block_names,
473 assembly);
475 std::pair<subdomain_id_type, std::vector<std::string>>(assembly_type,
476 background_block_names));
478 std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(
479 assembly_type, duct_block_names));
480 }
481 }
482 else
483 {
484 // For control drum structures, store region ID and block name information of drum regions
485 const auto & drum_region_ids =
486 getMeshProperty<std::vector<std::vector<subdomain_id_type>>>(RGMB::drum_region_ids,
487 assembly);
488 _drum_region_id_map.insert(
489 std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
490 assembly_type, drum_region_ids));
491 std::vector<std::vector<std::string>> drum_block_names =
492 getMeshProperty<std::vector<std::vector<std::string>>>(RGMB::drum_block_names,
493 assembly);
495 std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(
496 assembly_type, drum_block_names));
497 }
498 }
499 }
500
501 // periphery meshing
502 if (_mesh_periphery)
503 {
504 std::string periphery_mg_name = (_periphery_meshgenerator == "triangle")
505 ? "PeripheralTriangleMeshGenerator"
506 : "PeripheralRingMeshGenerator";
507
508 // set up common options
509 auto params = _app.getFactory().getValidParams(periphery_mg_name);
510 params.set<MeshGeneratorName>("input") = name() + "_delbds";
511 params.set<Real>("peripheral_ring_radius") = _outer_circle_radius;
512 params.set<BoundaryName>("external_boundary_name") = "outside_periphery";
513 params.set<SubdomainName>("peripheral_ring_block_name") = RGMB::PERIPHERAL_RING_BLOCK_NAME;
514
515 // unique MG options
516 if (_periphery_meshgenerator == "triangle")
517 {
518 params.set<unsigned int>("peripheral_ring_num_segments") = _outer_circle_num_segments;
519 params.set<Real>("desired_area") = _desired_area;
520 params.set<std::string>("desired_area_func") = _desired_area_func;
521 }
522 else if (_periphery_meshgenerator == "quad_ring")
523 {
524 params.set<subdomain_id_type>("peripheral_ring_block_id") = RGMB::PERIPHERAL_RING_BLOCK_ID;
525 params.set<BoundaryName>("input_mesh_external_boundary") = RGMB::CORE_BOUNDARY_NAME;
526 params.set<unsigned int>("peripheral_layer_num") = _periphery_num_layers;
527 }
528
529 // finish periphery input
530 build_mesh_name = name() + "_periphery";
531 addMeshSubgenerator(periphery_mg_name, build_mesh_name, params);
532 }
533
534 if (_extrude && _mesh_dimensions == 3)
535 build_mesh_name = callExtrusionMeshSubgenerators(build_mesh_name);
536
537 // Store final mesh subgenerator
538 _build_mesh = &getMeshByName(build_mesh_name);
539 }
540 else
541 {
542 // If mesh generation should be bypassed, call getMeshes to resolve MeshGeneratorSystem
543 // dependencies
544 auto input_meshes = getMeshes("inputs");
545
546 // Since subgenerators are not called, error checking on input parameters needs to happen here
548 paramError("pattern",
549 "Core lattice contains an index that exceeds the number of input assemblies");
550 }
551
552 // If we are in CSG only mode, store the CSGBase objects associated with input MG's
554 _input_csg_bases = getCSGBases("inputs");
555
557}
558
559void
561{
562 // Define metadata related to downstream function calls
563 if (_mesh_periphery)
564 {
567 }
568
569 // Determine constituent pin type ids and define lattice
570 std::vector<std::vector<int>> assembly_name_lattice;
571 std::vector<std::string> input_assembly_names;
572 std::vector<std::string> input_pin_names;
573
574 // Iterate through input assembly names and define constituent assemblies and pins
575 for (const auto i : index_range(_inputs))
576 {
577 const auto input_assembly_name = _inputs[i];
578 if (input_assembly_name != _empty_key)
579 {
580 input_assembly_names.push_back(input_assembly_name);
581 if (!getMeshProperty<bool>(RGMB::is_control_drum, input_assembly_name) &&
582 !getMeshProperty<bool>(RGMB::is_single_pin, input_assembly_name))
583 {
584 const auto pin_names =
585 getMeshProperty<std::vector<std::string>>(RGMB::pin_names, input_assembly_name);
586 for (const auto & pin_name : pin_names)
587 if (std::find(input_pin_names.begin(), input_pin_names.end(), pin_name) ==
588 input_pin_names.end())
589 input_pin_names.push_back(pin_name);
590 }
591 }
592 }
593
594 // Iterate through pattern and remap dummy assemblies with index -1
595 for (const auto i : index_range(_pattern))
596 {
597 std::vector<int> assembly_name_idx(_pattern[i].size());
598 for (const auto j : index_range(_pattern[i]))
599 {
600 const auto input_assembly_name = _inputs[_pattern[i][j]];
601 // Use an assembly type of -1 to represent a dummy assembly
602 if (input_assembly_name == _empty_key)
603 assembly_name_idx[j] = -1;
604 // Set index of assembly name based on `input_assembly_names` variable
605 else
606 {
607 const auto it = std::find(
608 input_assembly_names.begin(), input_assembly_names.end(), input_assembly_name);
609 assembly_name_idx[j] = it - input_assembly_names.begin();
610 }
611 }
612 assembly_name_lattice.push_back(assembly_name_idx);
613 }
614
615 declareMeshProperty(RGMB::pin_names, input_pin_names);
616 declareMeshProperty(RGMB::assembly_names, input_assembly_names);
617 declareMeshProperty(RGMB::assembly_lattice, assembly_name_lattice);
619}
620
621bool
623{
624 MeshGeneratorName first_nondummy_assembly = "";
625 bool assembly_homogenization = false;
626 unsigned int n_constituent_pins = 0;
627 unsigned int n_pin_sectors = 0;
628
629 // Loop through all non-dummy input assemblies. Flexible assembly stitching is needed if one of
630 // the following criteria are met:
631 // 1. The number of constituent pins within the assembly does not match with another assembly
632 // 2. The value of is_single_pin and is_homogenized metadata do not agree with another assembly
633 // 3. The number of sectors of the constituent pins of an assembly do not match with the
634 // constituent pins of another assembly
635 for (const auto i : index_range(_inputs))
636 {
637 // Skip if assembly name is equal to dummy assembly name
638 if (_inputs[i] == _empty_key)
639 continue;
640
641 // Compute total number of constituent pins in assembly, as well as the number of sectors per
642 // side for each pin Note: number of sectors per side is defined uniformly across constituent
643 // pins of an assembly, so only first one needs to be checked
644 unsigned int total_pins = 0;
645 unsigned int pin_sectors_per_side = 0;
646 if (!getMeshProperty<bool>(RGMB::is_single_pin, _inputs[i]))
647 {
648 const auto first_pin_name =
649 getMeshProperty<std::vector<std::string>>(RGMB::pin_names, _inputs[i])[0];
650 pin_sectors_per_side = getMeshProperty<std::vector<unsigned int>>("num_sectors_per_side_meta",
651 first_pin_name + "_2D")[0];
652 const auto pin_lattice =
653 getMeshProperty<std::vector<std::vector<int>>>(RGMB::pin_lattice, _inputs[i]);
654 for (const auto i : index_range(pin_lattice))
655 total_pins += pin_lattice[i].size();
656 }
657 else
658 {
659 if (getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]))
660 {
661 // Homogenized assembly
662 total_pins = 0;
663 pin_sectors_per_side = 0;
664 }
665 else
666 {
667 // Assembly with single constituent pin
668 total_pins = 1;
669 pin_sectors_per_side = getMeshProperty<std::vector<unsigned int>>(
670 "num_sectors_per_side_meta", _inputs[i] + "_2D")[0];
671 }
672 }
673
674 if (first_nondummy_assembly == "")
675 {
676 first_nondummy_assembly = MeshGeneratorName(_inputs[i]);
677 assembly_homogenization = getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]);
678 n_constituent_pins = total_pins;
679 n_pin_sectors = pin_sectors_per_side;
680 }
681 else
682 {
683 if (getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]) != assembly_homogenization)
684 {
685 mooseWarning("Detected mix of homogenized and heterogeneous assemblies between " +
686 first_nondummy_assembly + " and " + _inputs[i]);
687 return true;
688 }
689 if (total_pins != n_constituent_pins)
690 {
692 "Detected assemblies with different number of total constituent pins between " +
693 first_nondummy_assembly + " and " + _inputs[i]);
694 return true;
695 }
696 if (pin_sectors_per_side != n_pin_sectors)
697 {
698 mooseWarning("Constituent pins in " + first_nondummy_assembly + " and " + _inputs[i] +
699 " differ in terms of number of sectors per side");
700 return true;
701 }
702 }
703 }
704 return false;
705}
706
707std::unique_ptr<MeshBase>
709{
710 // Must be called to free the ReactorMeshParams mesh
712
713 // If bypass_mesh is true, return a null mesh. In this mode, an output mesh is not
714 // generated and only metadata is defined on the generator, so logic related to
715 // generation of output mesh will not be called
716 if (getReactorParam<bool>(RGMB::bypass_meshgen))
717 {
718 auto null_mesh = nullptr;
719 return null_mesh;
720 }
721 // This generate() method will be called once the subgenerators that we depend on are
722 // called. This is where we reassign subdomain ids/names in case they were merged
723 // when stitching assemblies into the core. This is also where we set region_id extra
724 // element integers, which has not been set yet for extruded geometries
725
726 // Define all extra element names and integers
727 std::string pin_type_id_name = "pin_type_id";
728 std::string assembly_type_id_name = "assembly_type_id";
729 std::string plane_id_name = "plane_id";
730 std::string region_id_name = "region_id";
731 std::string radial_id_name = "radial_id";
732 const std::string default_block_name = RGMB::CORE_BLOCK_NAME_PREFIX;
733
734 auto pin_type_id_int = getElemIntegerFromMesh(*(*_build_mesh), pin_type_id_name, true);
735 auto assembly_type_id_int = getElemIntegerFromMesh(*(*_build_mesh), assembly_type_id_name, true);
736 auto radial_id_int = getElemIntegerFromMesh(*(*_build_mesh), radial_id_name, true);
737 auto region_id_int = getElemIntegerFromMesh(*(*_build_mesh), region_id_name, true);
738 unsigned int plane_id_int = 0;
739 if (_extrude)
740 plane_id_int = getElemIntegerFromMesh(*(*_build_mesh), plane_id_name, true);
741
742 // Get next free block ID in mesh in case subdomain ids need to be remapped
743 auto next_block_id = MooseMeshUtils::getNextFreeSubdomainID(*(*(_build_mesh)));
744 std::map<std::string, SubdomainID> rgmb_name_id_map;
745
746 // Loop through all mesh elements and set region ids and reassign block IDs/names
747 // if they were merged during assembly stitching
748 for (auto & elem : (*_build_mesh)->active_element_ptr_range())
749 {
750 dof_id_type z_id = _extrude ? elem->get_extra_integer(plane_id_int) : 0;
751 dof_id_type pin_type_id = elem->get_extra_integer(pin_type_id_int);
752
753 if (_pin_region_id_map.find(pin_type_id) != _pin_region_id_map.end())
754 {
755 // Pin type element, get region ID from pin_type, z_id, and radial_idx
756 const dof_id_type radial_idx = elem->get_extra_integer(radial_id_int);
757 const auto elem_rid = _pin_region_id_map[pin_type_id][z_id][radial_idx];
758 elem->set_extra_integer(region_id_int, elem_rid);
759
760 // Set element block name and block id
761 bool has_block_names = !_pin_block_name_map[pin_type_id].empty();
762 auto elem_block_name = default_block_name;
763 if (has_block_names)
764 elem_block_name += "_" + _pin_block_name_map[pin_type_id][z_id][radial_idx];
765 else if (getReactorParam<bool>(RGMB::region_id_as_block_name))
766 elem_block_name += "_REG" + std::to_string(elem_rid);
767 if (elem->type() == TRI3 || elem->type() == PRISM6)
768 elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
770 *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
771 }
772 else if ((*_build_mesh)->subdomain_name(elem->subdomain_id()) ==
774 // periphery type element
775 {
776 // set region ID of core periphery element
777 elem->set_extra_integer(region_id_int, _periphery_region_id);
778 // set block name and block name of core periphery element
779 auto elem_block_name = _periphery_block_name;
780 if (getReactorParam<bool>(RGMB::region_id_as_block_name))
781 elem_block_name += "_REG" + std::to_string(_periphery_region_id);
782 if (elem->type() == TRI3 || elem->type() == PRISM6)
783 elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
785 *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
786 }
787 else
788 {
789 dof_id_type assembly_type_id = elem->get_extra_integer(assembly_type_id_int);
790 // Infer peripheral index of assembly background, assembly duct, or control drum regions from
791 // pin_type_id
792 unsigned int peripheral_idx = RGMB::MAX_PIN_TYPE_ID - pin_type_id;
793
794 // check if element is part of drum region
795 if (_drum_region_id_map.find(assembly_type_id) != _drum_region_id_map.end())
796 {
797 // Element is in a control drum region. Infer region id from assembly_type_id, z_id, and
798 // peripheral_index
799 const auto elem_rid = _drum_region_id_map[assembly_type_id][z_id][peripheral_idx];
800 elem->set_extra_integer(region_id_int, elem_rid);
801
802 // Set element block name and block id
803 auto elem_block_name = default_block_name;
804 if (getReactorParam<bool>(RGMB::region_id_as_block_name))
805 elem_block_name += "_REG" + std::to_string(elem_rid);
806 else
807 {
808 bool has_drum_block_name = !_drum_block_name_map[assembly_type_id].empty();
809 if (has_drum_block_name)
810 elem_block_name += "_" + _drum_block_name_map[assembly_type_id][z_id][peripheral_idx];
811 }
812 if (elem->type() == TRI3 || elem->type() == PRISM6)
813 elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
815 *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
816 }
817 else
818 {
819 // Element is in an assembly duct or background region since it doesn't
820 // have an assembly type id in the drum region map. Infer region id from
821 // assembly_type_id, z_id, and peripheral_index
822 bool is_background_region = peripheral_idx == 0;
823 const auto elem_rid =
824 (is_background_region
825 ? _background_region_id_map[assembly_type_id][z_id]
826 : _duct_region_id_map[assembly_type_id][z_id][peripheral_idx - 1]);
827 elem->set_extra_integer(region_id_int, elem_rid);
828
829 // Set element block name and block id
830 auto elem_block_name = default_block_name;
831 if (getReactorParam<bool>(RGMB::region_id_as_block_name))
832 elem_block_name += "_REG" + std::to_string(elem_rid);
833 else
834 {
835 if (is_background_region)
836 {
837 bool has_background_block_name = !_background_block_name_map[assembly_type_id].empty();
838 if (has_background_block_name)
839 elem_block_name += "_" + _background_block_name_map[assembly_type_id][z_id];
840 }
841 else
842 {
843 bool has_duct_block_names = !_duct_block_name_map[assembly_type_id].empty();
844 if (has_duct_block_names)
845 elem_block_name +=
846 "_" + _duct_block_name_map[assembly_type_id][z_id][peripheral_idx - 1];
847 }
848 }
849 if (elem->type() == TRI3 || elem->type() == PRISM6)
850 elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
852 *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
853 }
854 }
855 }
856
857 // Sideset 10000 does not get stitched properly when BlockDeletionGenerator
858 // is used for deleting dummy assemblies. This block copies missing sides
859 // into sideset 10000 from sideset RGMB::CORE_BOUNDARY_NAME
860 BoundaryInfo & boundary_info = (*_build_mesh)->get_boundary_info();
861 boundary_id_type source_id =
863 boundary_id_type target_id = 10000;
864 const auto sideset_map = boundary_info.get_sideset_map();
865
866 for (const auto & [elem, id_pair] : sideset_map)
867 {
868 const auto side_id = id_pair.first;
869 const auto sideset_id = id_pair.second;
870
871 // Filter all sides that belong to RGMB::CORE_BOUNDARY_NAME sideset
872 if (sideset_id == source_id)
873 {
874 auto mm_it = sideset_map.equal_range(elem);
875 bool found = false;
876 // Check if side is defined in sideset 10000
877 for (auto it = mm_it.first; it != mm_it.second; it++)
878 {
879 if (it->second.first == side_id && it->second.second == target_id)
880 found = true;
881 }
882 // Add side if not found in sideset 10000
883 if (!found)
884 boundary_info.add_side(elem, side_id, target_id);
885 }
886 }
887
888 if (getParam<bool>("generate_depletion_id"))
889 {
890 const MooseEnum option = getParam<MooseEnum>("depletion_id_type");
892 }
893
894 // Mark mesh as not prepared, as block ID's were re-assigned in this method
895 (*_build_mesh)->unset_is_prepared();
896
897 return std::move(*_build_mesh);
898}
899
900std::unique_ptr<CSG::CSGBase>
902{
903 // Must be called to free the ReactorMeshParams CSGBase object
905
906 auto csg_obj = std::make_unique<CSG::CSGBase>();
907
908 const auto dummy_univ_name = _empty_key + "_univ";
910 {
911 // Create universe with a single void cell with an empty region. This universe is used for
912 // defining dummy assemblies in the core lattice and the lattce outer universe for lattices
913 // that do not have a mesh periphery
914 const auto dummy_cell_name = _empty_key + "_cell";
915 const auto & dummy_univ = csg_obj->createUniverse(dummy_univ_name);
916 CSG::CSGRegion empty_region;
917 csg_obj->createCell(dummy_cell_name, empty_region, &dummy_univ);
918 }
919
920 // Combine all bases from AssemblyMG inputs into this base. We expect each AssemblyMG
921 // input to contain a root universe with a single cell that constrains the assembly based
922 // on the FEM boundary. Root universes from inputs are renamed to a new universe name.
923 // These universes and their cells will be discarded, so that only the infinite assembly
924 // universes are retained.
925 std::unordered_map<unsigned int, std::string> univ_id_names;
926 for (const auto i : index_range(_inputs))
927 {
928 if (_inputs[i] == _empty_key)
929 univ_id_names[i] = dummy_univ_name;
930 else
931 {
932 const auto input_univ_name_discard = _inputs[i] + "_root_univ";
933 csg_obj->joinOtherBase(std::move(*_input_csg_bases[i]), true, input_univ_name_discard);
934
935 const auto & universe_to_delete = csg_obj->getUniverseByName(input_univ_name_discard);
936 const auto cells_to_delete = universe_to_delete.getAllCells();
937 csg_obj->deleteUniverse(universe_to_delete);
938
939 // Store universe fill of cell that will be deleted. This will be the universe
940 // that gets populated into the assembly lattice
941 for (const auto & cell : cells_to_delete)
942 {
943 const auto & cell_to_delete = cell.get();
944 const auto & fill_univ_name = cell_to_delete.getFillUniverse().getName();
945 // Store surfaces use to define cell region. The radial surfaces will be deleted
946 // as they are no longer used in CSGBase instance after cell deletion.
947 const auto & surfs_to_delete = cell_to_delete.getRegion().getSurfaces();
948 csg_obj->deleteCell(cell_to_delete);
949 univ_id_names[i] = fill_univ_name;
950 for (const auto & surf : surfs_to_delete)
951 // Only delete those surfaces that aren't used as axial planes
952 if (surf.get().getName().find(RGMB::CSG_AXIAL_PLANE_PREFIX) == std::string::npos)
953 csg_obj->deleteSurface(surf);
954 }
955 }
956 }
957
958 // Build the universe pattern for the assembly lattice from the input pattern
959 std::vector<std::vector<std::reference_wrapper<const CSG::CSGUniverse>>> universe_pattern;
960 for (const auto & row : _pattern)
961 {
962 std::vector<std::reference_wrapper<const CSG::CSGUniverse>> universe_row;
963 for (const auto & univ_id : row)
964 {
965 const auto & lattice_univ = csg_obj->getUniverseByName(univ_id_names[univ_id]);
966 universe_row.push_back(lattice_univ);
967 }
968 universe_pattern.push_back(universe_row);
969 }
970
971 const auto assembly_pitch = getReactorParam<Real>(RGMB::assembly_pitch);
972 auto & core_lattice = createRGMBLattice(assembly_pitch, universe_pattern, *csg_obj);
973
974 // Define universe that fills region outside of lattice. For an explicity
975 // defined outer ring, this is a material outer corresponding to the region ID
976 // of the ring region. Otherwise, the outer is defined as a universe containing a void cell
977 if (_mesh_periphery)
978 {
979 std::string region_name = "rgmb_region_" + std::to_string(_periphery_region_id);
980 csg_obj->setLatticeOuter(core_lattice, region_name);
981 }
982 else
983 {
984 const auto & outer_univ = csg_obj->getUniverseByName(dummy_univ_name);
985 csg_obj->setLatticeOuter(core_lattice, outer_univ);
986 }
987
988 // Define lattice cell, with the lattice surrounded by a bounding circle whose radius is
989 // determined by the mesh periphery radius. If no mesh periphery is defined, the radius will be (N
990 // + 1) times the assembly pitch of the lattice for hex lattices, where N is the number of rings
991 // for a hexagonal lattice. For Cartesian lattices, the radius will be (N / 2 * sqrt(2)) times the
992 // assembly pitch, where N is the number of assembly widths that span a square lattice. This
993 // ensures that the ring radius completely surrounds the underlying lattice.
994 std::string lat_cell_name = name() + "_lattice_cell";
995 const auto ring_radius = _mesh_periphery ? _outer_circle_radius
996 : (_geom_type == "Hex")
997 ? (universe_pattern.size() + 2) / 2. * assembly_pitch
998 : universe_pattern.size() / 2. * sqrt(2.) * assembly_pitch;
999 const auto ring_surf_name = name() + "_radial_boundary";
1000 std::unique_ptr<CSG::CSGSurface> ring_surf_ptr =
1001 std::make_unique<CSG::CSGZCylinder>(ring_surf_name, 0, 0, ring_radius);
1002 const auto & ring_surf = csg_obj->addSurface(std::move(ring_surf_ptr));
1003 auto lat_cell_region = -ring_surf;
1004
1005 if (_mesh_dimensions == 3)
1006 {
1007 const auto surfaces_by_axial_region = getAxialPlaneSurfaces(*csg_obj, true);
1008 const auto & lowest_axial_surf = surfaces_by_axial_region.front().get();
1009 const auto & highest_axial_surf = surfaces_by_axial_region.back().get();
1010 lat_cell_region = lat_cell_region & +lowest_axial_surf & -highest_axial_surf;
1011 }
1012 csg_obj->createCell(lat_cell_name, core_lattice, lat_cell_region);
1013
1014 return csg_obj;
1015}
registerMooseObject("ReactorApp", CoreMeshGenerator)
void ErrorVector unsigned int
Mesh generator for defining a reactor core using a Cartesian or hexagonal lattice with the option to ...
unsigned int _mesh_dimensions
The number of dimensions the mesh is ultimately going to have (2 or 3, declared in the ReactorMeshPar...
const unsigned int _outer_circle_num_segments
Number of segments in the outer circle boundary.
bool _empty_pos
Whether empty positions are to be used in the pattern.
std::map< subdomain_id_type, std::vector< std::string > > _background_block_name_map
A mapping from assembly-type IDs to block names in the assembly background regions used when assignin...
CoreMeshGenerator(const InputParameters &parameters)
std::map< subdomain_id_type, std::vector< std::vector< std::string > > > _drum_block_name_map
A mapping from assembly-type IDs to block names in the drum regions used when assigning block names d...
const unsigned int _periphery_num_layers
Number of periphery layers.
const std::string _periphery_block_name
The subdomain name for the generated mesh outer boundary.
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 assembly stitch...
std::string _geom_type
The geometry type for the reactor that is stored on the ReactorMeshParams object.
const bool _mesh_periphery
Whether the core periphery should be meshed.
std::unique_ptr< MeshBase > * _build_mesh
The final mesh that is generated by the subgenerators; This mesh is generated by the subgenerators wi...
bool constituentAssembliesNeedFlexibleStiching()
std::map< subdomain_id_type, std::vector< subdomain_id_type > > _background_region_id_map
A mapping from assembly-type IDs to region IDs in the assembly background regions used when assigning...
const bool _extrude
Whether this mesh should be extruded to 3-D, the core is always assumed to be the last.
const Real _outer_circle_radius
outer circle boundary radius
std::unique_ptr< CSG::CSGBase > generateCSG() override
static InputParameters validParams()
const Real _desired_area
Desired (maximum) triangle area.
const std::vector< MeshGeneratorName > _inputs
The names of the assemblies that compose the core.
const std::vector< std::vector< unsigned int > > _pattern
The 2D assembly layout of the core.
std::vector< std::unique_ptr< CSG::CSGBase > * > _input_csg_bases
List of pointers to all CSG bases created by input mesh generators.
const subdomain_id_type _periphery_region_id
"region_id" extra-element integer of the periphery mesh elements
std::map< subdomain_id_type, std::vector< std::vector< subdomain_id_type > > > _drum_region_id_map
A mapping from assembly-type IDs to region IDs in the drum regions used when assigning region IDs dur...
std::map< subdomain_id_type, std::vector< std::vector< std::string > > > _duct_block_name_map
A mapping from assembly-type IDs to block names in the assembly duct regions used when assigning bloc...
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 assembly stitchin...
std::string _desired_area_func
Desired (local) triangle area as a function of (x,y)
const MeshGeneratorName _empty_key
The name of "filler" assembly given in the input to represent an empty space in the core pattern.
const MooseEnum _periphery_meshgenerator
Which periphery meshgenerator to use.
std::unique_ptr< MeshBase > generate() override
std::map< subdomain_id_type, std::vector< std::vector< subdomain_id_type > > > _duct_region_id_map
A mapping from assembly-type IDs to region IDs in the assembly duct regions used when assigning regio...
InputParameters getValidParams(const std::string &name) const
bool isParamSetByUser(const std::string &name) const
T & set(const std::string &name, bool quiet_mode=false)
bool getCSGOnly() const
std::vector< std::unique_ptr< MeshBase > * > getMeshes(const std::string &param_name)
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
static void setHasGenerateCSG(InputParameters &params)
std::vector< std::unique_ptr< CSG::CSGBase > * > getCSGBases(const std::string &param_name)
void declareMeshesForSub(const std::string &param_name)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
void declareNullMeshName(const MeshGeneratorName &name)
bool hasMeshProperty(const std::string &data_name, const std::string &prefix) const
const T & getMeshProperty(const std::string &data_name, const std::string &prefix)
Factory & getFactory()
MeshGeneratorSystem & getMeshGeneratorSystem()
const InputParameters & parameters() const
const std::string & name() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
MooseApp & _app
A base class that contains common members for Reactor Geometry Mesh Builder mesh generators.
void initializeReactorMeshParams(const std::string reactor_param_name)
Initializes and checks validity of ReactorMeshParams mesh generator object.
std::vector< std::reference_wrapper< const CSG::CSGSurface > > getAxialPlaneSurfaces(CSG::CSGBase &csg_obj, const bool skip_intermediate_plane_generation)
Get CSGSurfaces corresponding to axial planes of the extruded RGMB mesh.
static void addDepletionIDParams(InputParameters &parameters)
MeshGeneratorName callExtrusionMeshSubgenerators(const MeshGeneratorName input_mesh_name)
Calls mesh subgenerators related to extrusion, renaming of top / bottom boundaries,...
void freeReactorParamsMesh()
Releases the mesh obtained in _reactor_params_mesh.
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...
void addDepletionId(MeshBase &input_mesh, const MooseEnum &option, const DepletionIDGenerationLevel generation_level, const bool extrude)
add depletion IDs
const CSG::CSGLattice & createRGMBLattice(const Real pitch, const std::vector< std::vector< std::reference_wrapper< const CSG::CSGUniverse > > > pattern, CSG::CSGBase &csg_obj)
Create CSG lattice for assembly and core lattices.
void freeReactorParamsCSG()
Releases the CSG base object obtained in _reactor_params_csg.
bool checkUndefinedLatticeRefs(const std::vector< std::vector< unsigned int > > &input_lattice, unsigned int num_inputs)
Check if input lattice has values that are less than the number of input elements in lattice.
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...
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
SubdomainID getNextFreeSubdomainID(MeshBase &input_mesh)
const subdomain_id_type PERIPHERAL_RING_BLOCK_ID
static const std::string peripheral_ring_radius
const subdomain_id_type MAX_PIN_TYPE_ID
static const std::string bottom_boundary_id
static const std::string is_single_pin
static const std::string pin_region_id_map
static const std::string pin_lattice
static const std::string peripheral_ring_region_id
static const std::string radial_boundary_id
const SubdomainName CORE_BLOCK_NAME_PREFIX
static const std::string is_control_drum
static const std::string bypass_meshgen
const subdomain_id_type DUMMY_ASSEMBLY_BLOCK_ID
static const std::string assembly_names
static const std::string top_boundary_id
static const std::string drum_region_ids
static const std::string assembly_type
static const std::string pin_block_name_map
const SubdomainName PERIPHERAL_RING_BLOCK_NAME
static const std::string duct_block_names
const SubdomainName TRI_BLOCK_NAME_SUFFIX
const BoundaryName ASSEMBLY_BOUNDARY_NAME_PREFIX
static const std::string assembly_pitch
static const std::string mesh_dimensions
static const std::string duct_region_ids
const BoundaryName CORE_BOUNDARY_NAME
static const std::string extruded
static const std::string background_region_id
static const std::string assembly_lattice
static const std::string flexible_assembly_stitching
static const std::string is_homogenized
static const std::string drum_block_names
static const std::string CSG_AXIAL_PLANE_PREFIX
static const std::string region_id_as_block_name
static const std::string background_block_name
static const std::string reactor_params_name
static const std::string pin_names
static const std::string mesh_geometry
static const std::string pin_type
const boundary_id_type side_id