https://mooseframework.inl.gov
Loading...
Searching...
No Matches
HexagonalGridPositions.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
12
14
17{
20 "Create positions along a hexagonal grid. Numbering of positions increases first "
21 "counterclockwise, then expanding outwards from the inner ring. "
22 "Inner-numbering is within a radial ring.");
23
24 params.addRequiredParam<Point>("center", "Center of the hexagonal grid");
26 "lattice_flat_to_flat",
27 "lattice_flat_to_flat>0",
28 "Distance between two (inner) opposite sides of a lattice. Also known as bundle pitch or "
29 "inner flat-to-flat distance");
30 params.addRequiredRangeCheckedParam<Real>("pin_pitch", "pin_pitch>0", "Distance between pins");
31 params.addRequiredRangeCheckedParam<unsigned int>("nr", "nr>0", "Number of hexagonal rings");
32 params.addParam<Real>("rotation_around_axis",
33 0.,
34 "Rotation angle to apply to the underlying hexagonal lattice (in degrees)");
35
36 params.addRangeCheckedParam<std::vector<std::vector<unsigned int>>>(
37 "pattern",
38 {},
39 "pattern>=0",
40 "A double-indexed hexagonal-shaped array starting with the upper-left corner. '-1's are not "
41 "selected as positions.");
42 params.addParam<std::vector<unsigned int>>(
43 "include_in_pattern", {}, "A vector of the numbers in the pattern to include");
44 params.addParam<std::vector<std::vector<int>>>(
45 "positions_pattern",
46 {},
47 "A double-indexed hexagonal-shaped array with the index of other Positions objects starting "
48 "with the upper-left corner. These positions objects will be distributed within the "
49 "hexagonal grid. The indexing is given in 'positions_pattern_indexing'. Use '-1' to discard "
50 "a position in the lattice.");
51 params.addParam<std::map<std::string, unsigned int>>(
52 "positions_pattern_indexing",
53 {},
54 "A map from the name of positions objects to their index in the 'positions_pattern'");
55
56 // Use user-provided ordering
57 params.set<bool>("auto_sort") = false;
58 // All functors defined on all processes for now
59 params.set<bool>("auto_broadcast") = false;
60
61 return params;
62}
63
65 : Positions(parameters),
66 _center(getParam<Point>("center")),
67 _lattice_flat_to_flat(getParam<Real>("lattice_flat_to_flat")),
68 _pin_pitch(getParam<Real>("pin_pitch")),
69 _z_axis_index(MooseEnum("X Y Z", "Z")),
70 _nr(getParam<unsigned int>("nr")),
71 _pattern(getParam<std::vector<std::vector<unsigned int>>>("pattern")),
72 _include_in_pattern(
73 std::set<unsigned int>(getParam<std::vector<unsigned int>>("include_in_pattern").begin(),
74 getParam<std::vector<unsigned int>>("include_in_pattern").end())),
75 _positions_pattern(getParam<std::vector<std::vector<int>>>("positions_pattern")),
76 _positions_pattern_indexing(
77 getParam<std::map<std::string, unsigned int>>("positions_pattern_indexing"))
78{
79 // Check dimensions
80 if (_nr == 1)
81 {
82 if (MooseUtils::absoluteFuzzyGreaterThan(_pin_pitch, _lattice_flat_to_flat))
83 paramError("lattice_flat_to_flat",
84 "For one ring, the lattice flat to flat must be at least the pin pitch");
85 }
86 else
87 {
88 if (MooseUtils::absoluteFuzzyGreaterThan((3 * _nr - 1) * _pin_pitch / sqrt(3),
90 paramError("lattice_flat_to_flat",
91 "Lattice flat to flat distance is less than the minimum (3 * nr - 1) * pin_pitch "
92 "/ sqrt(3) given nr rings with a pitch of pin_pitch");
93 }
94
95 // Check pattern and include_in_pattern
96 if ((_include_in_pattern.empty() && _pattern.size()) ||
97 (_include_in_pattern.size() && _pattern.empty()))
99 "include_in_pattern",
100 "The 'pattern' parameter and the 'include_in_pattern' must be both specified or both not "
101 "specified by the user.");
102 for (const auto include : _include_in_pattern)
103 {
104 bool found = false;
105 for (const auto & row : _pattern)
106 if (std::find(row.begin(), row.end(), include) != row.end())
107 found = true;
108 if (!found)
109 paramError("include_in_pattern",
110 "Pattern item '" + std::to_string(include) +
111 "' to include is not present in the pattern");
112 }
113
114 // Check positions_pattern and positions_pattern_indexing
115 if ((_positions_pattern.empty() && !_positions_pattern_indexing.empty()) ||
117 paramError("positions_pattern_indexing",
118 "The 'positions_pattern' parameter and the 'positions_pattern_indexing' must be "
119 "both specified or both not specified by the user.");
120 for (const auto & [pos_name, index] : _positions_pattern_indexing)
121 {
122 bool found = false;
123 for (const auto & row : _positions_pattern)
124 if (std::find(row.begin(), row.end(), index) != row.end())
125 found = true;
126 if (!found)
127 paramError("include_in_pattern",
128 "Pattern item '" + pos_name + "' with index '" + std::to_string(index) +
129 "' to include is not present in the pattern");
130 }
131
132 // Check incompatible parameters
133 if (((_positions_pattern.size() && _positions_pattern[0].size()) ||
135 ((_pattern.size() && _pattern[0].size()) || _include_in_pattern.size()))
136 paramError("positions_pattern",
137 "'pattern'/'include_in_pattern' are not supported in combination with "
138 "'positions_pattern/positions_pattern_indexing'. Only one pattern is supported");
139
140 // Obtain the positions by unrolling the patterns
141 initialize();
142 // Sort if needed (user-specified)
143 finalize();
144}
145
146void
148{
150
151 // We make very large pins so they cover the entire position
152 _hex_latt = std::make_unique<HexagonalLatticeUtils>(_lattice_flat_to_flat,
155 0.,
156 1.,
157 _nr,
159 getParam<Real>("rotation_around_axis"));
160
161 if (!isParamSetByUser("positions_pattern"))
162 {
163 // Unroll pattern
164 std::vector<int> pattern_unrolled;
165
166 if (_pattern.size())
167 {
168 // Check number of pins in pattern
169 std::size_t pattern_size = 0;
170 for (const auto & row : _pattern)
171 pattern_size += row.size();
172 if (_pattern.size() != cast_int<std::size_t>(2 * _nr - 1))
173 mooseError("Number of rows in pattern (",
174 _pattern.size(),
175 ") should be equal to twice the number of hexagonal rings minus one");
176 if (pattern_size != _hex_latt->totalPins(_nr))
177 mooseError("Pattern size (",
178 pattern_size,
179 ") does not match the number of pins with ",
180 _nr,
181 " rings: ",
182 _hex_latt->totalPins(_nr));
183
184 pattern_unrolled.resize(_hex_latt->totalPins(_nr));
185 unsigned int i = 0;
186 for (const auto r_i : make_range(_nr))
187 for (const auto a_i : make_range(_hex_latt->pins(r_i + 1)))
188 {
189 libmesh_ignore(a_i);
190 unsigned int row_i, within_row_i;
191 _hex_latt->get2DInputPatternIndex(i, row_i, within_row_i);
192 pattern_unrolled[i++] = _pattern[row_i][within_row_i];
193 }
194 }
195 // just needs to be the right size
196 else
197 pattern_unrolled.resize(_hex_latt->totalPins(_nr), 0);
198
199 // Count the number of positions we do not need to include
200 unsigned int n_exclusions = 0;
201 if (_include_in_pattern.size())
202 for (const auto patt : pattern_unrolled)
203 if (_include_in_pattern.count(patt) == 0)
204 n_exclusions++;
205
206 // Size array, remove the '-1' / not included positions
207 const auto n_positions = cast_int<std::size_t>(_hex_latt->totalPins(_nr) - n_exclusions);
208 _positions.resize(n_positions);
209
210 // Fill the positions by retrieving the pin centers at indices included in the pattern (if
211 // specified)
212 unsigned int pos_i = 0;
213 for (const auto patt_i : index_range(pattern_unrolled))
214 if (!_pattern.size() || !_include_in_pattern.size() ||
215 _include_in_pattern.count(pattern_unrolled[patt_i]))
216 _positions[pos_i++] = _hex_latt->pinCenters()[patt_i];
217 }
218 else
219 {
220 // Unroll pattern into positions array
221 const bool initial = _fe_problem.getCurrentExecuteOnFlag() == EXEC_INITIAL;
222
223 // Check number of positions in pattern of nested positions
224 unsigned pattern_size = 0;
225 for (const auto & row : _positions_pattern)
226 pattern_size += row.size();
227 if (_positions_pattern.size() != cast_int<std::size_t>(2 * _nr - 1))
228 mooseError("Number of rows in 'positions_pattern' (",
229 _pattern.size(),
230 ") should be equal to twice the number of hexagonal rings minus one");
231 if (pattern_size != _hex_latt->totalPins(_nr))
232 mooseError("Pattern size ",
233 pattern_size,
234 " does not match the number of pins with ",
235 _nr,
236 " rings: ",
237 _hex_latt->totalPins(_nr));
238
239 // Check that all the positions names are valid
240 unsigned num_pos = 0;
241 for (const auto & [pos_name, index] : _positions_pattern_indexing)
242 if (_fe_problem.hasUserObject(pos_name))
243 num_pos += _fe_problem.getPositionsObject(pos_name).getNumPositions(initial);
244 _positions.reserve(num_pos);
245
246 // Invert map from positions to indices
247 std::map<unsigned int, PositionsName> index_to_pos;
248 for (const auto & [pos_name, index] : _positions_pattern_indexing)
249 index_to_pos[index] = pos_name;
250
251 // Unroll pattern : the positions vector is 1D and should be
252 std::vector<PositionsName> pattern_unrolled;
253 pattern_unrolled.resize(_hex_latt->totalPins(_nr));
254 unsigned int i = 0;
255 for (const auto r_i : make_range(_nr))
256 for (const auto a_i : make_range(_hex_latt->pins(r_i + 1)))
257 {
258 libmesh_ignore(a_i);
259 unsigned int row_i, within_row_i;
260 _hex_latt->get2DInputPatternIndex(i, row_i, within_row_i);
261 const auto pos_index = _positions_pattern[row_i][within_row_i];
262 if (auto it = index_to_pos.find(cast_int<unsigned int>(pos_index));
263 it != index_to_pos.end())
264 pattern_unrolled[i++] = it->second;
265 else if (pos_index != -1)
266 paramError("positions_pattern",
267 "Index '" + std::to_string(pos_index) +
268 "' in pattern is not found in 'positions_pattern_indexing'");
269 else
270 pattern_unrolled[i++] = "-1";
271 }
272
273 // Now place the positions in the _positions array with the offset from the parent lattice index
274 for (const auto patt_i : index_range(pattern_unrolled))
275 {
276 const auto & pos_name = pattern_unrolled[patt_i];
277 if (pos_name != "-1")
278 for (const auto & pos : _fe_problem.getPositionsObject(pos_name).getPositions(initial))
279 _positions.push_back(_hex_latt->pinCenters()[patt_i] + pos);
280 }
281 }
282
283 _initialized = true;
284}
registerMooseObject("ReactorApp", HexagonalGridPositions)
const ExecFlagType EXEC_INITIAL
void ErrorVector unsigned int
const Positions & getPositionsObject(const std::string &name) const
bool hasUserObject(const std::string &name) const
const ExecFlagType & getCurrentExecuteOnFlag() const
Creates positions (points) following an hexagonal grid.
const MooseEnum _z_axis_index
Axial component for the Z axis.
std::map< std::string, unsigned int > _positions_pattern_indexing
Indexing of the positions objects in the pattern.
std::vector< std::vector< int > > _positions_pattern
List of positions objects, the positions of which are translated in the parent hexagonal pattern.
HexagonalGridPositions(const InputParameters &parameters)
const unsigned int _nr
Number of rings in the radial direction.
const Real _lattice_flat_to_flat
Distance from one side to the one facing it of the lattice.
std::unique_ptr< HexagonalLatticeUtils > _hex_latt
Hexagonal lattice utility object.
static InputParameters validParams()
std::set< unsigned int > _include_in_pattern
List of the pattern locations to include. Include all if empty.
const Real _pin_pitch
Pitch between fuel pins.
std::vector< std::vector< unsigned int > > _pattern
2D pattern of the pins to select (if specified)
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
bool isParamSetByUser(const std::string &name) const
void mooseError(Args &&... args) const
unsigned int getNumPositions(bool initial=false) const
void clearPositions()
std::vector< Point > & _positions
const std::vector< Point > & getPositions(bool initial) const
static InputParameters validParams()
virtual void finalize() override
bool _initialized
FEProblemBase & _fe_problem