LCOV - code coverage report
Current view: top level - src/meshgenerators - CoreMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose reactor: #31405 (292dce) with base fef103 Lines: 362 390 92.8 %
Date: 2025-09-04 07:56:24 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      17             : registerMooseObject("ReactorApp", CoreMeshGenerator);
      18             : 
      19             : InputParameters
      20         524 : CoreMeshGenerator::validParams()
      21             : {
      22         524 :   auto params = ReactorGeometryMeshBuilderBase::validParams();
      23             : 
      24        1048 :   params.addRequiredParam<std::vector<MeshGeneratorName>>(
      25             :       "inputs",
      26             :       "The AssemblyMeshGenerator and ControlDrumMeshGenerator objects that form the components of "
      27             :       "the assembly.");
      28             : 
      29        1048 :   params.addParam<std::string>(
      30             :       "dummy_assembly_name",
      31             :       "dummy",
      32             :       "The place holder name in \"inputs\" that indicates an empty position.");
      33             : 
      34        1048 :   params.addRequiredParam<std::vector<std::vector<unsigned int>>>(
      35             :       "pattern",
      36             :       "A double-indexed array starting with the upper-left corner where the index"
      37             :       "represents the layout of input assemblies in the core lattice.");
      38        1048 :   params.addParam<bool>(
      39        1048 :       "mesh_periphery", false, "Determines if the core periphery should be meshed.");
      40        1048 :   MooseEnum periphery_mesher("triangle quad_ring", "triangle");
      41        1048 :   params.addParam<MooseEnum>("periphery_generator",
      42             :                              periphery_mesher,
      43             :                              "The meshgenerator to use when meshing the core boundary.");
      44             : 
      45             :   // Periphery meshing interface
      46        1048 :   params.addRangeCheckedParam<Real>(
      47             :       "outer_circle_radius", 0, "outer_circle_radius>=0", "Radius of outer circle boundary.");
      48        1572 :   params.addRangeCheckedParam<unsigned int>(
      49             :       "outer_circle_num_segments",
      50        1048 :       0,
      51             :       "outer_circle_num_segments>=0",
      52             :       "Number of radial segments to subdivide outer circle boundary.");
      53        1572 :   params.addRangeCheckedParam<unsigned int>(
      54             :       "periphery_num_layers",
      55        1048 :       1,
      56             :       "periphery_num_layers>0",
      57             :       "Number of layers to subdivide the periphery boundary.");
      58        1048 :   params.addParam<std::string>(
      59             :       "periphery_block_name", RGMB::CORE_BLOCK_NAME_PREFIX, "Block name for periphery zone.");
      60        1048 :   params.addParam<subdomain_id_type>(
      61             :       "periphery_region_id",
      62        1048 :       -1,
      63             :       "ID for periphery zone for assignment of region_id extra element id.");
      64        1048 :   params.addRangeCheckedParam<Real>(
      65             :       "desired_area",
      66             :       0,
      67             :       "desired_area>=0",
      68             :       "Desired (maximum) triangle area, or 0 to skip uniform refinement");
      69        1048 :   params.addParam<std::string>(
      70             :       "desired_area_func",
      71         524 :       std::string(),
      72             :       "Desired (local) triangle area as a function of x,y; omit to skip non-uniform refinement");
      73        1048 :   params.addParam<bool>("assign_control_drum_id",
      74        1048 :                         true,
      75             :                         "Whether control drum id is assigned to the mesh as an extra integer.");
      76        1048 :   params.addParamNamesToGroup("periphery_block_name periphery_region_id outer_circle_radius "
      77             :                               "mesh_periphery periphery_generator",
      78             :                               "Periphery Meshing");
      79        1048 :   params.addParamNamesToGroup("outer_circle_num_segments desired_area desired_area_func",
      80             :                               "Periphery Meshing: PTMG specific");
      81        1048 :   params.addParamNamesToGroup("periphery_num_layers", "Periphery Meshing: PRMG specific");
      82             :   // end meshing interface
      83             : 
      84        1048 :   params.addParam<bool>("extrude",
      85        1048 :                         false,
      86             :                         "Determines if this is the final step in the geometry construction"
      87             :                         " and extrudes the 2D geometry to 3D. If this is true then this mesh "
      88             :                         "cannot be used in further mesh building in the Reactor workflow");
      89             : 
      90         524 :   params.addClassDescription(
      91             :       "This CoreMeshGenerator object is designed to generate a core-like "
      92             :       "structure, with IDs, from a reactor geometry. "
      93             :       "The core-like structure consists of a pattern of assembly-like "
      94             :       "structures generated with AssemblyMeshGenerator and/or ControlDrumMeshGenerator "
      95             :       "and is permitted to have \"empty\" locations. The size and spacing "
      96             :       "of the assembly-like structures is defined, and "
      97             :       "enforced by declaration in the ReactorMeshParams.");
      98             :   // depletion id generation params are added
      99         524 :   addDepletionIDParams(params);
     100             : 
     101         524 :   return params;
     102         524 : }
     103             : 
     104         266 : CoreMeshGenerator::CoreMeshGenerator(const InputParameters & parameters)
     105             :   : ReactorGeometryMeshBuilderBase(parameters),
     106         266 :     _inputs(getParam<std::vector<MeshGeneratorName>>("inputs")),
     107         266 :     _empty_key(getParam<std::string>("dummy_assembly_name")),
     108         266 :     _pattern(getParam<std::vector<std::vector<unsigned int>>>("pattern")),
     109         532 :     _extrude(getParam<bool>("extrude")),
     110         532 :     _mesh_periphery(getParam<bool>("mesh_periphery")),
     111         532 :     _periphery_meshgenerator(getParam<MooseEnum>("periphery_generator")),
     112         532 :     _periphery_region_id(getParam<subdomain_id_type>("periphery_region_id")),
     113         532 :     _outer_circle_radius(getParam<Real>("outer_circle_radius")),
     114         532 :     _outer_circle_num_segments(getParam<unsigned int>("outer_circle_num_segments")),
     115         532 :     _periphery_block_name(getParam<std::string>("periphery_block_name")),
     116         532 :     _periphery_num_layers(getParam<unsigned int>("periphery_num_layers")),
     117         532 :     _desired_area(getParam<Real>("desired_area")),
     118        1330 :     _desired_area_func(getParam<std::string>("desired_area_func"))
     119             : {
     120             :   // This sets it so that any mesh that is input with the name _empty_key is considered a "null"
     121             :   // mesh, that is, whenever we try to get it with the standard getMesh() API we get a nullptr
     122             :   // mesh instead. In the specific case of the CoreMeshGenerator, we use said "null" mesh to
     123             :   // represent an empty position
     124         266 :   declareNullMeshName(_empty_key);
     125             : 
     126             :   // periphery meshing input checking
     127         266 :   if (_mesh_periphery)
     128             :   {
     129             :     // missing required input
     130         112 :     if (!parameters.isParamSetByUser("outer_circle_radius"))
     131             :     {
     132           0 :       paramError("outer_circle_radius",
     133             :                  "Outer circle radius must be specified when using periphery meshing.");
     134             :     }
     135         112 :     if (!parameters.isParamSetByUser("periphery_region_id"))
     136             :     {
     137           0 :       paramError("periphery_region_id",
     138             :                  "Periphery region id must be specified when using periphery meshing.");
     139             :     }
     140             :     // using PTMG-specific options with PRMG
     141          56 :     if (_periphery_meshgenerator == "quad_ring")
     142             :     {
     143          90 :       if (parameters.isParamSetByUser("outer_circle_num_segments"))
     144             :       {
     145           0 :         paramError("outer_circle_num_segments",
     146             :                    "outer_circle_num_segments cannot be used with PRMG periphery mesher.");
     147             :       }
     148          90 :       if (parameters.isParamSetByUser("extra_circle_radii"))
     149             :       {
     150           0 :         paramError("extra_circle_radii",
     151             :                    "extra_circle_radii cannot be used with PRMG periphery mesher.");
     152             :       }
     153          90 :       if (parameters.isParamSetByUser("extra_circle_num_segments"))
     154             :       {
     155           0 :         paramError("extra_circle_num_segments",
     156             :                    "extra_circle_num_segments cannot be used with PRMG periphery mesher.");
     157             :       }
     158             :     }
     159             :     // using PRMG-specific options with PTMG
     160          11 :     else if (_periphery_meshgenerator == "triangle")
     161             :     {
     162          22 :       if (parameters.isParamSetByUser("periphery_num_layers"))
     163             :       {
     164           0 :         paramError("periphery_num_layers",
     165             :                    "periphery_num_layers cannot be used with PTMG periphery mesher.");
     166             :       }
     167             :     }
     168             :     else
     169           0 :       paramError("periphery_generator",
     170             :                  "Provided periphery meshgenerator has not been implemented.");
     171             :   }
     172             : 
     173             :   MeshGeneratorName first_nondummy_assembly = "";
     174             :   MeshGeneratorName reactor_params = "";
     175             :   bool assembly_homogenization = false;
     176             :   bool pin_as_assembly = false;
     177             :   std::map<subdomain_id_type, std::string> global_pin_map_type_to_name;
     178             :   std::map<subdomain_id_type, std::string> assembly_map_type_to_name;
     179             :   // Check that MG name for reactor params and assembly homogenization schemes are
     180             :   // consistent across all assemblies, and there is no overlap in pin_type / assembly_type ids
     181        1068 :   for (const auto i : index_range(_inputs))
     182             :   {
     183             :     // Skip if assembly name is equal to dummy assembly name
     184         806 :     if (_inputs[i] == _empty_key)
     185         226 :       continue;
     186             : 
     187             :     // Save properties of first non-dummy assembly to compare to other assemblies
     188         580 :     if (first_nondummy_assembly == "")
     189             :     {
     190         264 :       first_nondummy_assembly = MeshGeneratorName(_inputs[i]);
     191             :       reactor_params =
     192         528 :           MeshGeneratorName(getMeshProperty<std::string>(RGMB::reactor_params_name, _inputs[i]));
     193         264 :       assembly_homogenization = getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]);
     194         264 :       pin_as_assembly = getMeshProperty<bool>(RGMB::is_single_pin, _inputs[i]);
     195             :     }
     196         580 :     if (getMeshProperty<std::string>(RGMB::reactor_params_name, _inputs[i]) != reactor_params)
     197           0 :       mooseError("The name of all reactor_params objects should be identical across all pins in "
     198             :                  "the input assemblies.\n");
     199         580 :     if ((getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]) != assembly_homogenization) &&
     200          39 :         !getMeshProperty<bool>(RGMB::flexible_assembly_stitching, reactor_params))
     201           0 :       mooseError("In order to stitch heterogeneous assemblies with homogeneous assemblies in "
     202             :                  "CoreMeshGenerator, ReactorMeshParams/flexible_assembly_stitching should be set "
     203             :                  "to true\n");
     204             : 
     205             :     // Check assembly_types across constituent assemblies are uniquely defined
     206         580 :     const auto assembly_type = getMeshProperty<subdomain_id_type>(RGMB::assembly_type, _inputs[i]);
     207         582 :     if (assembly_map_type_to_name.find(assembly_type) != assembly_map_type_to_name.end() &&
     208           2 :         assembly_map_type_to_name[assembly_type] != _inputs[i])
     209           2 :       mooseError(
     210             :           "Constituent assemblies have shared assembly_type ids but different names. Each uniquely "
     211             :           "defined assembly in AssemblyMeshGenerator must have its own assembly_type id.");
     212         578 :     assembly_map_type_to_name[assembly_type] = _inputs[i];
     213             : 
     214             :     // If assembly is composed of pins, check pin_types across all constituent assemblies are
     215             :     // uniquely defined
     216         578 :     if (hasMeshProperty<std::vector<std::string>>(RGMB::pin_names, _inputs[i]))
     217             :     {
     218         426 :       const auto pin_names = getMeshProperty<std::vector<std::string>>(RGMB::pin_names, _inputs[i]);
     219        1078 :       for (const auto & input_pin_name : pin_names)
     220             :       {
     221         654 :         const auto pin_type = getMeshProperty<subdomain_id_type>(RGMB::pin_type, input_pin_name);
     222         739 :         if (global_pin_map_type_to_name.find(pin_type) != global_pin_map_type_to_name.end() &&
     223          85 :             global_pin_map_type_to_name[pin_type] != input_pin_name)
     224           2 :           mooseError(
     225             :               "Constituent pins within assemblies have shared pin_type ids but different names. "
     226             :               "Each uniquely defined pin in AssemblyMeshGenerator must have its own pin_type id.");
     227         652 :         global_pin_map_type_to_name[pin_type] = input_pin_name;
     228             :       }
     229         424 :     }
     230             :   }
     231             : 
     232             :   // Check that there is at least one non-dummy assemby defined in lattice
     233         262 :   if (first_nondummy_assembly == "")
     234           2 :     paramError("inputs", "At least one non-dummy assembly must be defined in input assembly names");
     235             : 
     236             :   // Initialize ReactorMeshParams object stored in pin input
     237         520 :   initializeReactorMeshParams(reactor_params);
     238             : 
     239         260 :   _geom_type = getReactorParam<std::string>(RGMB::mesh_geometry);
     240         260 :   _mesh_dimensions = getReactorParam<unsigned int>(RGMB::mesh_dimensions);
     241             : 
     242         260 :   if (_extrude && _mesh_dimensions != 3)
     243           0 :     paramError("extrude",
     244             :                "In order to extrude this mesh, ReactorMeshParams/dim needs to be set to 3\n");
     245         892 :   if (_extrude && (!hasReactorParam<boundary_id_type>(RGMB::top_boundary_id) ||
     246         632 :                    !hasReactorParam<boundary_id_type>(RGMB::bottom_boundary_id)))
     247           0 :     mooseError("Both top_boundary_id and bottom_boundary_id must be provided in ReactorMeshParams "
     248             :                "if using extruded geometry");
     249         520 :   if (!hasReactorParam<boundary_id_type>(RGMB::radial_boundary_id))
     250           0 :     mooseError("radial_boundary_id must be provided in ReactorMeshParams for CoreMeshGenerators");
     251             : 
     252         520 :   if (parameters.isParamSetByUser("periphery_block_name") &&
     253          11 :       getReactorParam<bool>(RGMB::region_id_as_block_name))
     254           2 :     paramError("periphery_block_name",
     255             :                "If ReactorMeshParams/region_id_as_block_name is set, periphery_block_name should "
     256             :                "not be specified in CoreMeshGenerator");
     257             : 
     258             :   std::size_t empty_pattern_loc = 0;
     259             :   bool make_empty = false;
     260        1048 :   for (auto assembly : _inputs)
     261             :   {
     262         790 :     if (assembly != _empty_key)
     263             :     {
     264         568 :       ++empty_pattern_loc;
     265         568 :       if (getMeshProperty<bool>(RGMB::extruded, assembly))
     266           0 :         mooseError("Assemblies that have already been extruded cannot be used in CoreMeshGenerator "
     267             :                    "definition.\n");
     268             :     }
     269             :     else
     270             :     {
     271             :       // Found dummy assembly in input assembly names
     272             :       make_empty = true;
     273         805 :       for (const auto i : index_range(_pattern))
     274             :       {
     275        1908 :         for (const auto j : index_range(_pattern[i]))
     276             :         {
     277             :           // Found dummy assembly in input lattice definition
     278        1325 :           if (_pattern[i][j] == empty_pattern_loc)
     279         352 :             _empty_pos = true;
     280             :         }
     281             :       }
     282             :     }
     283             :   }
     284             : 
     285             :   // No subgenerators will be called if option to bypass mesh generators is enabled
     286         258 :   if (!getReactorParam<bool>(RGMB::bypass_meshgen))
     287             :   {
     288             :     // Check whether flexible stitching should be used for constituent assemblies and throw a
     289             :     // warning if flexible stitching option is not enabled
     290         382 :     if (!getReactorParam<bool>(RGMB::flexible_assembly_stitching) &&
     291         171 :         constituentAssembliesNeedFlexibleStiching())
     292           0 :       mooseWarning("Constituent assemblies do not share the same number of nodes at the outer "
     293             :                    "boundary. In order to ensure that output mesh does not having hanging nodes, a "
     294             :                    "flexible stitching approach should be used by setting "
     295             :                    "ReactorMeshParams/flexible_assembly_stitching = true.");
     296             : 
     297             :     // Declare that all of the meshes in the "inputs" parameter are to be used by
     298             :     // a sub mesh generator.
     299         211 :     declareMeshesForSub("inputs");
     300             : 
     301             :     // Stitch assemblies into a hexagonal / Cartesian core lattice
     302             :     {
     303             :       // create a dummy assembly that is a renamed version of one of the inputs
     304         211 :       if (make_empty)
     305             :       {
     306             :         {
     307         184 :           if (assembly_homogenization)
     308             :           {
     309          18 :             auto params = _app.getFactory().getValidParams("SimpleHexagonGenerator");
     310             : 
     311           9 :             params.set<Real>("hexagon_size") = getReactorParam<Real>(RGMB::assembly_pitch) / 2.0;
     312           9 :             params.set<std::vector<subdomain_id_type>>("block_id") = {
     313          18 :                 RGMB::DUMMY_ASSEMBLY_BLOCK_ID};
     314             : 
     315          18 :             addMeshSubgenerator("SimpleHexagonGenerator", std::string(_empty_key), params);
     316           9 :           }
     317             :           else
     318             :           {
     319             :             const auto adaptive_mg_name =
     320         175 :                 _geom_type == "Hex" ? "HexagonConcentricCircleAdaptiveBoundaryMeshGenerator"
     321             :                                     : "CartesianConcentricCircleAdaptiveBoundaryMeshGenerator";
     322         350 :             auto params = _app.getFactory().getValidParams(adaptive_mg_name);
     323             : 
     324         175 :             const auto assembly_pitch = getReactorParam<Real>(RGMB::assembly_pitch);
     325         175 :             if (_geom_type == "Hex")
     326             :             {
     327         102 :               params.set<Real>("hexagon_size") = assembly_pitch / 2.0;
     328         102 :               params.set<std::vector<unsigned int>>("num_sectors_per_side") =
     329         204 :                   std::vector<unsigned int>(6, 2);
     330             :             }
     331             :             else
     332             :             {
     333          73 :               params.set<Real>("square_size") = assembly_pitch;
     334          73 :               params.set<std::vector<unsigned int>>("num_sectors_per_side") =
     335         146 :                   std::vector<unsigned int>(4, 2);
     336             :             }
     337         350 :             params.set<std::vector<unsigned int>>("sides_to_adapt") = std::vector<unsigned int>{0};
     338         175 :             params.set<std::vector<MeshGeneratorName>>("meshes_to_adapt_to") =
     339         525 :                 std::vector<MeshGeneratorName>{first_nondummy_assembly};
     340         175 :             params.set<std::vector<subdomain_id_type>>("background_block_ids") =
     341         350 :                 std::vector<subdomain_id_type>{RGMB::DUMMY_ASSEMBLY_BLOCK_ID};
     342             : 
     343         350 :             addMeshSubgenerator(adaptive_mg_name, std::string(_empty_key), params);
     344         175 :           }
     345             :         }
     346             :       }
     347             :       {
     348             :         const auto patterned_mg_name =
     349         211 :             _geom_type == "Hex" ? "PatternedHexMeshGenerator" : "PatternedCartesianMeshGenerator";
     350         211 :         auto params = _app.getFactory().getValidParams(patterned_mg_name);
     351             : 
     352         633 :         params.set<std::vector<std::string>>("id_name") = {"assembly_id"};
     353         422 :         params.set<std::vector<MooseEnum>>("assign_type") = {
     354         844 :             MooseEnum("cell", "cell")}; // give elems IDs relative to position in assembly
     355         211 :         params.set<std::vector<MeshGeneratorName>>("inputs") = _inputs;
     356         211 :         params.set<std::vector<std::vector<unsigned int>>>("pattern") = _pattern;
     357         422 :         params.set<MooseEnum>("pattern_boundary") = "none";
     358         211 :         params.set<bool>("generate_core_metadata") = !pin_as_assembly;
     359         211 :         params.set<bool>("create_outward_interface_boundaries") = false;
     360         422 :         params.set<bool>("assign_control_drum_id") = getParam<bool>("assign_control_drum_id");
     361         211 :         if (make_empty)
     362             :         {
     363         184 :           params.set<std::vector<MeshGeneratorName>>("exclude_id") =
     364         552 :               std::vector<MeshGeneratorName>{_empty_key};
     365             :         }
     366             : 
     367         211 :         const auto radial_boundary = getReactorParam<boundary_id_type>(RGMB::radial_boundary_id);
     368         211 :         params.set<boundary_id_type>("external_boundary_id") = radial_boundary;
     369         211 :         params.set<BoundaryName>("external_boundary_name") = RGMB::CORE_BOUNDARY_NAME;
     370         211 :         params.set<double>("rotate_angle") = 0.0;
     371         211 :         params.set<bool>("allow_unused_inputs") = true;
     372             : 
     373         422 :         addMeshSubgenerator(patterned_mg_name, name() + "_pattern", params);
     374         211 :       }
     375             :     }
     376         211 :     if (_empty_pos)
     377             :     {
     378         121 :       auto params = _app.getFactory().getValidParams("BlockDeletionGenerator");
     379             : 
     380         242 :       params.set<std::vector<SubdomainName>>("block") = {
     381         726 :           std::to_string(RGMB::DUMMY_ASSEMBLY_BLOCK_ID)};
     382         363 :       params.set<MeshGeneratorName>("input") = name() + "_pattern";
     383         121 :       params.set<BoundaryName>("new_boundary") = RGMB::CORE_BOUNDARY_NAME;
     384             : 
     385         242 :       addMeshSubgenerator("BlockDeletionGenerator", name() + "_deleted", params);
     386         121 :     }
     387             : 
     388             :     std::string build_mesh_name;
     389             : 
     390             :     // Remove outer assembly sidesets created during assembly generation
     391             :     {
     392             :       // Get outer boundaries of all constituent assemblies based on assembly_type,
     393             :       // skipping all dummy assemblies
     394             :       std::vector<BoundaryName> boundaries_to_delete = {};
     395         781 :       for (const auto & pattern_x : _pattern)
     396             :       {
     397        1878 :         for (const auto & pattern_idx : pattern_x)
     398             :         {
     399        1308 :           const auto assembly_name = _inputs[pattern_idx];
     400        1308 :           if (assembly_name == _empty_key)
     401             :             continue;
     402             :           const auto assembly_id =
     403        1001 :               getMeshProperty<subdomain_id_type>(RGMB::assembly_type, assembly_name);
     404             :           const BoundaryName boundary_name =
     405        2002 :               RGMB::ASSEMBLY_BOUNDARY_NAME_PREFIX + std::to_string(assembly_id);
     406        1001 :           if (!std::count(boundaries_to_delete.begin(), boundaries_to_delete.end(), boundary_name))
     407         465 :             boundaries_to_delete.push_back(boundary_name);
     408             :         }
     409             :       }
     410         211 :       auto params = _app.getFactory().getValidParams("BoundaryDeletionGenerator");
     411             : 
     412         422 :       params.set<MeshGeneratorName>("input") =
     413         211 :           _empty_pos ? name() + "_deleted" : name() + "_pattern";
     414         422 :       params.set<std::vector<BoundaryName>>("boundary_names") = boundaries_to_delete;
     415             : 
     416         211 :       build_mesh_name = name() + "_delbds";
     417         422 :       addMeshSubgenerator("BoundaryDeletionGenerator", build_mesh_name, params);
     418         211 :     }
     419             : 
     420         869 :     for (auto assembly : _inputs)
     421             :     {
     422         658 :       if (assembly != _empty_key)
     423             :       {
     424             :         subdomain_id_type assembly_type =
     425         474 :             getMeshProperty<subdomain_id_type>(RGMB::assembly_type, assembly);
     426         474 :         if (!getMeshProperty<bool>(RGMB::is_control_drum, assembly))
     427             :         {
     428             :           // For assembly structures, store region ID and block names of assembly regions and
     429             :           // constituent pins
     430             :           const auto & pin_region_id_map = getMeshProperty<
     431         449 :               std::map<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>>(
     432             :               RGMB::pin_region_id_map, assembly);
     433        1069 :           for (auto pin = pin_region_id_map.begin(); pin != pin_region_id_map.end(); ++pin)
     434         620 :             _pin_region_id_map.insert(
     435         620 :                 std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
     436         620 :                     pin->first, pin->second));
     437             : 
     438             :           const auto & pin_block_name_map =
     439         449 :               getMeshProperty<std::map<subdomain_id_type, std::vector<std::vector<std::string>>>>(
     440             :                   RGMB::pin_block_name_map, assembly);
     441        1069 :           for (auto pin = pin_block_name_map.begin(); pin != pin_block_name_map.end(); ++pin)
     442         620 :             _pin_block_name_map.insert(
     443         620 :                 std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(pin->first,
     444         620 :                                                                                     pin->second));
     445             : 
     446             :           // Define background and duct region ID map from constituent assemblies
     447         449 :           if (_background_region_id_map.find(assembly_type) == _background_region_id_map.end())
     448             :           {
     449             :             // Store region ids and block names associated with duct and background regions for each
     450             :             // assembly, in case block names need to be recovered from region ids after
     451             :             // multiple assemblies have been stitched together into a core
     452             :             std::vector<subdomain_id_type> background_region_ids =
     453             :                 getMeshProperty<std::vector<subdomain_id_type>>(RGMB::background_region_id,
     454         449 :                                                                 assembly);
     455             :             std::vector<std::vector<subdomain_id_type>> duct_region_ids =
     456             :                 getMeshProperty<std::vector<std::vector<subdomain_id_type>>>(RGMB::duct_region_ids,
     457         449 :                                                                              assembly);
     458         898 :             _background_region_id_map.insert(
     459         449 :                 std::pair<subdomain_id_type, std::vector<subdomain_id_type>>(
     460             :                     assembly_type, background_region_ids));
     461         898 :             _duct_region_id_map.insert(
     462         449 :                 std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
     463             :                     assembly_type, duct_region_ids));
     464             : 
     465             :             std::vector<std::string> background_block_names =
     466         449 :                 getMeshProperty<std::vector<std::string>>(RGMB::background_block_name, assembly);
     467             :             std::vector<std::vector<std::string>> duct_block_names =
     468             :                 getMeshProperty<std::vector<std::vector<std::string>>>(RGMB::duct_block_names,
     469         449 :                                                                        assembly);
     470         898 :             _background_block_name_map.insert(
     471         449 :                 std::pair<subdomain_id_type, std::vector<std::string>>(assembly_type,
     472             :                                                                        background_block_names));
     473         898 :             _duct_block_name_map.insert(
     474         449 :                 std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(
     475             :                     assembly_type, duct_block_names));
     476         449 :           }
     477             :         }
     478             :         else
     479             :         {
     480             :           // For control drum structures, store region ID and block name information of drum regions
     481             :           const auto & drum_region_ids =
     482          25 :               getMeshProperty<std::vector<std::vector<subdomain_id_type>>>(RGMB::drum_region_ids,
     483             :                                                                            assembly);
     484          50 :           _drum_region_id_map.insert(
     485           0 :               std::pair<subdomain_id_type, std::vector<std::vector<subdomain_id_type>>>(
     486             :                   assembly_type, drum_region_ids));
     487             :           std::vector<std::vector<std::string>> drum_block_names =
     488             :               getMeshProperty<std::vector<std::vector<std::string>>>(RGMB::drum_block_names,
     489          25 :                                                                      assembly);
     490          50 :           _drum_block_name_map.insert(
     491          25 :               std::pair<subdomain_id_type, std::vector<std::vector<std::string>>>(
     492             :                   assembly_type, drum_block_names));
     493          25 :         }
     494             :       }
     495             :     }
     496             : 
     497             :     // periphery meshing
     498         211 :     if (_mesh_periphery)
     499             :     {
     500          45 :       std::string periphery_mg_name = (_periphery_meshgenerator == "triangle")
     501             :                                           ? "PeripheralTriangleMeshGenerator"
     502          81 :                                           : "PeripheralRingMeshGenerator";
     503             : 
     504             :       // set up common options
     505          45 :       auto params = _app.getFactory().getValidParams(periphery_mg_name);
     506         135 :       params.set<MeshGeneratorName>("input") = name() + "_delbds";
     507          45 :       params.set<Real>("peripheral_ring_radius") = _outer_circle_radius;
     508          90 :       params.set<BoundaryName>("external_boundary_name") = "outside_periphery";
     509          45 :       params.set<SubdomainName>("peripheral_ring_block_name") = RGMB::PERIPHERAL_RING_BLOCK_NAME;
     510             : 
     511             :       // unique MG options
     512          45 :       if (_periphery_meshgenerator == "triangle")
     513             :       {
     514           9 :         params.set<unsigned int>("peripheral_ring_num_segments") = _outer_circle_num_segments;
     515           9 :         params.set<Real>("desired_area") = _desired_area;
     516          18 :         params.set<std::string>("desired_area_func") = _desired_area_func;
     517             :       }
     518          36 :       else if (_periphery_meshgenerator == "quad_ring")
     519             :       {
     520          36 :         params.set<subdomain_id_type>("peripheral_ring_block_id") = RGMB::PERIPHERAL_RING_BLOCK_ID;
     521          36 :         params.set<BoundaryName>("input_mesh_external_boundary") = RGMB::CORE_BOUNDARY_NAME;
     522          36 :         params.set<unsigned int>("peripheral_layer_num") = _periphery_num_layers;
     523             :       }
     524             : 
     525             :       // finish periphery input
     526          45 :       build_mesh_name = name() + "_periphery";
     527          45 :       addMeshSubgenerator(periphery_mg_name, build_mesh_name, params);
     528          45 :     }
     529             : 
     530         211 :     if (_extrude && _mesh_dimensions == 3)
     531         296 :       build_mesh_name = callExtrusionMeshSubgenerators(build_mesh_name);
     532             : 
     533             :     // Store final mesh subgenerator
     534         211 :     _build_mesh = &getMeshByName(build_mesh_name);
     535             :   }
     536             :   // If mesh generation should be bypassed, call getMeshes to resolve MeshGeneratorSystem
     537             :   // dependencies
     538             :   else
     539          94 :     auto input_meshes = getMeshes("inputs");
     540             : 
     541         258 :   generateMetadata();
     542         891 : }
     543             : 
     544             : void
     545         258 : CoreMeshGenerator::generateMetadata()
     546             : {
     547             :   // Define metadata related to downstream function calls
     548         258 :   if (_mesh_periphery)
     549             :   {
     550          54 :     declareMeshProperty(RGMB::peripheral_ring_radius, _outer_circle_radius);
     551          54 :     declareMeshProperty(RGMB::peripheral_ring_region_id, _periphery_region_id);
     552             :   }
     553             : 
     554             :   // Determine constituent pin type ids and define lattice
     555             :   std::vector<std::vector<int>> assembly_name_lattice;
     556             :   std::vector<std::string> input_assembly_names;
     557             :   std::vector<std::string> input_pin_names;
     558             : 
     559             :   // Iterate through input assembly names and define constituent assemblies and pins
     560        1048 :   for (const auto i : index_range(_inputs))
     561             :   {
     562             :     const auto input_assembly_name = _inputs[i];
     563         790 :     if (input_assembly_name != _empty_key)
     564             :     {
     565         568 :       input_assembly_names.push_back(input_assembly_name);
     566         568 :       if (!getMeshProperty<bool>(RGMB::is_control_drum, input_assembly_name) &&
     567         534 :           !getMeshProperty<bool>(RGMB::is_single_pin, input_assembly_name))
     568             :       {
     569             :         const auto pin_names =
     570         416 :             getMeshProperty<std::vector<std::string>>(RGMB::pin_names, input_assembly_name);
     571        1052 :         for (const auto & pin_name : pin_names)
     572         636 :           if (std::find(input_pin_names.begin(), input_pin_names.end(), pin_name) ==
     573             :               input_pin_names.end())
     574         553 :             input_pin_names.push_back(pin_name);
     575         416 :       }
     576             :     }
     577             :   }
     578             : 
     579             :   // Iterate through pattern and remap dummy assemblies with index -1
     580         949 :   for (const auto i : index_range(_pattern))
     581             :   {
     582         691 :     std::vector<int> assembly_name_idx(_pattern[i].size());
     583        2268 :     for (const auto j : index_range(_pattern[i]))
     584             :     {
     585        1577 :       const auto input_assembly_name = _inputs[_pattern[i][j]];
     586             :       // Use an assembly type of -1 to represent a dummy assembly
     587        1577 :       if (input_assembly_name == _empty_key)
     588         352 :         assembly_name_idx[j] = -1;
     589             :       // Set index of assembly name based on `input_assembly_names` variable
     590             :       else
     591             :       {
     592        1225 :         const auto it = std::find(
     593             :             input_assembly_names.begin(), input_assembly_names.end(), input_assembly_name);
     594        1225 :         assembly_name_idx[j] = it - input_assembly_names.begin();
     595             :       }
     596             :     }
     597         691 :     assembly_name_lattice.push_back(assembly_name_idx);
     598         691 :   }
     599             : 
     600         258 :   declareMeshProperty(RGMB::pin_names, input_pin_names);
     601             :   declareMeshProperty(RGMB::assembly_names, input_assembly_names);
     602             :   declareMeshProperty(RGMB::assembly_lattice, assembly_name_lattice);
     603         330 :   declareMeshProperty(RGMB::extruded, _extrude && _mesh_dimensions == 3);
     604         258 : }
     605             : 
     606             : bool
     607         171 : CoreMeshGenerator::constituentAssembliesNeedFlexibleStiching()
     608             : {
     609             :   MeshGeneratorName first_nondummy_assembly = "";
     610             :   bool assembly_homogenization = false;
     611             :   unsigned int n_constituent_pins = 0;
     612             :   unsigned int n_pin_sectors = 0;
     613             : 
     614             :   // Loop through all non-dummy input assemblies. Flexible assembly stitching is needed if one of
     615             :   // the following criteria are met:
     616             :   // 1. The number of constituent pins within the assembly does not match with another assembly
     617             :   // 2. The value of is_single_pin and is_homogenized metadata do not agree with another assembly
     618             :   // 3. The number of sectors of the constituent pins of an assembly do not match with the
     619             :   // constituent pins of another assembly
     620         639 :   for (const auto i : index_range(_inputs))
     621             :   {
     622             :     // Skip if assembly name is equal to dummy assembly name
     623         468 :     if (_inputs[i] == _empty_key)
     624         144 :       continue;
     625             : 
     626             :     // Compute total number of constituent pins in assembly, as well as the number of sectors per
     627             :     // side for each pin Note: number of sectors per side is defined uniformly across constituent
     628             :     // pins of an assembly, so only first one needs to be checked
     629             :     unsigned int total_pins = 0;
     630             :     unsigned int pin_sectors_per_side = 0;
     631         324 :     if (!getMeshProperty<bool>(RGMB::is_single_pin, _inputs[i]))
     632             :     {
     633             :       const auto first_pin_name =
     634         270 :           getMeshProperty<std::vector<std::string>>(RGMB::pin_names, _inputs[i])[0];
     635         270 :       pin_sectors_per_side = getMeshProperty<std::vector<unsigned int>>("num_sectors_per_side_meta",
     636         540 :                                                                         first_pin_name + "_2D")[0];
     637             :       const auto pin_lattice =
     638         270 :           getMeshProperty<std::vector<std::vector<int>>>(RGMB::pin_lattice, _inputs[i]);
     639         972 :       for (const auto i : index_range(pin_lattice))
     640         702 :         total_pins += pin_lattice[i].size();
     641         270 :     }
     642             :     else
     643             :     {
     644          54 :       if (getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]))
     645             :       {
     646             :         // Homogenized assembly
     647             :         total_pins = 0;
     648             :         pin_sectors_per_side = 0;
     649             :       }
     650             :       else
     651             :       {
     652             :         // Assembly with single constituent pin
     653             :         total_pins = 1;
     654          36 :         pin_sectors_per_side = getMeshProperty<std::vector<unsigned int>>(
     655          72 :             "num_sectors_per_side_meta", _inputs[i] + "_2D")[0];
     656             :       }
     657             :     }
     658             : 
     659         324 :     if (first_nondummy_assembly == "")
     660             :     {
     661         171 :       first_nondummy_assembly = MeshGeneratorName(_inputs[i]);
     662         171 :       assembly_homogenization = getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]);
     663             :       n_constituent_pins = total_pins;
     664             :       n_pin_sectors = pin_sectors_per_side;
     665             :     }
     666             :     else
     667             :     {
     668         153 :       if (getMeshProperty<bool>(RGMB::is_homogenized, _inputs[i]) != assembly_homogenization)
     669             :       {
     670           0 :         mooseWarning("Detected mix of homogenized and heterogeneous assemblies between " +
     671           0 :                      first_nondummy_assembly + " and " + _inputs[i]);
     672           0 :         return true;
     673             :       }
     674         153 :       if (total_pins != n_constituent_pins)
     675             :       {
     676           0 :         mooseWarning(
     677           0 :             "Detected assemblies with different number of total constituent pins between " +
     678           0 :             first_nondummy_assembly + " and " + _inputs[i]);
     679           0 :         return true;
     680             :       }
     681         153 :       if (pin_sectors_per_side != n_pin_sectors)
     682             :       {
     683           0 :         mooseWarning("Constituent pins in " + first_nondummy_assembly + " and " + _inputs[i] +
     684             :                      " differ in terms of number of sectors per side");
     685           0 :         return true;
     686             :       }
     687             :     }
     688             :   }
     689             :   return false;
     690             : }
     691             : 
     692             : std::unique_ptr<MeshBase>
     693         213 : CoreMeshGenerator::generate()
     694             : {
     695             :   // Must be called to free the ReactorMeshParams mesh
     696         213 :   freeReactorMeshParams();
     697             : 
     698             :   // If bypass_mesh is true, return a null mesh. In this mode, an output mesh is not
     699             :   // generated and only metadata is defined on the generator, so logic related to
     700             :   // generation of output mesh will not be called
     701         213 :   if (getReactorParam<bool>(RGMB::bypass_meshgen))
     702             :   {
     703             :     auto null_mesh = nullptr;
     704             :     return null_mesh;
     705             :   }
     706             :   // This generate() method will be called once the subgenerators that we depend on are
     707             :   // called. This is where we reassign subdomain ids/names in case they were merged
     708             :   // when stitching assemblies into the core. This is also where we set region_id extra
     709             :   // element integers, which has not been set yet for extruded geometries
     710             : 
     711             :   // Define all extra element names and integers
     712         211 :   std::string pin_type_id_name = "pin_type_id";
     713         211 :   std::string assembly_type_id_name = "assembly_type_id";
     714         211 :   std::string plane_id_name = "plane_id";
     715         211 :   std::string region_id_name = "region_id";
     716         211 :   std::string radial_id_name = "radial_id";
     717         211 :   const std::string default_block_name = RGMB::CORE_BLOCK_NAME_PREFIX;
     718             : 
     719         211 :   auto pin_type_id_int = getElemIntegerFromMesh(*(*_build_mesh), pin_type_id_name, true);
     720         211 :   auto assembly_type_id_int = getElemIntegerFromMesh(*(*_build_mesh), assembly_type_id_name, true);
     721         211 :   auto radial_id_int = getElemIntegerFromMesh(*(*_build_mesh), radial_id_name, true);
     722         211 :   auto region_id_int = getElemIntegerFromMesh(*(*_build_mesh), region_id_name, true);
     723             :   unsigned int plane_id_int = 0;
     724         211 :   if (_extrude)
     725         296 :     plane_id_int = getElemIntegerFromMesh(*(*_build_mesh), plane_id_name, true);
     726             : 
     727             :   // Get next free block ID in mesh in case subdomain ids need to be remapped
     728         211 :   auto next_block_id = MooseMeshUtils::getNextFreeSubdomainID(*(*(_build_mesh)));
     729             :   std::map<std::string, SubdomainID> rgmb_name_id_map;
     730             : 
     731             :   // Loop through all mesh elements and set region ids and reassign block IDs/names
     732             :   // if they were merged during assembly stitching
     733      616486 :   for (auto & elem : (*_build_mesh)->active_element_ptr_range())
     734             :   {
     735      308032 :     dof_id_type z_id = _extrude ? elem->get_extra_integer(plane_id_int) : 0;
     736      308032 :     dof_id_type pin_type_id = elem->get_extra_integer(pin_type_id_int);
     737             : 
     738      308032 :     if (_pin_region_id_map.find(pin_type_id) != _pin_region_id_map.end())
     739             :     {
     740             :       // Pin type element, get region ID from pin_type, z_id, and radial_idx
     741      172346 :       const dof_id_type radial_idx = elem->get_extra_integer(radial_id_int);
     742      172346 :       const auto elem_rid = _pin_region_id_map[pin_type_id][z_id][radial_idx];
     743      172346 :       elem->set_extra_integer(region_id_int, elem_rid);
     744             : 
     745             :       // Set element block name and block id
     746      172346 :       bool has_block_names = !_pin_block_name_map[pin_type_id].empty();
     747      172346 :       auto elem_block_name = default_block_name;
     748      172346 :       if (has_block_names)
     749      115776 :         elem_block_name += "_" + _pin_block_name_map[pin_type_id][z_id][radial_idx];
     750      114458 :       else if (getReactorParam<bool>(RGMB::region_id_as_block_name))
     751       67384 :         elem_block_name += "_REG" + std::to_string(elem_rid);
     752      172346 :       if (elem->type() == TRI3 || elem->type() == PRISM6)
     753             :         elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
     754      344692 :       updateElementBlockNameId(
     755      172346 :           *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
     756             :     }
     757      135686 :     else if ((*_build_mesh)->subdomain_name(elem->subdomain_id()) ==
     758             :              RGMB::PERIPHERAL_RING_BLOCK_NAME)
     759             :     // periphery type element
     760             :     {
     761             :       // set region ID of core periphery element
     762       17454 :       elem->set_extra_integer(region_id_int, _periphery_region_id);
     763             :       // set block name and block name of core periphery element
     764       17454 :       auto elem_block_name = _periphery_block_name;
     765       17454 :       if (getReactorParam<bool>(RGMB::region_id_as_block_name))
     766           0 :         elem_block_name += "_REG" + std::to_string(_periphery_region_id);
     767       17454 :       if (elem->type() == TRI3 || elem->type() == PRISM6)
     768             :         elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
     769       34908 :       updateElementBlockNameId(
     770       17454 :           *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
     771             :     }
     772             :     else
     773             :     {
     774      118232 :       dof_id_type assembly_type_id = elem->get_extra_integer(assembly_type_id_int);
     775             :       // Infer peripheral index of assembly background, assembly duct, or control drum regions from
     776             :       // pin_type_id
     777      118232 :       unsigned int peripheral_idx = RGMB::MAX_PIN_TYPE_ID - pin_type_id;
     778             : 
     779             :       // check if element is part of drum region
     780      118232 :       if (_drum_region_id_map.find(assembly_type_id) != _drum_region_id_map.end())
     781             :       {
     782             :         // Element is in a control drum region. Infer region id from assembly_type_id, z_id, and
     783             :         // peripheral_index
     784       24128 :         const auto elem_rid = _drum_region_id_map[assembly_type_id][z_id][peripheral_idx];
     785       24128 :         elem->set_extra_integer(region_id_int, elem_rid);
     786             : 
     787             :         // Set element block name and block id
     788       24128 :         auto elem_block_name = default_block_name;
     789       24128 :         if (getReactorParam<bool>(RGMB::region_id_as_block_name))
     790       48256 :           elem_block_name += "_REG" + std::to_string(elem_rid);
     791             :         else
     792             :         {
     793           0 :           bool has_drum_block_name = !_drum_block_name_map[assembly_type_id].empty();
     794           0 :           if (has_drum_block_name)
     795           0 :             elem_block_name += "_" + _drum_block_name_map[assembly_type_id][z_id][peripheral_idx];
     796             :         }
     797       24128 :         if (elem->type() == TRI3 || elem->type() == PRISM6)
     798             :           elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
     799       48256 :         updateElementBlockNameId(
     800       24128 :             *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
     801             :       }
     802             :       else
     803             :       {
     804             :         // Element is in an assembly duct or background region since it doesn't
     805             :         // have an assembly type id in the drum region map. Infer region id from
     806             :         // assembly_type_id, z_id, and peripheral_index
     807             :         bool is_background_region = peripheral_idx == 0;
     808             :         const auto elem_rid =
     809             :             (is_background_region
     810       94104 :                  ? _background_region_id_map[assembly_type_id][z_id]
     811       30394 :                  : _duct_region_id_map[assembly_type_id][z_id][peripheral_idx - 1]);
     812       94104 :         elem->set_extra_integer(region_id_int, elem_rid);
     813             : 
     814             :         // Set element block name and block id
     815       94104 :         auto elem_block_name = default_block_name;
     816       94104 :         if (getReactorParam<bool>(RGMB::region_id_as_block_name))
     817      114480 :           elem_block_name += "_REG" + std::to_string(elem_rid);
     818             :         else
     819             :         {
     820       36864 :           if (is_background_region)
     821             :           {
     822       21996 :             bool has_background_block_name = !_background_block_name_map[assembly_type_id].empty();
     823       21996 :             if (has_background_block_name)
     824       20736 :               elem_block_name += "_" + _background_block_name_map[assembly_type_id][z_id];
     825             :           }
     826             :           else
     827             :           {
     828       14868 :             bool has_duct_block_names = !_duct_block_name_map[assembly_type_id].empty();
     829       14868 :             if (has_duct_block_names)
     830             :               elem_block_name +=
     831       15552 :                   "_" + _duct_block_name_map[assembly_type_id][z_id][peripheral_idx - 1];
     832             :           }
     833             :         }
     834       94104 :         if (elem->type() == TRI3 || elem->type() == PRISM6)
     835             :           elem_block_name += RGMB::TRI_BLOCK_NAME_SUFFIX;
     836      188208 :         updateElementBlockNameId(
     837       94104 :             *(*_build_mesh), elem, rgmb_name_id_map, elem_block_name, next_block_id);
     838             :       }
     839             :     }
     840         211 :   }
     841             : 
     842             :   // Sideset 10000 does not get stitched properly when BlockDeletionGenerator
     843             :   // is used for deleting dummy assemblies. This block copies missing sides
     844             :   // into sideset 10000 from sideset RGMB::CORE_BOUNDARY_NAME
     845         211 :   BoundaryInfo & boundary_info = (*_build_mesh)->get_boundary_info();
     846             :   boundary_id_type source_id =
     847         422 :       MooseMeshUtils::getBoundaryIDs(**_build_mesh, {RGMB::CORE_BOUNDARY_NAME}, true)[0];
     848             :   boundary_id_type target_id = 10000;
     849             :   const auto sideset_map = boundary_info.get_sideset_map();
     850             : 
     851      358710 :   for (const auto & [elem, id_pair] : sideset_map)
     852             :   {
     853      358499 :     const auto side_id = id_pair.first;
     854      358499 :     const auto sideset_id = id_pair.second;
     855             : 
     856             :     // Filter all sides that belong to RGMB::CORE_BOUNDARY_NAME sideset
     857      358499 :     if (sideset_id == source_id)
     858             :     {
     859             :       auto mm_it = sideset_map.equal_range(elem);
     860             :       bool found = false;
     861             :       // Check if side is defined in sideset 10000
     862       68754 :       for (auto it = mm_it.first; it != mm_it.second; it++)
     863             :       {
     864       50160 :         if (it->second.first == side_id && it->second.second == target_id)
     865             :           found = true;
     866             :       }
     867             :       // Add side if not found in sideset 10000
     868       18594 :       if (!found)
     869        4893 :         boundary_info.add_side(elem, side_id, target_id);
     870             :     }
     871             :   }
     872             : 
     873         422 :   if (getParam<bool>("generate_depletion_id"))
     874             :   {
     875          56 :     const MooseEnum option = getParam<MooseEnum>("depletion_id_type");
     876          28 :     addDepletionId(*(*_build_mesh), option, DepletionIDGenerationLevel::Core, _extrude);
     877          28 :   }
     878             : 
     879             :   // Mark mesh as not prepared, as block ID's were re-assigned in this method
     880         211 :   (*_build_mesh)->set_isnt_prepared();
     881             : 
     882             :   return std::move(*_build_mesh);
     883             : }

Generated by: LCOV version 1.14