https://mooseframework.inl.gov
ReactorGeometryMeshBuilderBase.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 
11 #include "DepletionIDGenerator.h"
12 #include "MooseMeshUtils.h"
13 #include "CSGPlane.h"
14 #include "CSGCartesianLattice.h"
15 #include "CSGHexagonalLattice.h"
16 
19 {
21 
22  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  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
31  return params;
32 }
33 
34 void
36 {
37  params.addParam<bool>(
38  "generate_depletion_id", false, "Determine wheter the depletion ID is assigned.");
39  MooseEnum depletion_id_option("assembly assembly_type pin pin_type");
40  params.addParam<MooseEnum>("depletion_id_type",
41  depletion_id_option,
42  "Determine level of details in depletion ID assignment.");
43  params.addParamNamesToGroup("generate_depletion_id depletion_id_type", "Depletion ID assignment");
44 }
45 
47  : MeshGenerator(parameters)
48 {
49 }
50 
51 void
53 {
54  _reactor_params = reactor_param_name;
55 
56  // Ensure that the user has supplied a valid ReactorMeshParams object
57  _reactor_params_mesh = &getMeshByName(reactor_param_name);
59  mooseError("The reactor_params mesh is not of the correct type");
60 
61  if (!hasMeshProperty<unsigned int>("mesh_dimensions", _reactor_params) ||
62  !hasMeshProperty<std::string>("mesh_geometry", _reactor_params))
63  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  declareMeshProperty("reactor_params_name", std::string(_reactor_params));
68 
69  // Store CSGBase object if we are in CSG only mode
72 }
73 
74 void
76 {
77  _reactor_params_mesh->reset();
78 }
79 
80 void
82 {
83  _reactor_params_csg->reset();
84 }
85 
86 unsigned int
88  std::string extra_int_name,
89  bool should_exist)
90 {
91  if (input_mesh.has_elem_integer(extra_int_name))
92  return input_mesh.get_elem_integer_index(extra_int_name);
93  else
94  {
95  if (should_exist)
96  mooseError("Expected extruded mesh to have " + extra_int_name + " extra integers");
97  else
98  return input_mesh.add_elem_integer(extra_int_name);
99  }
100 }
101 
102 void
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  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  elem_block_id = next_free_id++;
115  elem->subdomain_id() = elem_block_id;
116  input_mesh.subdomain_name(elem_block_id) = elem_block_name;
117  name_id_map[elem_block_name] = elem_block_id;
118  }
119  else
120  {
121  // Block name exists in mesh, reuse block id
122  elem_block_id = name_id_map[elem_block_name];
123  elem->subdomain_id() = elem_block_id;
124  }
125 
126  input_mesh.unset_has_cached_elem_data();
127 }
128 
129 void
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  if (extrude)
138  id_names.push_back("plane_id");
139  if (generation_level == DepletionIDGenerationLevel::Core)
140  {
141  if (option == "pin")
142  id_names.insert(id_names.end(), {"assembly_id", "pin_id"});
143  else if (option == "pin_type")
144  id_names.insert(id_names.end(), {"assembly_id", "pin_type_id"});
145  else if (option == "assembly")
146  id_names.push_back("assembly_id");
147  else if (option == "assembly_type")
148  id_names.push_back("assembly_type_id");
149  }
150  else if (generation_level == DepletionIDGenerationLevel::Assembly)
151  {
152  if (option == "pin")
153  id_names.push_back("pin_id");
154  else if (option == "pin_type")
155  id_names.push_back("pin_type_id");
156  else
157  paramError("depletion_id_type",
158  "'assembly_id' or 'assembly_type_id' is not allowed in depletion ID generation at "
159  "assembly level");
160  }
161  else if (generation_level == DepletionIDGenerationLevel::Drum)
162  {
163  if (option == "pin_type")
164  id_names.push_back("pin_type_id");
165  else
166  paramError("depletion_id_type",
167  "Only 'pin_type' is allowed in depletion ID generation at "
168  "drum level");
169  }
170  else if (generation_level == DepletionIDGenerationLevel::Pin)
171  mooseError("Depletion ID generation is not supported at pin level yet in RGMB");
172  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  MooseMeshUtils::getExtraIDUniqueCombinationMap(input_mesh, block_ids, id_names);
180  // assign depletion ids to elements
181  const auto depl_id_index = input_mesh.add_elem_integer("depletion_id");
182  for (Elem * const elem : input_mesh.active_element_ptr_range())
183  elem->set_extra_integer(depl_id_index, depl_ids.at(elem->id()));
184 }
185 
186 MeshGeneratorName
188  const MeshGeneratorName input_mesh_name)
189 {
190  std::vector<Real> axial_boundaries = getReactorParam<std::vector<Real>>(RGMB::axial_mesh_sizes);
191  const auto top_boundary = getReactorParam<boundary_id_type>(RGMB::top_boundary_id);
192  const auto bottom_boundary = getReactorParam<boundary_id_type>(RGMB::bottom_boundary_id);
193 
194  {
195  auto params = _app.getFactory().getValidParams("AdvancedExtruderGenerator");
196 
197  params.set<MeshGeneratorName>("input") = input_mesh_name;
198  params.set<Point>("direction") = Point(0, 0, 1);
199  params.set<std::vector<unsigned int>>("num_layers") =
200  getReactorParam<std::vector<unsigned int>>(RGMB::axial_mesh_intervals);
201  params.set<std::vector<Real>>("heights") = axial_boundaries;
202  params.set<BoundaryName>("bottom_boundary") = std::to_string(bottom_boundary);
203  params.set<BoundaryName>("top_boundary") = std::to_string(top_boundary);
204  addMeshSubgenerator("AdvancedExtruderGenerator", name() + "_extruded", params);
205  }
206 
207  {
208  auto params = _app.getFactory().getValidParams("RenameBoundaryGenerator");
209 
210  params.set<MeshGeneratorName>("input") = name() + "_extruded";
211  params.set<std::vector<BoundaryName>>("old_boundary") = {
212  std::to_string(top_boundary),
213  std::to_string(bottom_boundary)}; // hard coded boundary IDs in patterned mesh generator
214  params.set<std::vector<BoundaryName>>("new_boundary") = {"top", "bottom"};
215  addMeshSubgenerator("RenameBoundaryGenerator", name() + "_change_plane_name", params);
216  }
217 
218  const MeshGeneratorName output_mesh_name = name() + "_extrudedIDs";
219  {
220  auto params = _app.getFactory().getValidParams("PlaneIDMeshGenerator");
221 
222  params.set<MeshGeneratorName>("input") = name() + "_change_plane_name";
223 
224  std::vector<Real> plane_heights{0};
225  for (Real z : axial_boundaries)
226  plane_heights.push_back(z + plane_heights.back());
227 
228  params.set<std::vector<Real>>("plane_coordinates") = plane_heights;
229 
230  std::string plane_id_name = "plane_id";
231  params.set<std::string>("id_name") = "plane_id";
232 
233  addMeshSubgenerator("PlaneIDMeshGenerator", output_mesh_name, params);
234  }
235 
236  return output_mesh_name;
237 }
238 
239 std::vector<std::reference_wrapper<const CSG::CSGSurface>>
241  Real halfpitch,
242  CSG::CSGBase & csg_obj)
243 {
244  std::vector<std::reference_wrapper<const CSG::CSGSurface>> duct_surfaces;
245  const auto mesh_geometry = getReactorParam<std::string>(RGMB::mesh_geometry);
246  const auto n_azim_surfaces = mesh_geometry == "Square" ? 4 : 6;
247 
248  // Convert halfpitch to radius (distance from vertex to center)
249  const Real angle_offset_degrees = mesh_geometry == "Square" ? 45. : 30.;
250  const Real angle_offset_radians = angle_offset_degrees * (M_PI / 180.);
251  const auto radius = halfpitch / std::cos(angle_offset_radians);
252 
253  Real angle_increment_radians = 360. / n_azim_surfaces * (M_PI / 180.);
254 
255  for (const auto i : make_range(n_azim_surfaces))
256  {
257  const auto surf_name =
258  name() + "_radial_duct_" + std::to_string(radial_index) + "_surf_" + std::to_string(i);
259 
260  // Define 3 points on the surface
261  const auto current_angle = i * angle_increment_radians + angle_offset_radians;
262  const auto next_angle = (i + 1) * angle_increment_radians + angle_offset_radians;
263  libMesh::Point p0(radius * std::cos(current_angle), radius * std::sin(current_angle), 0.);
264  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  p2(2) = angle_offset_degrees;
268 
269  std::unique_ptr<CSG::CSGSurface> duct_surf_ptr =
270  std::make_unique<CSG::CSGPlane>(surf_name, p0, p1, p2);
271  const auto & duct_surf = csg_obj.addSurface(std::move(duct_surf_ptr));
272  duct_surfaces.push_back(duct_surf);
273  }
274 
275  return duct_surfaces;
276 }
277 
278 std::vector<std::reference_wrapper<const CSG::CSGSurface>>
280 {
281  std::vector<std::reference_wrapper<const CSG::CSGSurface>> surfaces_by_axial_region;
282  const auto axial_boundaries = getReactorParam<std::vector<Real>>(RGMB::axial_mesh_sizes);
283  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  auto axial_surf_name = RGMB::CSG_AXIAL_PLANE_PREFIX + "0";
288  const auto has_axial_surfaces = csg_obj.hasSurface(axial_surf_name);
289 
290  for (const auto i : make_range(axial_boundaries.size() + 1))
291  {
292  axial_surf_name = RGMB::CSG_AXIAL_PLANE_PREFIX + std::to_string(i);
293  if (has_axial_surfaces)
294  // Surface should exist in CSGBase, retrieve from object
295  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  axial_level += (i != 0) ? axial_boundaries[i - 1] : 0.;
300  std::unique_ptr<CSG::CSGSurface> plane_surf_ptr =
301  std::make_unique<CSG::CSGPlane>(axial_surf_name, 0, 0, 1, axial_level);
302  const auto & plane_surf = csg_obj.addSurface(std::move(plane_surf_ptr));
303  surfaces_by_axial_region.push_back(plane_surf);
304  }
305  }
306 
307  return surfaces_by_axial_region;
308 }
309 
310 const CSG::CSGLattice &
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  std::string lat_name = name() + "_lattice";
318  std::unique_ptr<CSG::CSGLattice> lat_ptr;
319  const auto mesh_geometry = getReactorParam<std::string>(RGMB::mesh_geometry);
320  if (mesh_geometry == "Square")
321  lat_ptr = std::make_unique<CSG::CSGCartesianLattice>(lat_name, pitch, pattern);
322  else // _geom_type == "Hex"
323  lat_ptr = std::make_unique<CSG::CSGHexagonalLattice>(lat_name, pitch, pattern);
324 
325  auto & assembly_lattice = csg_obj.addLattice(std::move(lat_ptr));
326  return assembly_lattice;
327 }
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
static void addDepletionIDParams(InputParameters &parameters)
std::unordered_map< dof_id_type, dof_id_type > getExtraIDUniqueCombinationMap(const MeshBase &mesh, const std::set< SubdomainID > &block_ids, std::vector< ExtraElementIDName > extra_ids)
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 addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static const std::string assembly_lattice
static const std::string CSG_AXIAL_PLANE_PREFIX
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...
T & set(const std::string &name, bool quiet_mode=false)
static const std::string mesh_geometry
const CSGSurface & getSurfaceByName(const std::string &name) const
void initializeReactorMeshParams(const std::string reactor_param_name)
Initializes and checks validity of ReactorMeshParams mesh generator object.
InputParameters getValidParams(const std::string &name) const
std::vector< std::reference_wrapper< const CSG::CSGSurface > > getAxialPlaneSurfaces(CSG::CSGBase &csg_obj)
Get CSGSurfaces corresponding to axial planes of the extruded RGMB mesh.
void addDepletionId(MeshBase &input_mesh, const MooseEnum &option, const DepletionIDGenerationLevel generation_level, const bool extrude)
add depletion IDs
static const std::string axial_mesh_sizes
Factory & getFactory()
const T & getReactorParam(const std::string &param_name)
Returns reference of parameter in ReactorMeshParams object.
const std::string & name() const
std::unique_ptr< MeshBase > * _reactor_params_mesh
The dummy param mesh that we need to clear once we&#39;ve generated (in freeReactorMeshParams) ...
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
MeshGeneratorName callExtrusionMeshSubgenerators(const MeshGeneratorName input_mesh_name)
Calls mesh subgenerators related to extrusion, renaming of top / bottom boundaries, and defining plane IDs.
static const std::string pitch
DepletionIDGenerationLevel
specify the depletion id is generated at which reactor generation level
void freeReactorParamsMesh()
Releases the mesh obtained in _reactor_params_mesh.
bool getCSGOnly() const
static const std::string top_boundary_id
MeshGeneratorName _reactor_params
The ReactorMeshParams object that is storing the reactor global information for this reactor geometry...
const LatticeType & addLattice(std::unique_ptr< LatticeType > lattice)
ReactorGeometryMeshBuilderBase(const InputParameters &parameters)
std::vector< std::reference_wrapper< const CSG::CSGSurface > > getOuterRadialSurfacesForUnitCell(unsigned int radial_index, Real halfpitch, CSG::CSGBase &csg_obj)
Get CSGSurfaces corresponding to hexagonal or square region with given halfpitch and centered around ...
const CSGSurface & addSurface(std::unique_ptr< CSGSurface > surf)
static InputParameters validParams()
bool hasSurface(const std::string &name) const
void freeReactorParamsCSG()
Releases the CSG base object obtained in _reactor_params_csg.
const double radius
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MooseApp & _app
std::unique_ptr< CSG::CSGBase > * _reactor_params_csg
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.
static const std::string axial_mesh_intervals
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
std::unique_ptr< CSG::CSGBase > & getCSGBaseByName(const MeshGeneratorName &mesh_generator_name)
static void setHasGenerateData(InputParameters &params)
void addClassDescription(const std::string &doc_string)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
MeshGeneratorSystem & getMeshGeneratorSystem()
static const std::string bottom_boundary_id
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)