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 : }
|