https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CSGHexagonalLattice.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 "CSGHexagonalLattice.h"
11
12namespace CSG
13{
14
16 const std::string & name,
17 Real pitch,
18 std::vector<std::vector<std::reference_wrapper<const CSGUniverse>>> universes,
19 const std::optional<OuterVariant> & outer)
20 : CSGLattice(name, outer), _pitch(pitch)
21{
22 setUniverses(universes); // this will set _nrow
23 if (_pitch < 0)
24 mooseError("Lattice " + getName() + " must have pitch greater than 0.");
25}
26
28 Real pitch,
29 const std::optional<OuterVariant> & outer)
30 : CSGLattice(name, outer), _pitch(pitch), _nrow(0), _nring(0)
31{
32 if (_pitch < 0)
33 mooseError("Lattice " + getName() + " must have pitch greater than 0.");
34}
35
36bool
38 std::vector<std::vector<std::reference_wrapper<const CSGUniverse>>> universes) const
39{
40 if (universes.size() < 1) // need at least one row
41 return false;
42
43 if (universes.size() % 2 == 0) // must be odd number of rows
44 return false;
45
46 // each row differs in how many elements are required depending on size of lattice
47 unsigned int num_row = universes.size();
48 unsigned int center_row = (num_row - 1) / 2;
49 for (unsigned int row_i : index_range(universes))
50 {
51 unsigned int n_ele =
52 num_row - ((row_i > center_row) ? (row_i - center_row) : (center_row - row_i));
53 if (universes[row_i].size() != n_ele)
54 return false;
55 }
56
57 return true;
58}
59
60void
62 std::vector<std::vector<std::reference_wrapper<const CSGUniverse>>> universes)
63{
64 // check for valid map arrangment
65 if (!isValidUniverseMap(universes))
66 mooseError("Cannot set lattice " + getName() +
67 " with universes. Does not have valid dimensions for lattice type " + getType());
68 // set attributes based on universe map (in case they differ from original values)
69 _nrow = universes.size();
71 _universe_map = universes;
73}
74void
76{
77 if (pitch < 0)
78 mooseError("Lattice " + getName() + " must have pitch greater than 0.");
79 _pitch = pitch;
80}
81
82std::unordered_map<std::string, AttributeVariant>
84{
85 return {{"nrow", static_cast<unsigned int>(_nrow)},
86 {"nring", static_cast<unsigned int>(_nring)},
87 {"pitch", _pitch}};
88}
89
90bool
91CSGHexagonalLattice::isValidIndex(const std::pair<int, int> index) const
92{
93 auto row = index.first; // row index
94 auto ele = index.second; // column index within the row
95
96 // Check if row is valid (0 <= row < _nrow)
97 if (row < 0 || row >= (int)_nrow)
98 return false;
99
100 // Calculate maximum number of elements in this specific row
101 auto center_row = (_nrow - 1) / 2; // center row index
102 int max_ele = _nrow - std::abs((int)(row - center_row));
103
104 // Check if column index is valid for this row
105 return !(ele < 0 || ele >= max_ele);
106}
107
108bool
110{
111 if (other.getType() != this->getType())
112 return false;
113
114 auto this_dims = this->getAttributes();
115 auto other_dims = other.getAttributes();
116 if (std::get<unsigned int>(this_dims["nrow"]) != std::get<unsigned int>(other_dims["nrow"]))
117 return false;
118 if (std::get<unsigned int>(this_dims["nring"]) != std::get<unsigned int>(other_dims["nring"]))
119 return false;
120 if (std::get<Real>(this_dims["pitch"]) != std::get<Real>(other_dims["pitch"]))
121 return false;
122 return true;
123}
124
125void
127{
128 for (const auto ring : make_range(_nring))
129 {
130 unsigned int num_elements = (ring == _nring - 1) ? 1 : 6 * (_nring - 1 - ring);
131 for (const auto element : make_range(num_elements))
132 {
133 std::pair<unsigned int, unsigned int> ring_index = std::make_pair(ring, element);
134 std::pair<unsigned int, unsigned int> row_index = getRowIndexFromRingIndex(ring_index);
135 _row_to_ring_map[row_index] = ring_index;
136 }
137 }
138}
139
140std::pair<int, int>
141CSGHexagonalLattice::getRowIndexFromRingIndex(const std::pair<int, int> & ring_ele_index) const
142{
143 auto og_ring = ring_ele_index.first; // ring corresponds to the outermost ring as ring 0
144 int ring = _nring - og_ring - 1; // convert to internal indexing (0 as innermost ring)
145 auto element = ring_ele_index.second;
146
147 if (og_ring < 0 || og_ring >= (int)_nring)
148 mooseError("Ring " + std::to_string(og_ring) + " is not valid for hexagonal lattice " +
149 getName());
150 if (element < 0 || element >= (ring == 0 ? 1 : 6 * ring))
151 mooseError("Position " + std::to_string(element) + " is not valid for ring " +
152 std::to_string(og_ring) + " in hexagonal lattice " + getName());
153
154 // Calculate the center row and column indices
155 int center_row = (_nrow - 1) / 2;
156 int center_col = center_row;
157
158 // Special case for the center element
159 if (ring == 0)
160 return {center_row, center_col};
161
162 // Calculate the side length of the hexagon for the given ring
163 int side_length = ring;
164
165 // Determine which side of the hexagon the element is on and get row/col from this
166 int side = element / side_length;
167 int offset = element % side_length; // position within the side moving counter-clockwise
168 int row, col;
169
170 // lamba to calculate the number of columns in any given row
171 auto calc_num_cols_in_row = [&](int r) { return _nrow - std::abs(center_row - r); };
172
173 // diagram of side numbers:
174 // 4
175 // _______
176 // / \*
177 // 3 / \ 5
178 // / \*
179 // \ /
180 // 2 \ / 0
181 // \ _______ /
182 // 1
183 switch (side)
184 {
185 case 0: // bottom right (contains starting position of the ring)
186 row = center_row + offset;
187 col = calc_num_cols_in_row(row) - og_ring - 1;
188 break;
189 case 1: // bottom
190 row = center_row + ring;
191 col = calc_num_cols_in_row(row) - og_ring - 1 - offset;
192 break;
193 case 2: // bottom left
194 row = center_row + (side_length - offset);
195 col = center_col - ring;
196 break;
197 case 3: // top left
198 row = center_row - offset;
199 col = center_col - ring;
200 break;
201 case 4: // top
202 row = center_row - ring;
203 col = center_col - ring + offset;
204 break;
205 case 5: // top right
206 row = center_row - (side_length - offset);
207 col = calc_num_cols_in_row(row) - og_ring - 1;
208 break;
209 default:
210 mooseError("Invalid side ID calculation in hexagonal lattice " + getName());
211 }
212
213 mooseAssert(isValidIndex(std::make_pair(row, col)),
214 "Calculated index (" + std::to_string(row) + ", " + std::to_string(col) +
215 ") is not valid for hexagonal lattice " + getName());
216
217 return {row, col};
218}
219
220std::pair<int, int>
221CSGHexagonalLattice::getRingIndexFromRowIndex(const std::pair<int, int> & row_col_index) const
222{
223 if (!isValidIndex(row_col_index))
224 mooseError("Index (" + std::to_string(row_col_index.first) + ", " +
225 std::to_string(row_col_index.second) +
226 ") is not a valid index for hexagonal "
227 "lattice " +
228 getName());
229
230 return _row_to_ring_map.at(row_col_index);
231}
232
234
235unsigned int
236nRowToRing(int nrow)
237{
238 if (nrow == 0) // special case
239 return 0;
240 std::string base_msg = "Cannot convert number of rows " + std::to_string(nrow) +
241 " to number of rings in hexagonal lattice. ";
242 if (nrow < 0)
243 mooseError(base_msg + "Number of rows must be >= 0.");
244 if (nrow % 2 == 0)
245 mooseError(base_msg + "Number of rows must be odd.");
246 return (nrow + 1) / 2;
247}
248
249unsigned int
250nRingToRow(int nring)
251{
252 if (nring == 0) // special case
253 return 0;
254 if (nring < 0)
255 mooseError("Cannot convert number of rings " + std::to_string(nring) +
256 " to number of rows in hexagonal lattice. Number of rings must be >= 0.");
257 return 2 * nring - 1;
258}
259
260} // namespace CSG
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int _nring
number of rings in the hexagonal lattice, should be consistent with the number of rows
Real _pitch
lattice pitch (flat-to-flat distance between adjacent hex elements)
void buildIndexMap()
build a mapping of row-column indices to ring-position indices for quick conversion and look-up.
virtual bool compareAttributes(const CSGLattice &other) const override
compare the attributes returned in getAttributes of this lattice to another lattice
std::map< std::pair< unsigned int, unsigned int >, std::pair< unsigned int, unsigned int > > _row_to_ring_map
map of row-column indices to ring-position indices for quick conversion and look-up
virtual bool isValidIndex(const std::pair< int, int > index) const override
check if provided index in row-column form is valid for the given hexagonal lattice
unsigned int _nrow
number of rows in the hexagonal lattice (must be odd), should be consistent with the number of rings
std::pair< int, int > getRowIndexFromRingIndex(const std::pair< int, int > &row_col_index) const
Given an index in ring-position form, get the corresponding row-column index.
CSGHexagonalLattice(const std::string &name, Real pitch, std::vector< std::vector< std::reference_wrapper< const CSGUniverse > > > universes, const std::optional< OuterVariant > &outer=std::nullopt)
Construct a new CSGHexagonalLattice from a map of universes.
virtual std::unordered_map< std::string, AttributeVariant > getAttributes() const override
Get attributes that define the lattice (excluding the universe map).
std::pair< int, int > getRingIndexFromRowIndex(const std::pair< int, int > &row_col_index) const
Given an index in row-column form, get the corresponding ring-position index.
virtual bool isValidUniverseMap(std::vector< std::vector< std::reference_wrapper< const CSGUniverse > > > universes) const override
check if the arrangement of the provided universes is valid for the hexagonal lattice given the numbe...
void setPitch(Real pitch)
set the pitch of the lattice
virtual void setUniverses(std::vector< std::vector< std::reference_wrapper< const CSGUniverse > > > universes) override
set the universes that define the lattice layout
CSGLattice is the abstract class for defining lattices.
Definition CSGLattice.h:35
const std::string & getName() const
Get the name of lattice.
Definition CSGLattice.h:60
virtual std::unordered_map< std::string, AttributeVariant > getAttributes() const =0
Get attributes that define the lattice (excluding the universe map).
const std::string getType() const
Get the lattice type.
Definition CSGLattice.h:67
std::vector< std::vector< std::reference_wrapper< const CSGUniverse > > > _universe_map
Universes in the arrangement of how they appear in the lattice; dimensions depends on lattice type.
Definition CSGLattice.h:223
unsigned int nRowToRing(int nrow)
methods to help convert between number of rows and rings get the total number of rings from the numbe...
unsigned int nRingToRow(int nring)
get the total number of rows from the number of rings