LCOV - code coverage report
Current view: top level - src/meshgenerators - ReactorGeometryMeshBuilderBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose reactor: #33187 (5aa0b2) with base d7c4bd Lines: 148 160 92.5 %
Date: 2026-06-30 12:23:22 Functions: 13 13 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 "ReactorGeometryMeshBuilderBase.h"
      11             : #include "DepletionIDGenerator.h"
      12             : #include "MooseMeshUtils.h"
      13             : #include "CSGPlane.h"
      14             : #include "CSGCartesianLattice.h"
      15             : #include "CSGHexagonalLattice.h"
      16             : 
      17             : InputParameters
      18        3676 : ReactorGeometryMeshBuilderBase::validParams()
      19             : {
      20        3676 :   InputParameters params = MeshGenerator::validParams();
      21             : 
      22        7352 :   params.addDeprecatedParam<bool>("show_rgmb_metadata",
      23             :                                   "Print out RGMB-related metadata to console output",
      24             :                                   "This parameter is deprecated. Please use MeshMetaDataReporter "
      25             :                                   "system to print out mesh metadata to JSON output file instead");
      26        3676 :   params.addClassDescription("A base class that contains common members and methods for Reactor "
      27             :                              "Geometry Mesh Builder mesh generators.");
      28             : 
      29             :   // Declare that this generator has a generateData method
      30        3676 :   MeshGenerator::setHasGenerateData(params);
      31        3676 :   return params;
      32           0 : }
      33             : 
      34             : void
      35        1676 : ReactorGeometryMeshBuilderBase::addDepletionIDParams(InputParameters & params)
      36             : {
      37        3352 :   params.addParam<bool>(
      38        3352 :       "generate_depletion_id", false, "Determine wheter the depletion ID is assigned.");
      39        3352 :   MooseEnum depletion_id_option("assembly assembly_type pin pin_type");
      40        3352 :   params.addParam<MooseEnum>("depletion_id_type",
      41             :                              depletion_id_option,
      42             :                              "Determine level of details in depletion ID assignment.");
      43        3352 :   params.addParamNamesToGroup("generate_depletion_id depletion_id_type", "Depletion ID assignment");
      44        1676 : }
      45             : 
      46        1855 : ReactorGeometryMeshBuilderBase::ReactorGeometryMeshBuilderBase(const InputParameters & parameters)
      47        1855 :   : MeshGenerator(parameters)
      48             : {
      49        1855 : }
      50             : 
      51             : void
      52        1849 : ReactorGeometryMeshBuilderBase::initializeReactorMeshParams(const std::string reactor_param_name)
      53             : {
      54        1849 :   _reactor_params = reactor_param_name;
      55             : 
      56             :   // Ensure that the user has supplied a valid ReactorMeshParams object
      57        1849 :   _reactor_params_mesh = &getMeshByName(reactor_param_name);
      58        1849 :   if (*_reactor_params_mesh)
      59           0 :     mooseError("The reactor_params mesh is not of the correct type");
      60             : 
      61        5547 :   if (!hasMeshProperty<unsigned int>("mesh_dimensions", _reactor_params) ||
      62        5547 :       !hasMeshProperty<std::string>("mesh_geometry", _reactor_params))
      63           0 :     mooseError("The reactor_params input must be a ReactorMeshParams type MeshGenerator\n Please "
      64             :                "check that a valid definition and name of ReactorMeshParams has been provided.");
      65             : 
      66             :   // Set reactor_params_name metadata for use by future mesh generators
      67        3698 :   declareMeshProperty("reactor_params_name", std::string(_reactor_params));
      68             : 
      69             :   // Store CSGBase object if we are in CSG only mode
      70        1849 :   if (_app.getMeshGeneratorSystem().getCSGOnly())
      71         325 :     _reactor_params_csg = &getCSGBaseByName(_reactor_params);
      72        1849 : }
      73             : 
      74             : void
      75        1252 : ReactorGeometryMeshBuilderBase::freeReactorParamsMesh()
      76             : {
      77        1252 :   _reactor_params_mesh->reset();
      78        1252 : }
      79             : 
      80             : void
      81         325 : ReactorGeometryMeshBuilderBase::freeReactorParamsCSG()
      82             : {
      83         325 :   _reactor_params_csg->reset();
      84         325 : }
      85             : 
      86             : unsigned int
      87        4569 : ReactorGeometryMeshBuilderBase::getElemIntegerFromMesh(MeshBase & input_mesh,
      88             :                                                        std::string extra_int_name,
      89             :                                                        bool should_exist)
      90             : {
      91        4569 :   if (input_mesh.has_elem_integer(extra_int_name))
      92        1902 :     return input_mesh.get_elem_integer_index(extra_int_name);
      93             :   else
      94             :   {
      95        2667 :     if (should_exist)
      96           0 :       mooseError("Expected extruded mesh to have " + extra_int_name + " extra integers");
      97             :     else
      98        5334 :       return input_mesh.add_elem_integer(extra_int_name);
      99             :   }
     100             : }
     101             : 
     102             : void
     103      551920 : ReactorGeometryMeshBuilderBase::updateElementBlockNameId(
     104             :     MeshBase & input_mesh,
     105             :     Elem * elem,
     106             :     std::map<std::string, SubdomainID> & name_id_map,
     107             :     std::string elem_block_name,
     108             :     SubdomainID & next_free_id)
     109             : {
     110             :   SubdomainID elem_block_id;
     111      551920 :   if (name_id_map.find(elem_block_name) == name_id_map.end())
     112             :   {
     113             :     // Block name does not exist in mesh yet, assign new block id and name
     114        3459 :     elem_block_id = next_free_id++;
     115        3459 :     elem->subdomain_id() = elem_block_id;
     116        3459 :     input_mesh.subdomain_name(elem_block_id) = elem_block_name;
     117        3459 :     name_id_map[elem_block_name] = elem_block_id;
     118             :   }
     119             :   else
     120             :   {
     121             :     // Block name exists in mesh, reuse block id
     122      548461 :     elem_block_id = name_id_map[elem_block_name];
     123      548461 :     elem->subdomain_id() = elem_block_id;
     124             :   }
     125             : 
     126             :   input_mesh.unset_has_cached_elem_data();
     127      551920 : }
     128             : 
     129             : void
     130          45 : ReactorGeometryMeshBuilderBase::addDepletionId(MeshBase & input_mesh,
     131             :                                                const MooseEnum & option,
     132             :                                                const DepletionIDGenerationLevel generation_level,
     133             :                                                const bool extrude)
     134             : {
     135             :   // prepare set of extra elem ids for depletion ID generation
     136             :   std::vector<ExtraElementIDName> id_names = {};
     137          45 :   if (extrude)
     138          24 :     id_names.push_back("plane_id");
     139          45 :   if (generation_level == DepletionIDGenerationLevel::Core)
     140             :   {
     141          24 :     if (option == "pin")
     142          36 :       id_names.insert(id_names.end(), {"assembly_id", "pin_id"});
     143          12 :     else if (option == "pin_type")
     144          36 :       id_names.insert(id_names.end(), {"assembly_id", "pin_type_id"});
     145           0 :     else if (option == "assembly")
     146           0 :       id_names.push_back("assembly_id");
     147           0 :     else if (option == "assembly_type")
     148           0 :       id_names.push_back("assembly_type_id");
     149             :   }
     150          21 :   else if (generation_level == DepletionIDGenerationLevel::Assembly)
     151             :   {
     152          14 :     if (option == "pin")
     153           7 :       id_names.push_back("pin_id");
     154           7 :     else if (option == "pin_type")
     155           7 :       id_names.push_back("pin_type_id");
     156             :     else
     157           0 :       paramError("depletion_id_type",
     158             :                  "'assembly_id' or 'assembly_type_id' is not allowed in depletion ID generation at "
     159             :                  "assembly level");
     160             :   }
     161           7 :   else if (generation_level == DepletionIDGenerationLevel::Drum)
     162             :   {
     163           7 :     if (option == "pin_type")
     164           5 :       id_names.push_back("pin_type_id");
     165             :     else
     166           2 :       paramError("depletion_id_type",
     167             :                  "Only 'pin_type' is allowed in depletion ID generation at "
     168             :                  "drum level");
     169             :   }
     170           0 :   else if (generation_level == DepletionIDGenerationLevel::Pin)
     171           0 :     mooseError("Depletion ID generation is not supported at pin level yet in RGMB");
     172          43 :   id_names.push_back("region_id");
     173             :   // no block restriction
     174             :   std::set<SubdomainID> block_ids = {};
     175             :   // create depletion IDs
     176             :   // depletion IDs will be assigned in the following order:
     177             :   // regions (materials) within pin -> pins in assembly -> assemblies in core -> axial planes
     178             :   std::unordered_map<dof_id_type, dof_id_type> depl_ids =
     179          43 :       MooseMeshUtils::getExtraIDUniqueCombinationMap(input_mesh, block_ids, id_names);
     180             :   // assign depletion ids to elements
     181          43 :   const auto depl_id_index = input_mesh.add_elem_integer("depletion_id");
     182       55906 :   for (Elem * const elem : input_mesh.active_element_ptr_range())
     183       55863 :     elem->set_extra_integer(depl_id_index, depl_ids.at(elem->id()));
     184          43 : }
     185             : 
     186             : MeshGeneratorName
     187         187 : ReactorGeometryMeshBuilderBase::callExtrusionMeshSubgenerators(
     188             :     const MeshGeneratorName input_mesh_name)
     189             : {
     190         187 :   std::vector<Real> axial_boundaries = getReactorParam<std::vector<Real>>(RGMB::axial_mesh_sizes);
     191         187 :   const auto top_boundary = getReactorParam<boundary_id_type>(RGMB::top_boundary_id);
     192         187 :   const auto bottom_boundary = getReactorParam<boundary_id_type>(RGMB::bottom_boundary_id);
     193             : 
     194             :   {
     195         187 :     auto params = _app.getFactory().getValidParams("AdvancedExtruderGenerator");
     196             : 
     197         187 :     params.set<MeshGeneratorName>("input") = input_mesh_name;
     198         187 :     params.set<Point>("direction") = Point(0, 0, 1);
     199         187 :     params.set<std::vector<unsigned int>>("num_layers") =
     200         187 :         getReactorParam<std::vector<unsigned int>>(RGMB::axial_mesh_intervals);
     201         187 :     params.set<std::vector<Real>>("heights") = axial_boundaries;
     202         561 :     params.set<BoundaryName>("bottom_boundary") = std::to_string(bottom_boundary);
     203         561 :     params.set<BoundaryName>("top_boundary") = std::to_string(top_boundary);
     204         374 :     addMeshSubgenerator("AdvancedExtruderGenerator", name() + "_extruded", params);
     205         187 :   }
     206             : 
     207             :   {
     208         374 :     auto params = _app.getFactory().getValidParams("RenameBoundaryGenerator");
     209             : 
     210         561 :     params.set<MeshGeneratorName>("input") = name() + "_extruded";
     211         374 :     params.set<std::vector<BoundaryName>>("old_boundary") = {
     212         187 :         std::to_string(top_boundary),
     213        1309 :         std::to_string(bottom_boundary)}; // hard coded boundary IDs in patterned mesh generator
     214         748 :     params.set<std::vector<BoundaryName>>("new_boundary") = {"top", "bottom"};
     215         374 :     addMeshSubgenerator("RenameBoundaryGenerator", name() + "_change_plane_name", params);
     216         187 :   }
     217             : 
     218         187 :   const MeshGeneratorName output_mesh_name = name() + "_extrudedIDs";
     219             :   {
     220         374 :     auto params = _app.getFactory().getValidParams("PlaneIDMeshGenerator");
     221             : 
     222         561 :     params.set<MeshGeneratorName>("input") = name() + "_change_plane_name";
     223             : 
     224         187 :     std::vector<Real> plane_heights{0};
     225         451 :     for (Real z : axial_boundaries)
     226         264 :       plane_heights.push_back(z + plane_heights.back());
     227             : 
     228         187 :     params.set<std::vector<Real>>("plane_coordinates") = plane_heights;
     229             : 
     230         187 :     std::string plane_id_name = "plane_id";
     231         187 :     params.set<std::string>("id_name") = "plane_id";
     232             : 
     233         374 :     addMeshSubgenerator("PlaneIDMeshGenerator", output_mesh_name, params);
     234         187 :   }
     235             : 
     236         187 :   return output_mesh_name;
     237         187 : }
     238             : 
     239             : std::vector<std::reference_wrapper<const CSG::CSGSurface>>
     240         395 : ReactorGeometryMeshBuilderBase::getOuterRadialSurfacesForUnitCell(unsigned int radial_index,
     241             :                                                                   Real halfpitch,
     242             :                                                                   CSG::CSGBase & csg_obj)
     243             : {
     244             :   std::vector<std::reference_wrapper<const CSG::CSGSurface>> duct_surfaces;
     245         395 :   const auto mesh_geometry = getReactorParam<std::string>(RGMB::mesh_geometry);
     246         395 :   const auto n_azim_surfaces = mesh_geometry == "Square" ? 4 : 6;
     247             : 
     248             :   // Convert halfpitch to radius (distance from vertex to center)
     249         395 :   const Real angle_offset_degrees = mesh_geometry == "Square" ? 45. : 30.;
     250         395 :   const Real angle_offset_radians = angle_offset_degrees * (M_PI / 180.);
     251         395 :   const auto radius = halfpitch / std::cos(angle_offset_radians);
     252             : 
     253         395 :   Real angle_increment_radians = 360. / n_azim_surfaces * (M_PI / 180.);
     254             : 
     255        2345 :   for (const auto i : make_range(n_azim_surfaces))
     256             :   {
     257             :     const auto surf_name =
     258        5850 :         name() + "_radial_duct_" + std::to_string(radial_index) + "_surf_" + std::to_string(i);
     259             : 
     260             :     // Define 3 points on the surface
     261        1950 :     const auto current_angle = i * angle_increment_radians + angle_offset_radians;
     262        1950 :     const auto next_angle = (i + 1) * angle_increment_radians + angle_offset_radians;
     263        1950 :     libMesh::Point p0(radius * std::cos(current_angle), radius * std::sin(current_angle), 0.);
     264        1950 :     libMesh::Point p1(radius * std::cos(next_angle), radius * std::sin(next_angle), 0.);
     265             :     libMesh::Point p2 = (p0 + p1) / 2.;
     266             :     // Place third point above the two others to form a vertical plane
     267        1950 :     p2(2) = angle_offset_degrees;
     268             : 
     269             :     std::unique_ptr<CSG::CSGSurface> duct_surf_ptr =
     270        1950 :         std::make_unique<CSG::CSGPlane>(surf_name, p0, p1, p2);
     271        1950 :     const auto & duct_surf = csg_obj.addSurface(std::move(duct_surf_ptr));
     272        1950 :     duct_surfaces.push_back(duct_surf);
     273        1950 :   }
     274             : 
     275         395 :   return duct_surfaces;
     276           0 : }
     277             : 
     278             : std::vector<std::reference_wrapper<const CSG::CSGSurface>>
     279         260 : ReactorGeometryMeshBuilderBase::getAxialPlaneSurfaces(CSG::CSGBase & csg_obj)
     280             : {
     281             :   std::vector<std::reference_wrapper<const CSG::CSGSurface>> surfaces_by_axial_region;
     282         260 :   const auto axial_boundaries = getReactorParam<std::vector<Real>>(RGMB::axial_mesh_sizes);
     283         260 :   Real axial_level = 0.;
     284             : 
     285             :   // Check if axial planes have been defined in CSGBase based on a surface name we expect
     286             :   // to find
     287         260 :   auto axial_surf_name = RGMB::CSG_AXIAL_PLANE_PREFIX + "0";
     288             :   const auto has_axial_surfaces = csg_obj.hasSurface(axial_surf_name);
     289             : 
     290         865 :   for (const auto i : make_range(axial_boundaries.size() + 1))
     291             :   {
     292         605 :     axial_surf_name = RGMB::CSG_AXIAL_PLANE_PREFIX + std::to_string(i);
     293         605 :     if (has_axial_surfaces)
     294             :       // Surface should exist in CSGBase, retrieve from object
     295         240 :       surfaces_by_axial_region.push_back(csg_obj.getSurfaceByName(axial_surf_name));
     296             :     else
     297             :     {
     298             :       // Surface has not been defined, create it and add to CSGBase
     299         365 :       axial_level += (i != 0) ? axial_boundaries[i - 1] : 0.;
     300             :       std::unique_ptr<CSG::CSGSurface> plane_surf_ptr =
     301         365 :           std::make_unique<CSG::CSGPlane>(axial_surf_name, 0, 0, 1, axial_level);
     302         365 :       const auto & plane_surf = csg_obj.addSurface(std::move(plane_surf_ptr));
     303         365 :       surfaces_by_axial_region.push_back(plane_surf);
     304         365 :     }
     305             :   }
     306             : 
     307         260 :   return surfaces_by_axial_region;
     308         260 : }
     309             : 
     310             : const CSG::CSGLattice &
     311         120 : ReactorGeometryMeshBuilderBase::createRGMBLattice(
     312             :     const Real pitch,
     313             :     const std::vector<std::vector<std::reference_wrapper<const CSG::CSGUniverse>>> pattern,
     314             :     CSG::CSGBase & csg_obj)
     315             : {
     316             :   // Create lattice based on whether it is hexagonal or Cartesian
     317         120 :   std::string lat_name = name() + "_lattice";
     318         120 :   std::unique_ptr<CSG::CSGLattice> lat_ptr;
     319         120 :   const auto mesh_geometry = getReactorParam<std::string>(RGMB::mesh_geometry);
     320         120 :   if (mesh_geometry == "Square")
     321          70 :     lat_ptr = std::make_unique<CSG::CSGCartesianLattice>(lat_name, pitch, pattern);
     322             :   else // _geom_type == "Hex"
     323          50 :     lat_ptr = std::make_unique<CSG::CSGHexagonalLattice>(lat_name, pitch, pattern);
     324             : 
     325         120 :   auto & assembly_lattice = csg_obj.addLattice(std::move(lat_ptr));
     326         120 :   return assembly_lattice;
     327         120 : }

Generated by: LCOV version 1.14