https://mooseframework.inl.gov
Loading...
Searching...
No Matches
DuctedPinEngUnit.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://www.mooseframework.org
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 "DuctedPinEngUnit.h"
11#include "PinUniverseEngUnit.h"
12#include "CSGNPolygonUnit.h"
13#include "CSGUtils.h"
14#include "CSGPlane.h"
15
16namespace CSG
17{
18
20 const std::string & geometry_type,
21 const std::vector<Real> & ring_radii,
22 const std::vector<Real> & duct_apothems,
23 const std::vector<std::vector<std::string>> & region_names,
24 const std::vector<Real> & axial_plane_levels,
25 const std::vector<std::string> & axial_plane_names)
27 _ring_radii(ring_radii),
28 _duct_apothems(duct_apothems),
29 _region_names(region_names),
30 _axial_plane_levels(axial_plane_levels),
31 _axial_plane_names(axial_plane_names)
32{
33 // Check radii in ascending order
34 if (_ring_radii.size() > 1)
35 for (const auto i : make_range(_ring_radii.size() - 1))
36 if (_ring_radii[i] >= _ring_radii[i + 1])
38 "Ducted pin engineering unit must have ring radii defined in strictly ascending order");
39
40 // Check duct apothems in ascending order
41 if (_duct_apothems.size() > 1)
42 for (const auto i : make_range(_duct_apothems.size() - 1))
43 if (_duct_apothems[i] >= _duct_apothems[i + 1])
44 mooseError("Ducted pin engineering unit must have duct apothems defined in strictly "
45 "ascending order");
46
47 // Check axial plane levels in ascending order
48 if (_axial_plane_levels.size() > 1)
49 for (const auto i : make_range(_axial_plane_levels.size() - 1))
51 mooseError("Ducted pin engineering unit must have axial plane levels defined in strictly "
52 "ascending order");
53
54 // Check size of axial plane names
55 if (_axial_plane_levels.size() != _axial_plane_names.size())
56 mooseError("Size of axial plane levels must match size of axial plane names");
57
58 // Check size of region ids
59 unsigned int n_axial = _axial_plane_levels.size() + 1;
60 if (_region_names.size() != n_axial)
61 mooseError("Size of region IDs must be one larger than the number of axial levels");
62
63 unsigned int n_radial = _ring_radii.size() + _duct_apothems.size() + 1;
64 for (const auto & region_names_radial : _region_names)
65 if (region_names_radial.size() != n_radial)
66 mooseError("Size of each entry in region IDs must be one larger than the number of radial "
67 "zones in pin");
68
69 _geometry_type = geometry_type;
70}
71
72std::unordered_map<std::string, AttributeVariant>
74{
75 std::unordered_map<std::string, AttributeVariant> attr_map{
76 {"duct_apothems", _duct_apothems},
77 {"ring_radii", _ring_radii},
78 {"region_names", _region_names},
79 {"geometry_type", getGeometryTypeString()}};
80 if (_axial_plane_levels.size())
81 attr_map["axial_plane_levels"] = _axial_plane_levels;
82 return attr_map;
83}
84
85std::unique_ptr<CSGUniverseEngUnit>
87{
88 return std::make_unique<DuctedPinEngUnit>(_name,
95}
96
97void
99{
100 const auto has_axial_levels = _axial_plane_levels.size() > 0;
101 unsigned int n_axial = _axial_plane_levels.size() + 1;
102 unsigned int n_ring = _ring_radii.size();
103 std::vector<std::reference_wrapper<const CSG::PinUniverseEngUnit>> pin_units_by_axial_region;
104
105 // Define pin universe engineering units for each axial level
106 if (n_ring)
107 {
108 for (const auto i : make_range(n_axial))
109 {
110 auto unit_name = _name + "_pin_unit";
111 if (has_axial_levels)
112 unit_name += "_axial_" + std::to_string(i);
113 std::vector<std::string> pin_fill_mats;
114 for (const auto j : make_range(n_ring + 1))
115 pin_fill_mats.push_back(_region_names[i][j]);
116 // Create a PinUniverseEngUnit engineering unit and add it to CSGBase
117 std::unique_ptr<CSG::PinUniverseEngUnit> pin_ptr =
118 std::make_unique<CSG::PinUniverseEngUnit>(unit_name, _ring_radii, pin_fill_mats);
119 auto & pin_unit = _internal_base->addEngUnit(std::move(pin_ptr));
120 pin_units_by_axial_region.push_back(pin_unit);
121 }
122 }
123
124 // Define CSGNPolygonUnit representing each duct unit and define all radial regions
125 // created by the ducts
126 std::vector<CSG::CSGRegion> radial_regions;
127 CSG::CSGRegion inner_region, outer_region, radial_region;
128 std::vector<std::reference_wrapper<const CSG::CSGNPolygonUnit>> duct_units_by_radial_region;
129 for (const auto i : index_range(_duct_apothems))
130 {
131 const auto unit_name = _name + "_radial_duct_" + std::to_string(i);
132 const auto n_sides = (getGeometryTypeString() == "Hex") ? 6 : 4;
133 std::unique_ptr<CSG::CSGNPolygonUnit> duct_ptr =
134 std::make_unique<CSG::CSGNPolygonUnit>(unit_name, n_sides, _duct_apothems[i]);
135 auto & duct_unit = _internal_base->addEngUnit(std::move(duct_ptr));
136 duct_units_by_radial_region.push_back(duct_unit);
137
138 if (i == 0)
139 {
140 // We are in the innermost radial region, the radial region is inner_region
141 inner_region = -duct_unit;
142 radial_region = inner_region;
143 }
144 else
145 {
146 // For all other regions, the radial region is the intersection of inner_region and
147 // outer_region
148 outer_region = ~inner_region;
149 inner_region = -duct_unit;
150 radial_region = inner_region & outer_region;
151 }
152 radial_regions.push_back(radial_region);
153 }
154
155 // Define outermost region
156 radial_region = radial_regions.empty() ? outer_region : ~inner_region;
157 radial_regions.push_back(radial_region);
158
159 // Define all axial surfaces and regions
160 std::vector<CSG::CSGRegion> axial_regions;
161 std::vector<std::reference_wrapper<const CSG::CSGSurface>> surfaces_by_axial_region;
162 if (has_axial_levels)
163 for (const auto i : make_range(n_axial))
164 {
165 // Create the axial plane and add it to _internal_base
166 if (i != _axial_plane_levels.size())
167 {
168 auto axial_level = _axial_plane_levels[i];
169 auto axial_surf_name = _axial_plane_names[i];
170 std::unique_ptr<CSG::CSGSurface> plane_surf_ptr =
171 std::make_unique<CSG::CSGPlane>(axial_surf_name, 0, 0, 1, axial_level);
172 const auto & plane_surf = _internal_base->addSurface(std::move(plane_surf_ptr));
173 surfaces_by_axial_region.push_back(plane_surf);
174 }
175
176 // Define each axial region. This will be one more than the number of axial planes
177 CSG::CSGRegion axial_region;
178 const auto & current_surf = surfaces_by_axial_region.back().get();
179 if (i == 0)
180 // First axial region is the negative halfspace of the first plane
181 axial_region = -current_surf;
182 else if (i == _axial_plane_levels.size())
183 // Last axial region is the positive halfspace of the last plane
184 axial_region = +current_surf;
185 else
186 {
187 // All other axial regions are the intersection of the negative halfspace
188 // of the current plane and the positive halfspace of the previous plane
189 const auto & prev_surf = surfaces_by_axial_region[i - 1].get();
190 axial_region = -current_surf & +prev_surf;
191 }
192 axial_regions.push_back(axial_region);
193 }
194
195 // Define all cells within pin domain and add to root universe of engineering unit
196 for (const auto i : index_range(radial_regions))
197 {
198 const unsigned int radial_index = _ring_radii.size() + i;
199 for (const auto j : make_range(has_axial_levels ? axial_regions.size() : 1))
200 {
201 auto cell_region = radial_regions[i];
202 auto cell_name = _name + "_cell_radial_" + std::to_string(i);
203 if (has_axial_levels)
204 {
205 // update name and region with axial info only if extruded
206 const auto axial_region = axial_regions[j];
207 if (cell_region.getRegionType() != CSG::CSGRegion::RegionType::EMPTY)
208 cell_region &= axial_region;
209 else
210 cell_region = axial_region;
211 cell_name += "_axial_" + std::to_string(j);
212 }
213 if (i == 0 && n_ring > 0)
214 // For first radial region where pin rings exist, we fill cell with pin universe unit
215 _internal_base->createCell(cell_name, pin_units_by_axial_region[j], cell_region);
216 else
217 {
218 // Otherwise, we fill the region with a material fill based on the region name
219 const auto mat_name = _region_names[j][radial_index];
220 _internal_base->createCell(cell_name, mat_name, cell_region);
221 }
222 }
223 }
224}
225
226} // namespace CSG
void mooseError(Args &&... args)
const std::string name
Definition Setup.h:21
std::unique_ptr< CSGBase > _internal_base
DuctedPinEngUnit(const std::string &name, const std::string &geometry_type, const std::vector< Real > &ring_radii, const std::vector< Real > &duct_apothems, const std::vector< std::vector< std::string > > &region_names, const std::vector< Real > &axial_plane_levels, const std::vector< std::string > &axial_plane_names)
Constructor for DuctedPinEngUnit.
std::unique_ptr< CSGUniverseEngUnit > clone() const override
Return a deep copy of this unit.
std::vector< Real > _axial_plane_levels
Axial plane levels for an extruded pin cell.
void expandUnit() override
Represent the pin cell as a single universe that contains cells that define each region of the pin ce...
const std::string getGeometryTypeString() const
Get the geometry type as a string.
MooseEnum _geometry_type
Geometry type of pin cell structure (hex or square)
std::unordered_map< std::string, AttributeVariant > getAttributes() const override
Return the pin engeering unit attributes for this object.
std::vector< std::vector< std::string > > _region_names
Region IDs of pin cell.
const std::vector< Real > _ring_radii
List of ring radii of pin cell.
const std::vector< Real > _duct_apothems
List of duct apothems of pin cell.
std::vector< std::string > _axial_plane_names
Axial plane names for an extruded pin cell.