https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
SCMDetailedTriAssemblyMeshGenerator Class Reference

Mesh generator that builds a 3D mesh representing triangular subchannels and pins. More...

#include <SCMDetailedTriAssemblyMeshGenerator.h>

Inheritance diagram for SCMDetailedTriAssemblyMeshGenerator:
[legend]

Public Types

typedef DataFileName DataFileParameterType
 

Public Member Functions

 SCMDetailedTriAssemblyMeshGenerator (const InputParameters &parameters)
 
virtual std::unique_ptr< MeshBase > generate () override
 
std::unique_ptr< CSG::CSGBasegenerateInternalCSG ()
 
std::unique_ptr< MeshBase > generateInternal ()
 
const std::set< MeshGeneratorName > & getRequestedMeshGenerators () const
 
const std::set< MeshGeneratorName > & getRequestedMeshGeneratorsForSub () const
 
void addParentMeshGenerator (const MeshGenerator &mg, const AddParentChildKey)
 
void addChildMeshGenerator (const MeshGenerator &mg, const AddParentChildKey)
 
const std::set< const MeshGenerator *, Comparator > & getParentMeshGenerators () const
 
const std::set< const MeshGenerator *, Comparator > & getChildMeshGenerators () const
 
const std::set< const MeshGenerator *, Comparator > & getSubMeshGenerators () const
 
bool isParentMeshGenerator (const MeshGeneratorName &name, const bool direct=true) const
 
bool isChildMeshGenerator (const MeshGeneratorName &name, const bool direct=true) const
 
bool isNullMeshName (const MeshGeneratorName &name) const
 
bool hasSaveMesh () const
 
bool hasOutput () const
 
const std::string & getSavedMeshName () const
 
bool hasGenerateData () const
 
bool hasGenerateCSG () const
 
bool isDataOnly () const
 
virtual bool enabled () const
 
std::shared_ptr< MooseObjectgetSharedPtr ()
 
std::shared_ptr< const MooseObjectgetSharedPtr () const
 
bool isKokkosObject () const
 
MooseAppgetMooseApp () const
 
const std::string & type () const
 
const std::string & name () const
 
std::string typeAndName () const
 
MooseObjectParameterName uniqueParameterName (const std::string &parameter_name) const
 
MooseObjectName uniqueName () const
 
const InputParametersparameters () const
 
const hit::Node * getHitNode () const
 
bool hasBase () const
 
const std::string & getBase () const
 
const TgetParam (const std::string &name) const
 
std::vector< std::pair< T1, T2 > > getParam (const std::string &param1, const std::string &param2) const
 
const TqueryParam (const std::string &name) const
 
const TgetRenamedParam (const std::string &old_name, const std::string &new_name) const
 
T getCheckedPointerParam (const std::string &name, const std::string &error_string="") const
 
bool isParamValid (const std::string &name) const
 
bool isParamSetByUser (const std::string &name) const
 
void connectControllableParams (const std::string &parameter, const std::string &object_type, const std::string &object_name, const std::string &object_parameter) const
 
void paramError (const std::string &param, Args... args) const
 
void paramWarning (const std::string &param, Args... args) const
 
void paramWarning (const std::string &param, Args... args) const
 
void paramInfo (const std::string &param, Args... args) const
 
std::string messagePrefix (const bool hit_prefix=true) const
 
std::string errorPrefix (const std::string &) const
 
void mooseError (Args &&... args) const
 
void mooseDocumentedError (const std::string &repo_name, const unsigned int issue_num, Args &&... args) const
 
void mooseErrorNonPrefixed (Args &&... args) const
 
void mooseWarning (Args &&... args) const
 
void mooseWarning (Args &&... args) const
 
void mooseWarningNonPrefixed (Args &&... args) const
 
void mooseWarningNonPrefixed (Args &&... args) const
 
void mooseDeprecated (Args &&... args) const
 
void mooseDeprecated (Args &&... args) const
 
void mooseDeprecatedNoTrace (Args &&... args) const
 
void mooseInfo (Args &&... args) const
 
void callMooseError (std::string msg, const bool with_prefix, const hit::Node *node=nullptr, const bool show_trace=true) const
 
std::string getDataFileName (const std::string &param) const
 
std::string getDataFileNameByName (const std::string &relative_path) const
 
std::string getDataFilePath (const std::string &relative_path) const
 
const Parallel::Communicator & comm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Static Public Member Functions

static InputParameters validParams ()
 
static bool hasGenerateData (const InputParameters &params)
 
static bool hasGenerateCSG (const InputParameters &params)
 
static void callMooseError (MooseApp *const app, const InputParameters &params, std::string msg, const bool with_prefix, const hit::Node *node, const bool show_trace=true)
 
static void setHasGenerateData (InputParameters &params)
 
static void setHasGenerateCSG (InputParameters &params)
 

Public Attributes

 usingCombinedWarningSolutionWarnings
 
const ConsoleStream _console
 

Static Public Attributes

static const std::string data_only_param
 
static const std::string type_param
 
static const std::string name_param
 
static const std::string unique_name_param
 
static const std::string app_param
 
static const std::string moose_base_param
 
static const std::string kokkos_object_param
 
static constexpr auto SYSTEM
 
static constexpr auto NAME
 

Protected Member Functions

EChannelType getSubchannelType (unsigned int index) const
 returns the type of the subchannel given the index
 
Point rotatePoint (Point b, Real theta)
 rotate a point by theta radians about the origin
 
void generatePin (std::unique_ptr< MeshBase > &mesh_base, const Point &center)
 Generate one detailed fuel pin volume centered at the supplied point.
 
Point getPinPosition (unsigned int i)
 returns the position of pin given pin index
 
std::vector< Real > getSubchannelPosition (unsigned int i)
 returns the position of subchannel given pin index
 
std::vector< unsigned intgetSubChannelPins (unsigned int i)
 returns the index of neighboring pins given subchannel index
 
virtual void generateData ()
 
virtual std::unique_ptr< CSG::CSGBasegenerateCSG ()
 
TcopyMeshProperty (const std::string &target_data_name, const std::string &source_data_name, const std::string &source_mesh)
 
TcopyMeshProperty (const std::string &source_data_name, const std::string &source_mesh)
 
std::unique_ptr< MeshBase > & getMesh (const std::string &param_name, const bool allow_invalid=false)
 
std::vector< std::unique_ptr< MeshBase > * > getMeshes (const std::string &param_name)
 
std::unique_ptr< MeshBase > & getMeshByName (const MeshGeneratorName &mesh_generator_name)
 
std::vector< std::unique_ptr< MeshBase > * > getMeshesByName (const std::vector< MeshGeneratorName > &mesh_generator_names)
 
std::unique_ptr< CSG::CSGBase > & getCSGBase (const std::string &param_name)
 
std::unique_ptr< CSG::CSGBase > & getCSGBaseByName (const MeshGeneratorName &mesh_generator_name)
 
std::vector< std::unique_ptr< CSG::CSGBase > * > getCSGBases (const std::string &param_name)
 
std::vector< std::unique_ptr< CSG::CSGBase > * > getCSGBasesByName (const std::vector< MeshGeneratorName > &mesh_generator_names)
 
void declareMeshForSub (const std::string &param_name)
 
void declareMeshesForSub (const std::string &param_name)
 
void declareMeshForSubByName (const MeshGeneratorName &mesh_generator_name)
 
void declareMeshesForSubByName (const std::vector< MeshGeneratorName > &mesh_generator_names)
 
std::unique_ptr< MeshBase > buildMeshBaseObject (unsigned int dim=libMesh::invalid_uint)
 
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh (unsigned int dim=libMesh::invalid_uint)
 
std::unique_ptr< DistributedMesh > buildDistributedMesh (unsigned int dim=libMesh::invalid_uint)
 
void addMeshSubgenerator (const std::string &type, const std::string &name, Ts... extra_input_parameters)
 
void addMeshSubgenerator (const std::string &type, const std::string &name, InputParameters params)
 
void declareNullMeshName (const MeshGeneratorName &name)
 
void flagInvalidSolutionInternal (const InvalidSolutionID invalid_solution_id) const
 
InvalidSolutionID registerInvalidSolutionInternal (const std::string &message, const bool warning) const
 
const TgetMeshProperty (const std::string &data_name, const std::string &prefix)
 
const TgetMeshProperty (const std::string &data_name)
 
bool hasMeshProperty (const std::string &data_name, const std::string &prefix) const
 
bool hasMeshProperty (const std::string &data_name, const std::string &prefix) const
 
bool hasMeshProperty (const std::string &data_name) const
 
bool hasMeshProperty (const std::string &data_name) const
 
std::string meshPropertyName (const std::string &data_name) const
 
TdeclareMeshProperty (const std::string &data_name, Args &&... args)
 
TdeclareMeshProperty (const std::string &data_name, const T &data_value)
 
TdeclareMeshProperty (const std::string &data_name, Args &&... args)
 
TdeclareMeshProperty (const std::string &data_name, const T &data_value)
 
TsetMeshProperty (const std::string &data_name, Args &&... args)
 
TsetMeshProperty (const std::string &data_name, const T &data_value)
 
TsetMeshProperty (const std::string &data_name, Args &&... args)
 
TsetMeshProperty (const std::string &data_name, const T &data_value)
 

Static Protected Member Functions

static std::string meshPropertyName (const std::string &data_name, const std::string &prefix)
 

Protected Attributes

const Real _unheated_length_entry
 unheated length of the fuel Pin at the entry of the assembly
 
const Real _heated_length
 heated length of the fuel Pin
 
const Real _unheated_length_exit
 unheated length of the fuel Pin at the exit of the assembly
 
std::vector< Real > _z_grid
 axial location of nodes
 
const Real _pitch
 Distance between the neighbor fuel pins, pitch.
 
const Real _pin_diameter
 fuel Pin diameter
 
const unsigned int _n_rings
 Number of rings in the geometry.
 
const Real _flat_to_flat
 Half of gap between adjacent assemblies.
 
const unsigned int _num_sectors
 Number of azimuthal sectors used to discretize each circular pin cross section.
 
std::vector< EChannelType_subch_type
 Subchannel type.
 
std::vector< Point > _pin_position
 x,y coordinates of the fuel pins
 
std::vector< std::vector< Real > > _subchannel_position
 x,y coordinates of the subchannels
 
const unsigned int _subchannel_block_id
 Subchannel subdomain ID.
 
const unsigned int _pin_block_id
 Pin subdomain ID.
 
const unsigned int _n_cells
 Number of cells in the axial direction.
 
unsigned int _nrods
 Number of pins.
 
std::vector< std::vector< unsigned int > > _pins_in_rings
 fuel pins that are belonging to each ring
 
std::map< unsigned int, Real > _orientation_map
 map inner and outer rings
 
unsigned int _n_channels
 number of subchannels
 
std::vector< std::vector< unsigned int > > _chan_to_pin_map
 stores the fuel pins belonging to each subchannel
 
const bool _verbose
 Flag to print out the detailed mesh assembly and coordinates.
 
dof_id_type _elem_id
 counter for element numbering
 
MooseMesh *const _mesh
 
const bool & _enabled
 
MooseApp_app
 
Factory_factory
 
ActionFactory_action_factory
 
const std::string & _type
 
const std::string & _name
 
const InputParameters_pars
 
const Parallel::Communicator & _communicator
 

Private Member Functions

virtual std::string meshPropertyPrefix (const std::string &) const override final
 
void checkGetMesh (const MeshGeneratorName &mesh_generator_name, const std::string &param_name) const
 
const MeshGeneratorName * getMeshGeneratorNameFromParam (const std::string &param_name, const bool allow_invalid) const
 
const std::vector< MeshGeneratorName > & getMeshGeneratorNamesFromParam (const std::string &param_name) const
 
RestartableDataValuesetMeshPropertyHelper (const std::string &data_name)
 
const RestartableDataValuegetMeshPropertyInternal (const std::string &data_name, const std::string &prefix) const
 
void mooseErrorInternal (Args &&... args) const
 

Static Private Member Functions

static const hit::Node * getHitNode (const InputParameters &params)
 
static std::string messagePrefix (const InputParameters &params, const bool hit_prefix)
 

Private Attributes

std::set< MeshGeneratorName > _requested_mesh_generators
 
std::set< MeshGeneratorName > _requested_mesh_generators_for_sub
 
std::vector< std::pair< std::string, std::unique_ptr< MeshBase > * > > _requested_meshes
 
std::vector< std::pair< std::string, std::unique_ptr< CSG::CSGBase > * > > _requested_csg_bases
 
std::unique_ptr< MeshBase > _null_mesh
 
std::unique_ptr< CSG::CSGBase_null_csg_base
 
std::set< const MeshGenerator *, Comparator > _parent_mesh_generators
 
std::set< const MeshGenerator *, Comparator > _child_mesh_generators
 
std::set< const MeshGenerator *, Comparator > _sub_mesh_generators
 
std::set< std::string > _null_mesh_names
 
const std::string & _save_with_name
 
const bool _data_only
 
const ParallelParamObject_parent
 
const MooseBase_si_moose_base
 
const FEProblemBase_si_problem
 
MooseApp_meta_data_app
 
const MooseObject *const _meta_data_object
 

Detailed Description

Mesh generator that builds a 3D mesh representing triangular subchannels and pins.

Definition at line 18 of file SCMDetailedTriAssemblyMeshGenerator.h.

Constructor & Destructor Documentation

◆ SCMDetailedTriAssemblyMeshGenerator()

SCMDetailedTriAssemblyMeshGenerator::SCMDetailedTriAssemblyMeshGenerator ( const InputParameters parameters)

Definition at line 65 of file SCMDetailedTriAssemblyMeshGenerator.C.

68 _unheated_length_entry(getParam<Real>("unheated_length_entry")),
69 _heated_length(getParam<Real>("heated_length")),
70 _unheated_length_exit(getParam<Real>("unheated_length_exit")),
71 _pitch(getParam<Real>("pitch")),
72 _pin_diameter(getParam<Real>("pin_diameter")),
73 _n_rings(getParam<unsigned int>("nrings")),
74 _flat_to_flat(getParam<Real>("flat_to_flat")),
75 _num_sectors(getParam<unsigned int>("num_sectors")),
76 _subchannel_block_id(getParam<unsigned int>("subchannel_block_id")),
77 _pin_block_id(getParam<unsigned int>("pin_block_id")),
78 _n_cells(getParam<unsigned int>("n_cells")),
79 _nrods(0),
80 _n_channels(0),
81 _verbose(getParam<bool>("verbose_flag")),
82 _elem_id(0)
83{
85
86 if (_n_rings < 2)
87 paramError("nrings",
88 "'nrings' must be at least 2. In this mesh generator, the center pin counts as "
89 "the first ring, so a 7-pin bundle uses nrings = 2.");
90
91 if (_n_cells == 0)
92 paramError("n_cells", "The number of axial cells must be greater than zero");
93
94 if (L <= 0.0)
95 mooseError("Total bundle length must be greater than zero");
96
97 Real dz = L / _n_cells;
98 for (unsigned int i = 0; i < _n_cells + 1; i++)
99 _z_grid.push_back(dz * i);
100
101 // x coordinate for the first position
102 Real x0 = 0.0;
103 // y coordinate for the first position
104 Real y0 = 0.0;
105 // x coordinate for the second position
106 Real x1 = 0.0;
107 // y coordinate for the second position dummy variable
108 Real y1 = 0.0;
109 // dummy variable
110 Real a1 = 0.0;
111 // dummy variable
112 Real a2 = 0.0;
113 // average x coordinate
114 Real avg_coor_x = 0.0;
115 // average y coordinate
116 Real avg_coor_y = 0.0;
117 // distance between two points
118 Real dist = 0.0;
119 // distance between two points
120 Real dist0 = 0.0;
121 // the indicator used while setting _gap_to_chan_map array
122 std::vector<std::pair<unsigned int, unsigned int>> gap_fill;
124 _nrods = _pin_position.size();
125 // assign the pins to the corresponding rings
126 unsigned int k = 0; // initialize the fuel Pin counter index
127 _pins_in_rings.resize(_n_rings);
128 _pins_in_rings[0].push_back(k++);
129 for (unsigned int i = 1; i < _n_rings; i++)
130 for (unsigned int j = 0; j < i * 6; j++)
131 _pins_in_rings[i].push_back(k++);
132 // Given the number of pins and number of fuel Pin rings, the number of subchannels can be
133 // computed as follows:
134 unsigned int chancount = 0;
135 // Summing internal channels
136 for (unsigned int j = 0; j < _n_rings - 1; j++)
137 chancount += j * 6;
138 // Adding external channels to the total count
139 _n_channels = chancount + _nrods - 1 + (_n_rings - 1) * 6 + 6;
140
141 // Utils for building the mesh
143 _subch_type.resize(_n_channels);
145
146 for (unsigned int i = 0; i < _n_channels; i++)
147 {
148 _subchannel_position[i].reserve(3);
149 for (unsigned int j = 0; j < 3; j++)
150 {
151 _subchannel_position.at(i).push_back(0.0);
152 }
153 }
154
155 // create the subchannels
156 k = 0; // initialize the subchannel counter index
157 for (unsigned int i = 1; i < _n_rings; i++)
158 {
159 // find the closest Pin at back ring
160 for (unsigned int j = 0; j < _pins_in_rings[i].size(); j++)
161 {
162 if (j == _pins_in_rings[i].size() - 1)
163 {
164 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
165 _chan_to_pin_map[k].push_back(_pins_in_rings[i][0]);
166 avg_coor_x =
167 0.5 * (_pin_position[_pins_in_rings[i][j]](0) + _pin_position[_pins_in_rings[i][0]](0));
168 avg_coor_y =
169 0.5 * (_pin_position[_pins_in_rings[i][j]](1) + _pin_position[_pins_in_rings[i][0]](1));
170 }
171 else
172 {
173 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
174 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j + 1]);
175 avg_coor_x = 0.5 * (_pin_position[_pins_in_rings[i][j]](0) +
176 _pin_position[_pins_in_rings[i][j + 1]](0));
177 avg_coor_y = 0.5 * (_pin_position[_pins_in_rings[i][j]](1) +
178 _pin_position[_pins_in_rings[i][j + 1]](1));
179 }
180 dist0 = 1.0e+5;
181 _chan_to_pin_map[k].push_back(_pins_in_rings[i - 1][0]);
182 for (unsigned int l = 0; l < _pins_in_rings[i - 1].size(); l++)
183 {
184 dist = std::sqrt(pow(_pin_position[_pins_in_rings[i - 1][l]](0) - avg_coor_x, 2) +
185 pow(_pin_position[_pins_in_rings[i - 1][l]](1) - avg_coor_y, 2));
186
187 if (dist < dist0)
188 {
189 _chan_to_pin_map[k][2] = _pins_in_rings[i - 1][l];
190 dist0 = dist;
191 }
192 }
194 _orientation_map.insert(std::make_pair(k, 0.0));
195 k = k + 1;
196 }
197
198 // find the closest Pin at front ring
199 for (unsigned int j = 0; j < _pins_in_rings[i].size(); j++)
200 {
201 if (j == _pins_in_rings[i].size() - 1)
202 {
203 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
204 _chan_to_pin_map[k].push_back(_pins_in_rings[i][0]);
205 avg_coor_x =
206 0.5 * (_pin_position[_pins_in_rings[i][j]](0) + _pin_position[_pins_in_rings[i][0]](0));
207 avg_coor_y =
208 0.5 * (_pin_position[_pins_in_rings[i][j]](1) + _pin_position[_pins_in_rings[i][0]](1));
209 }
210 else
211 {
212 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
213 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j + 1]);
214 avg_coor_x = 0.5 * (_pin_position[_pins_in_rings[i][j]](0) +
215 _pin_position[_pins_in_rings[i][j + 1]](0));
216 avg_coor_y = 0.5 * (_pin_position[_pins_in_rings[i][j]](1) +
217 _pin_position[_pins_in_rings[i][j + 1]](1));
218 }
219 // if the outermost ring, set the edge subchannels first... then the corner subchannels
220 if (i == _n_rings - 1)
221 {
222 // add edges
223 _subch_type[k] = EChannelType::EDGE; // an edge subchannel is created
224 k = k + 1;
225 if (j % i == 0)
226 {
227 // corner subchannel
228 _chan_to_pin_map[k].push_back(_pins_in_rings[i][j]);
230 k = k + 1;
231 }
232 // if not the outer most ring
233 }
234 else
235 {
236 dist0 = 1.0e+5;
237 _chan_to_pin_map[k].push_back(_pins_in_rings[i + 1][0]);
238 for (unsigned int l = 0; l < _pins_in_rings[i + 1].size(); l++)
239 {
240 dist = std::sqrt(pow(_pin_position[_pins_in_rings[i + 1][l]](0) - avg_coor_x, 2) +
241 pow(_pin_position[_pins_in_rings[i + 1][l]](1) - avg_coor_y, 2));
242 if (dist < dist0)
243 {
244 _chan_to_pin_map[k][2] = _pins_in_rings[i + 1][l];
245 dist0 = dist;
246 }
247 }
249 _orientation_map.insert(std::make_pair(k, libMesh::pi));
250 k = k + 1;
251 }
252 }
253 }
254
255 for (auto & pin : _chan_to_pin_map)
256 pin.shrink_to_fit();
257
258 // set the subchannel positions
259 Real _duct_to_pin_gap =
260 0.5 * (_flat_to_flat - (_n_rings - 1) * _pitch * std::sqrt(3.0) - _pin_diameter);
261 for (unsigned int i = 0; i < _n_channels; i++)
262 {
264 {
268 3.0;
272 3.0;
273 }
274 else if (_subch_type[i] == EChannelType::EDGE)
275 {
276 for (unsigned int j = 0; j < _n_channels; j++)
277 {
279 ((_chan_to_pin_map[i][0] == _chan_to_pin_map[j][0] &&
280 _chan_to_pin_map[i][1] == _chan_to_pin_map[j][1]) ||
281 (_chan_to_pin_map[i][0] == _chan_to_pin_map[j][1] &&
282 _chan_to_pin_map[i][1] == _chan_to_pin_map[j][0])))
283 {
284 x0 = _pin_position[_chan_to_pin_map[j][2]](0);
285 y0 = _pin_position[_chan_to_pin_map[j][2]](1);
286 }
287 else if (_subch_type[j] == EChannelType::CENTER &&
288 ((_chan_to_pin_map[i][0] == _chan_to_pin_map[j][0] &&
289 _chan_to_pin_map[i][1] == _chan_to_pin_map[j][2]) ||
290 (_chan_to_pin_map[i][0] == _chan_to_pin_map[j][2] &&
291 _chan_to_pin_map[i][1] == _chan_to_pin_map[j][0])))
292 {
293 x0 = _pin_position[_chan_to_pin_map[j][1]](0);
294 y0 = _pin_position[_chan_to_pin_map[j][1]](1);
295 }
296 else if (_subch_type[j] == EChannelType::CENTER &&
297 ((_chan_to_pin_map[i][0] == _chan_to_pin_map[j][1] &&
298 _chan_to_pin_map[i][1] == _chan_to_pin_map[j][2]) ||
299 (_chan_to_pin_map[i][0] == _chan_to_pin_map[j][2] &&
300 _chan_to_pin_map[i][1] == _chan_to_pin_map[j][1])))
301 {
302 x0 = _pin_position[_chan_to_pin_map[j][0]](0);
303 y0 = _pin_position[_chan_to_pin_map[j][0]](1);
304 }
305 x1 = 0.5 *
307 y1 = 0.5 *
309 a1 = _pin_diameter / 2.0 + _duct_to_pin_gap / 2.0;
310 a2 = std::sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) + a1;
311 _subchannel_position[i][0] = (a2 * x1 - a1 * x0) / (a2 - a1);
312 _subchannel_position[i][1] = (a2 * y1 - a1 * y0) / (a2 - a1);
313 } // j
314 }
315 else if (_subch_type[i] == EChannelType::CORNER)
316 {
317 x0 = _pin_position[0](0);
318 y0 = _pin_position[0](1);
319 x1 = _pin_position[_chan_to_pin_map[i][0]](0);
320 y1 = _pin_position[_chan_to_pin_map[i][0]](1);
321 a1 = _pin_diameter / 2.0 + _duct_to_pin_gap / 2.0;
322 a2 = std::sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) + a1;
323 _subchannel_position[i][0] = (a2 * x1 - a1 * x0) / (a2 - a1);
324 _subchannel_position[i][1] = (a2 * y1 - a1 * y0) / (a2 - a1);
325 }
326 }
327}
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const InputParameters & parameters() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
const unsigned int _n_rings
Number of rings in the geometry.
std::vector< EChannelType > _subch_type
Subchannel type.
const Real _heated_length
heated length of the fuel Pin
std::vector< std::vector< unsigned int > > _chan_to_pin_map
stores the fuel pins belonging to each subchannel
const Real _flat_to_flat
Half of gap between adjacent assemblies.
std::vector< Point > _pin_position
x,y coordinates of the fuel pins
const Real _pitch
Distance between the neighbor fuel pins, pitch.
const unsigned int _num_sectors
Number of azimuthal sectors used to discretize each circular pin cross section.
const unsigned int _n_cells
Number of cells in the axial direction.
std::vector< std::vector< unsigned int > > _pins_in_rings
fuel pins that are belonging to each ring
const Real _unheated_length_exit
unheated length of the fuel Pin at the exit of the assembly
const Real _unheated_length_entry
unheated length of the fuel Pin at the entry of the assembly
const unsigned int _subchannel_block_id
Subchannel subdomain ID.
const unsigned int _pin_block_id
Pin subdomain ID.
std::vector< Real > _z_grid
axial location of nodes
dof_id_type _elem_id
counter for element numbering
const bool _verbose
Flag to print out the detailed mesh assembly and coordinates.
std::map< unsigned int, Real > _orientation_map
map inner and outer rings
std::vector< std::vector< Real > > _subchannel_position
x,y coordinates of the subchannels
static void pinPositions(std::vector< Point > &positions, unsigned int nrings, Real pitch, Point center)
Calculates and stores the pin positions/centers for a hexagonal assembly containing the given number ...
const Real pi
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

Member Function Documentation

◆ generate()

std::unique_ptr< MeshBase > SCMDetailedTriAssemblyMeshGenerator::generate ( )
overridevirtual

Implements MeshGenerator.

Definition at line 373 of file SCMDetailedTriAssemblyMeshGenerator.C.

374{
375 auto mesh_base = buildMeshBaseObject();
376 BoundaryInfo & boundary_info = mesh_base->get_boundary_info();
377 mesh_base->set_spatial_dimension(3);
378 // Define the resolution (the number of points used to represent a circle).
379 // This must be divisible by 4.
380 const unsigned int theta_res_triangle = 24; // TODO: parameterize
381 const unsigned int theta_res_square = 24; // TODO: parameterize
382 // Compute the number of points needed to represent one sixth and quadrant of a circle.
383 const unsigned int points_per_sixth = theta_res_triangle / 6 + 1;
384 const unsigned int points_per_quadrant = theta_res_square / 4 + 1;
385
386 // Compute the points needed to represent one axial cross-flow of a subchannel.
387 // For the center subchannel (sc) there is one center point plus the points from 3 side
388 // circles.
389 const unsigned int points_per_center = points_per_sixth * 3 + 1;
390 // For the corner sc there is one center point plus the points from 1 side circle plus 3
391 // corners
392 const unsigned int points_per_corner = points_per_sixth * 1 + 1 + 3;
393 // For the side sc there is one center point plus the points from 2 intersecting circles plus 2
394 // corners
395 const unsigned int points_per_side = points_per_quadrant * 2 + 1 + 2;
396
397 if (_verbose)
398 {
399 _console << "Points per center: " << points_per_center << std::endl;
400 _console << "Points per side: " << points_per_side << std::endl;
401 _console << "Points per corner: " << points_per_corner << std::endl;
402 }
403
404 // Compute the number of elements (Prism6) which combined base creates the sub-channel
405 // cross-section
406 const unsigned int elems_per_center = theta_res_triangle * 3 / 6 + 3; // TODO: check
407 const unsigned int elems_per_corner = theta_res_triangle / 6 + 4;
408 const unsigned int elems_per_side = 2 * theta_res_square / 4 + 4;
409 if (_verbose)
410 {
411 _console << "Elems per center: " << elems_per_center << std::endl;
412 _console << "Elems per side: " << elems_per_side << std::endl;
413 _console << "Elems per corner: " << elems_per_corner << std::endl;
414 }
415
416 // specify number and type of sub-channel
417 unsigned int n_corner = 6;
418 unsigned int n_side = (_n_rings - 1) * 6;
419 unsigned int n_center = _n_channels - n_side - n_corner;
420 if (_verbose)
421 {
422 _console << "Centers: " << n_center << std::endl;
423 _console << "Sides: " << n_side << std::endl;
424 _console << "Corners: " << n_corner << std::endl;
425 }
426
427 // Compute the total number of points and elements.
428 const unsigned int points_per_level =
429 n_corner * points_per_corner + n_side * points_per_side + n_center * points_per_center;
430 const unsigned int elems_per_level =
431 n_corner * elems_per_corner + n_side * elems_per_side + n_center * elems_per_center;
432 if (_verbose)
433 {
434 _console << "Points per level: " << points_per_level << std::endl;
435 _console << "Elements per level: " << elems_per_level << std::endl;
436 }
437 const unsigned int n_points = points_per_level * (_n_cells + 1);
438 const unsigned int n_elems = elems_per_level * _n_cells;
439 const unsigned int n_pins = _pin_position.size();
440 const unsigned int pin_points = n_pins > 0 ? (_n_cells + 1) * (_num_sectors + 1) * n_pins : 0;
441 const unsigned int pin_elems = n_pins > 0 ? _n_cells * _num_sectors * n_pins : 0;
442 if (_verbose)
443 {
444 _console << "Number of points: " << n_points << std::endl;
445 _console << "Number of elements: " << n_elems << std::endl;
446 }
447 mesh_base->reserve_nodes(n_points + pin_points);
448 mesh_base->reserve_elem(n_elems + pin_elems);
449 // Build an array of points arranged in a circle on the xy-plane. (last and first node overlap)
450 // We build for both the square discretization in the edges and the triangular discretization
451 // within the mesh
452 const Real radius = _pin_diameter / 2.0;
453 std::array<Point, theta_res_square + 1> circle_points_square;
454 {
455 Real theta = 0;
456 for (unsigned int i = 0; i < theta_res_square + 1; i++)
457 {
458 circle_points_square[i](0) = radius * std::cos(theta);
459 circle_points_square[i](1) = radius * std::sin(theta);
460 theta += 2.0 * libMesh::pi / theta_res_square;
461 }
462 }
463 std::array<Point, theta_res_triangle + 1> circle_points_triangle;
464 {
465 Real theta = 0;
466 for (unsigned int i = 0; i < theta_res_triangle + 1; i++)
467 {
468 circle_points_triangle[i](0) = radius * std::cos(theta);
469 circle_points_triangle[i](1) = radius * std::sin(theta);
470 theta += 2.0 * libMesh::pi / theta_res_triangle;
471 }
472 }
473 // Define "quadrant center" reference points. These will be the centers of
474 // the 3 circles that represent the fuel pins. These centers are
475 // offset a little bit so that in the final mesh, there is a tiny gap between
476 // neighboring subchannel cells. That allows us to easily map a solution to
477 // this detailed mesh with a nearest-neighbor search.
478 const Real shrink_factor = 0.99999;
479 // Quadrants are used only for the side and corner subchannels
480 Real _duct_to_pin_gap =
481 0.5 * (_flat_to_flat - (_n_rings - 1) * _pitch * std::sqrt(3.0) - _pin_diameter);
482 std::array<Point, 2> quadrant_centers_sides;
483 quadrant_centers_sides[0] = Point(
484 -_pitch * 0.5 * shrink_factor, -(_duct_to_pin_gap + _pin_diameter) * 0.5 * shrink_factor, 0);
485 quadrant_centers_sides[1] = Point(
486 _pitch * 0.5 * shrink_factor, -(_duct_to_pin_gap + _pin_diameter) * 0.5 * shrink_factor, 0);
487 std::array<Point, 1> quadrant_centers_corner;
488 quadrant_centers_corner[0] =
489 Point(-(_duct_to_pin_gap + _pin_diameter) * 0.5 * std::sin(libMesh::pi / 6) * shrink_factor,
490 -(_duct_to_pin_gap + _pin_diameter) * 0.5 * std::cos(libMesh::pi / 6) * shrink_factor,
491 0);
492 // Triangles are used for all center subchannels
493 std::array<Point, 3> triangle_centers;
494 triangle_centers[0] = Point(0, _pitch * std::cos(libMesh::pi / 6) * 2 / 3 * shrink_factor, 0);
495 triangle_centers[1] = Point(-_pitch * 0.5 * shrink_factor,
496 -_pitch * std::cos(libMesh::pi / 6) * 1 / 3 * shrink_factor,
497 0);
498 triangle_centers[2] = Point(
499 _pitch * 0.5 * shrink_factor, -_pitch * std::cos(libMesh::pi / 6) * 1 / 3 * shrink_factor, 0);
500
501 const unsigned int m_sixth = theta_res_triangle / 6;
502 const unsigned int m_quarter = theta_res_square / 4;
503 // Build an array of points that represent a cross section of a center subchannel
504 // cell. The points are ordered in this fashion:
505 // 3 1
506 // 2
507 // 0
508 // 4 5 8 9
509 // 6 7
510 std::array<Point, points_per_center> center_points{};
511 center_points[0] = Point(0, 0, 0);
512 {
513 unsigned int start;
514 for (unsigned int i = 0; i < 3; i++)
515 {
516 if (i == 0)
517 start = 5 * (m_sixth);
518 if (i == 1)
519 start = 1 * (m_sixth);
520 if (i == 2)
521 start = 3 * (m_sixth);
522 for (unsigned int ii = 0; ii < points_per_sixth; ii++)
523 {
524 auto c_pt = circle_points_triangle[start - ii];
525 center_points[i * points_per_sixth + ii + 1] = triangle_centers[i] + c_pt;
526 }
527 }
528 }
529
530 // Build an array of points that represent a cross section of a top left corner subchannel
531 // cell. The points are ordered in this fashion (x direction towards point 4, y direction towards
532 // point 6):
533 // 5 6
534 //
535 // 0
536 // 4 2 3
537 // 1
538 std::array<Point, points_per_corner> corner_points{};
539 corner_points[0] = Point(0, 0, 0);
540 {
541 for (unsigned int ii = 0; ii < points_per_sixth; ii++)
542 {
543 auto c_pt = circle_points_triangle[1 * m_quarter - ii];
544 corner_points[ii + 1] = quadrant_centers_corner[0] + c_pt;
545 }
546 Real side_short = (_duct_to_pin_gap + _pin_diameter) * 0.5;
547 Real side_long = (2.0 * _duct_to_pin_gap + _pin_diameter) * 0.5;
548 Real side_length = std::sqrt(std::pow(side_short, 2) + std::pow(side_long, 2) -
549 2 * side_short * side_long * std::cos(libMesh::pi / 6));
550 Real angle =
552 std::acos((-std::pow(side_long, 2) + std::pow(side_short, 2) + std::pow(side_length, 2)) /
553 (2 * side_short * side_length));
554 corner_points[points_per_sixth + 1] = Point(side_length * std::cos(angle) * shrink_factor,
555 -side_length * std::sin(angle) * shrink_factor,
556 0);
557 corner_points[points_per_sixth + 2] =
558 Point(side_length * std::sin(libMesh::pi / 2 - angle - libMesh::pi / 6) * shrink_factor *
559 std::tan(libMesh::pi / 6),
560 side_length * std::sin(libMesh::pi / 2 - angle - libMesh::pi / 6) * shrink_factor,
561 0);
562 corner_points[points_per_sixth + 3] =
563 Point(-side_length * std::cos(libMesh::pi / 2 - angle - libMesh::pi / 6) * shrink_factor,
564 side_length * std::sin(libMesh::pi / 2 - angle - libMesh::pi / 6) * shrink_factor,
565 0);
566 }
567
568 // Build an array of points that represent a cross-section of a top side subchannel
569 // cell. The points are ordered in this fashion:
570 // 8 7
571 //
572 // 0
573 // 1 2 5 6
574 // 3 4
575 std::array<Point, points_per_side> side_points{};
576 side_points[0] = Point(0, 0, 0);
577 {
578 for (unsigned int ii = 0; ii < points_per_quadrant; ii++)
579 {
580 auto c_pt = circle_points_square[m_quarter - ii];
581 side_points[ii + 1] = quadrant_centers_sides[0] + c_pt;
582 }
583 for (unsigned int ii = 0; ii < points_per_quadrant; ii++)
584 {
585 auto c_pt = circle_points_square[2 * m_quarter - ii];
586 side_points[points_per_quadrant + ii + 1] = quadrant_centers_sides[1] + c_pt;
587 }
588 side_points[2 * points_per_quadrant + 1] =
589 Point(_pitch * 0.5 * shrink_factor, 0.5 * _duct_to_pin_gap * shrink_factor, 0);
590 side_points[2 * points_per_quadrant + 2] =
591 Point(-_pitch * 0.5 * shrink_factor, 0.5 * _duct_to_pin_gap * shrink_factor, 0);
592 }
593
594 int point_counter = 0;
595 unsigned int node_id = 0;
596 for (unsigned int i = 0; i < _n_channels; i++)
597 {
598 // Real offset_x = _flat_to_flat / 2.0;
599 // Real offset_y = _flat_to_flat / 2.0;
600
602 {
603 for (auto z : _z_grid)
604 {
605 // Get height
606 Point z0{0, 0, z};
607
608 // Get suchannel position and assign to point
609 auto loc_position = getSubchannelPosition(i);
610 Point p0{loc_position[0], loc_position[1], 0};
611
612 // Determine orientation of current subchannel
613 auto subchannel_pins = getSubChannelPins(i);
614 Point subchannel_side =
615 getPinPosition(subchannel_pins[0]) + getPinPosition(subchannel_pins[1]);
616 Point base_center_orientation = {0, -1};
617
618 // Get rotation angle for current subchannel
619 Real dot_prod = 0;
620 for (unsigned int lp = 0; lp < 2; lp++)
621 dot_prod += base_center_orientation(lp) * subchannel_side(lp);
622 auto theta =
623 std::acos(dot_prod / (base_center_orientation.norm() * subchannel_side.norm()));
624 if (subchannel_side(0) < 0)
625 theta = 2.0 * libMesh::pi - theta;
626
627 // Real distance_side = subchannel_side.norm();
628 // Real distance_top = getPinPosition(subchannel_pins[2]).norm();
629 // if (distance_top > distance_side)
630 // theta += libMesh::pi * 0.0;
631
632 theta += _orientation_map[i];
633
634 theta = trunc((theta + (libMesh::pi / 6.0)) / (libMesh::pi / 3.0)) * libMesh::pi / 3.0;
635
636 if (_verbose)
637 {
638 if (z == 0)
639 {
640 _console << "Subchannel Position: " << p0 << std::endl;
641 auto pins = getSubChannelPins(i);
642 for (auto r : pins)
643 _console << r << " ";
644 _console << std::endl;
645 _console << "Theta: " << theta / libMesh::pi * 180. << std::endl;
646 }
647 }
648
649 // Assigning points for center channels
650 for (unsigned int i = 0; i < points_per_center; i++)
651 {
652 auto new_point = rotatePoint(center_points[i], theta) + p0 + z0;
653 if (_verbose)
654 {
655 if (z == 0)
656 _console << i << " - " << new_point << std::endl;
657 }
658 mesh_base->add_point(new_point, node_id++);
659 point_counter += 1;
660 }
661 }
662 }
664 {
665 for (auto z : _z_grid)
666 {
667 // Get height
668 Point z0{0, 0, z};
669
670 // Get suchannel position and assign to point
671 auto loc_position = getSubchannelPosition(i);
672 Point p0{loc_position[0], loc_position[1], 0};
673
674 // Determine orientation of current subchannel
675 auto subchannel_pins = getSubChannelPins(i);
676 Point subchannel_side =
677 getPinPosition(subchannel_pins[0]) + getPinPosition(subchannel_pins[1]);
678 Point base_center_orientation = {0, 1};
679
680 // Get rotation angle for current subchannel
681 Real dot_prod = 0;
682 for (unsigned int lp = 0; lp < 2; lp++)
683 dot_prod += base_center_orientation(lp) * subchannel_side(lp);
684 auto theta =
685 std::acos(dot_prod / (base_center_orientation.norm() * subchannel_side.norm()));
686 if (subchannel_side(0) > 0)
687 theta = 2. * libMesh::pi - theta;
688 theta = trunc((theta + (libMesh::pi / 6.0)) / (libMesh::pi / 3.0)) * libMesh::pi / 3.0;
689
690 if (_verbose)
691 {
692 if (z == 0)
693 {
694 _console << "Subchannel Position: " << p0 << std::endl;
695 auto pins = getSubChannelPins(i);
696 for (auto r : pins)
697 _console << r << " ";
698 _console << std::endl;
699 _console << "Theta: " << theta * 180 / libMesh::pi << std::endl;
700 }
701 }
702
703 // Assigning points for center channels
704 for (unsigned int i = 0; i < points_per_side; i++)
705 {
706 auto new_point = rotatePoint(side_points[i], theta) + p0 + z0;
707 if (_verbose)
708 {
709 if (z == 0)
710 _console << i << " - " << new_point << std::endl;
711 }
712 mesh_base->add_point(new_point, node_id++);
713 point_counter += 1;
714 }
715 }
716 }
717 else // getSubchannelType(i) == EChannelType::CORNER
718 {
719 for (auto z : _z_grid)
720 {
721 // Get height
722 Point z0{0, 0, z};
723
724 // Get suchannel position and assign to point
725 auto loc_position = getSubchannelPosition(i);
726 Point p0{loc_position[0], loc_position[1], 0};
727
728 // Determine orientation of current subchannel
729 auto subchannel_pins = getSubChannelPins(i);
730 Point subchannel_side = getPinPosition(subchannel_pins[0]);
731 Point base_center_orientation = {1, 1};
732
733 // Get rotation angle for current subchannel
734 Real dot_prod = 0;
735 for (unsigned int lp = 0; lp < 2; lp++)
736 dot_prod += base_center_orientation(lp) * subchannel_side(lp);
737 auto theta =
738 std::acos(dot_prod / (base_center_orientation.norm() * subchannel_side.norm()));
739 if (subchannel_side(0) > 0)
740 theta = 2. * libMesh::pi - theta;
741 theta = trunc((theta + (libMesh::pi / 6.0)) / (libMesh::pi / 3.0)) * libMesh::pi / 3.0;
742
743 if (_verbose)
744 {
745 if (z == 0)
746 {
747 _console << "Subchannel Position: " << p0 << std::endl;
748 auto pins = getSubChannelPins(i);
749 for (auto r : pins)
750 _console << r << " ";
751 _console << std::endl;
752 _console << "Theta: " << theta * 180 / libMesh::pi << std::endl;
753 }
754 }
755
756 // Assigning points for center channels
757 for (unsigned int i = 0; i < points_per_corner; i++)
758 {
759 auto new_point = rotatePoint(corner_points[i], theta) + p0 + z0;
760 if (_verbose)
761 {
762 if (z == 0)
763 _console << i << " - " << new_point << std::endl;
764 }
765 mesh_base->add_point(new_point, node_id++);
766 point_counter += 1;
767 }
768 }
769 }
770 } // i
771 if (_verbose)
772 _console << "Point counter: " << point_counter << std::endl;
773
774 int element_counter = 0;
775 unsigned int elem_id = 0;
776 unsigned int number_of_corner = 0;
777 unsigned int number_of_side = 0;
778 unsigned int number_of_center = 0;
779 unsigned int elems_per_channel = 0;
780 unsigned int points_per_channel = 0;
781 for (unsigned int i = 0; i < _n_channels; i++)
782 {
783 auto subch_type = getSubchannelType(i);
784 if (subch_type == EChannelType::CORNER)
785 {
786 number_of_corner++;
787 elems_per_channel = elems_per_corner;
788 points_per_channel = points_per_corner;
789 if (_verbose)
790 _console << "Corner" << std::endl;
791 }
792 else if (subch_type == EChannelType::EDGE)
793 {
794 number_of_side++;
795 elems_per_channel = elems_per_side;
796 points_per_channel = points_per_side;
797 if (_verbose)
798 _console << "Edge" << std::endl;
799 }
800 else if (subch_type == EChannelType::CENTER)
801 {
802 number_of_center++;
803 elems_per_channel = elems_per_center;
804 points_per_channel = points_per_center;
805 if (_verbose)
806 _console << "Center" << std::endl;
807 }
808 for (unsigned int iz = 0; iz < _n_cells; iz++)
809 {
810 unsigned int elapsed_points = number_of_corner * points_per_corner * (_n_cells + 1) +
811 number_of_side * points_per_side * (_n_cells + 1) +
812 number_of_center * points_per_center * (_n_cells + 1) -
813 points_per_channel * (_n_cells + 1);
814 // index of the central node at base of cell
815 unsigned int indx1 = iz * points_per_channel + elapsed_points;
816 // index of the central node at top of cell
817 unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
818
819 for (unsigned int i = 0; i < elems_per_channel; i++)
820 {
821 Elem * elem = mesh_base->add_elem(std::make_unique<Prism6>());
822 elem->subdomain_id() = _subchannel_block_id;
823 elem->set_id(elem_id++);
824
825 if (_verbose)
826 _console << "Node 0: " << *mesh_base->node_ptr(indx1) << std::endl;
827
828 elem->set_node(0, mesh_base->node_ptr(indx1));
829 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
830 if (i != elems_per_channel - 1)
831 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
832 else
833 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
834
835 elem->set_node(3, mesh_base->node_ptr(indx2));
836 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
837 if (i != elems_per_channel - 1)
838 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
839 else
840 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
841
842 if (iz == 0)
843 boundary_info.add_side(elem, 0, 0);
844 if (iz == _n_cells - 1)
845 boundary_info.add_side(elem, 4, 1);
846
847 element_counter += 1;
848 }
849 }
850 }
851 if (_verbose)
852 _console << "Element counter: " << element_counter << std::endl;
853 boundary_info.sideset_name(0) = "inlet";
854 boundary_info.sideset_name(1) = "outlet";
855 mesh_base->set_subdomain_name(_subchannel_block_id, "subchannel", true);
856 if (n_pins > 0)
857 {
858 _elem_id = mesh_base->n_elem();
859 for (auto & ctr : _pin_position)
860 generatePin(mesh_base, ctr);
861 }
862 if (n_pins > 0)
863 mesh_base->set_subdomain_name(_pin_block_id, "fuel_pins", true);
864 if (_verbose)
865 _console << "Mesh assembly done" << std::endl;
866 mesh_base->prepare_for_use();
867
868 return mesh_base;
869}
const ConsoleStream _console
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Point rotatePoint(Point b, Real theta)
rotate a point by theta radians about the origin
Point getPinPosition(unsigned int i)
returns the position of pin given pin index
EChannelType getSubchannelType(unsigned int index) const
returns the type of the subchannel given the index
void generatePin(std::unique_ptr< MeshBase > &mesh_base, const Point &center)
Generate one detailed fuel pin volume centered at the supplied point.
std::vector< unsigned int > getSubChannelPins(unsigned int i)
returns the index of neighboring pins given subchannel index
std::vector< Real > getSubchannelPosition(unsigned int i)
returns the position of subchannel given pin index
const Real radius

◆ generatePin()

void SCMDetailedTriAssemblyMeshGenerator::generatePin ( std::unique_ptr< MeshBase > &  mesh_base,
const Point &  center 
)
protected

Generate one detailed fuel pin volume centered at the supplied point.

Definition at line 330 of file SCMDetailedTriAssemblyMeshGenerator.C.

332{
333 const Real dalpha = 360. / _num_sectors;
334 const Real radius = _pin_diameter / 2.;
335
336 // Add a center node and radial boundary nodes on each axial level so each pin is discretized into
337 // triangular prism sectors.
338 std::vector<std::vector<Node *>> nodes;
339 nodes.resize(_n_cells + 1);
340 for (unsigned int k = 0; k < _n_cells + 1; k++)
341 {
342 const Real elev = _z_grid[k];
343 nodes[k].push_back(mesh_base->add_point(Point(center(0), center(1), elev)));
344 Real alpha = 0.;
345 for (unsigned int i = 0; i < _num_sectors; i++, alpha += dalpha)
346 {
347 const Real dx = radius * std::cos(alpha * M_PI / 180.);
348 const Real dy = radius * std::sin(alpha * M_PI / 180.);
349 nodes[k].push_back(mesh_base->add_point(Point(center(0) + dx, center(1) + dy, elev)));
350 }
351 }
352
353 // Add the pin volume elements, linking matching radial sectors between adjacent axial levels.
354 for (unsigned int k = 0; k < _n_cells; k++)
355 for (unsigned int i = 0; i < _num_sectors; i++)
356 {
357 Elem * elem = mesh_base->add_elem(std::make_unique<Prism6>());
358 elem->subdomain_id() = _pin_block_id;
359 elem->set_id(_elem_id++);
360 const unsigned int ctr_idx = 0;
361 const unsigned int idx1 = (i % _num_sectors) + 1;
362 const unsigned int idx2 = ((i + 1) % _num_sectors) + 1;
363 elem->set_node(0, nodes[k][ctr_idx]);
364 elem->set_node(1, nodes[k][idx1]);
365 elem->set_node(2, nodes[k][idx2]);
366 elem->set_node(3, nodes[k + 1][ctr_idx]);
367 elem->set_node(4, nodes[k + 1][idx1]);
368 elem->set_node(5, nodes[k + 1][idx2]);
369 }
370}
Point center

Referenced by generate().

◆ getPinPosition()

Point SCMDetailedTriAssemblyMeshGenerator::getPinPosition ( unsigned int  i)
inlineprotected

returns the position of pin given pin index

Definition at line 32 of file SCMDetailedTriAssemblyMeshGenerator.h.

32{ return _pin_position[i]; }

Referenced by generate().

◆ getSubChannelPins()

std::vector< unsigned int > SCMDetailedTriAssemblyMeshGenerator::getSubChannelPins ( unsigned int  i)
inlineprotected

returns the index of neighboring pins given subchannel index

Definition at line 36 of file SCMDetailedTriAssemblyMeshGenerator.h.

36{ return _chan_to_pin_map[i]; }

Referenced by generate().

◆ getSubchannelPosition()

std::vector< Real > SCMDetailedTriAssemblyMeshGenerator::getSubchannelPosition ( unsigned int  i)
inlineprotected

returns the position of subchannel given pin index

Definition at line 34 of file SCMDetailedTriAssemblyMeshGenerator.h.

34{ return _subchannel_position[i]; }

Referenced by generate().

◆ getSubchannelType()

EChannelType SCMDetailedTriAssemblyMeshGenerator::getSubchannelType ( unsigned int  index) const
inlineprotected

returns the type of the subchannel given the index

Definition at line 26 of file SCMDetailedTriAssemblyMeshGenerator.h.

26{ return _subch_type[index]; }

Referenced by generate().

◆ rotatePoint()

Point SCMDetailedTriAssemblyMeshGenerator::rotatePoint ( Point  b,
Real  theta 
)
protected

rotate a point by theta radians about the origin

Definition at line 872 of file SCMDetailedTriAssemblyMeshGenerator.C.

873{
874 std::vector<std::vector<Real>> A(3, std::vector<Real>(3));
875
876 A[0] = {std::cos(theta), -std::sin(theta), 0.0};
877 A[1] = {std::sin(theta), std::cos(theta), 0.0};
878 A[2] = {0.0, 0.0, 1.0};
879
880 Point rotated_vector = Point(0.0, 0.0, 0.0);
881 for (unsigned int i = 0; i < 3; i++)
882 for (unsigned int j = 0; j < 3; j++)
883 rotated_vector(i) += A[i][j] * b(j);
884
885 return rotated_vector;
886}

Referenced by generate().

◆ validParams()

InputParameters SCMDetailedTriAssemblyMeshGenerator::validParams ( )
static

Definition at line 37 of file SCMDetailedTriAssemblyMeshGenerator.C.

38{
41 "Creates a detailed mesh of subchannels and pins in a triangular lattice arrangement");
42 params.addRequiredParam<Real>("pitch", "Pitch [m]");
43 params.addRequiredParam<Real>("pin_diameter", "Rod diameter [m]");
44 params.addParam<Real>("unheated_length_entry", 0.0, "Unheated length at entry [m]");
45 params.addRequiredParam<Real>("heated_length", "Heated length [m]");
46 params.addParam<Real>("unheated_length_exit", 0.0, "Unheated length at exit [m]");
47 params.addRequiredParam<unsigned int>(
48 "nrings",
49 "Number of fuel-pin rings per assembly, counting the center pin as the first ring [-]");
50 params.addRequiredParam<Real>("flat_to_flat",
51 "Flat to flat distance for the hexagonal assembly [m]");
52 params.addRequiredParam<unsigned int>("n_cells", "The number of cells in the axial direction");
53 params.addRangeCheckedParam<unsigned int>("num_sectors",
54 16,
55 "num_sectors>=4",
56 "Number of azimuthal sectors used to discretize each "
57 "circular pin cross section.");
58 params.addParam<unsigned int>("block_id", 0, "Subchannel block id.");
59 params.deprecateParam("block_id", "subchannel_block_id", "07/01/2027");
60 params.addParam<unsigned int>("pin_block_id", 1, "Fuel pin block id.");
61 params.addParam<bool>("verbose_flag", false, "Flag to print out the mesh coordinates.");
62 return params;
63}
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)
void deprecateParam(const std::string &old_name, const std::string &new_name, const std::string &removal_date)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
static InputParameters validParams()

Member Data Documentation

◆ _chan_to_pin_map

std::vector<std::vector<unsigned int> > SCMDetailedTriAssemblyMeshGenerator::_chan_to_pin_map
protected

stores the fuel pins belonging to each subchannel

Definition at line 77 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by getSubChannelPins(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _elem_id

dof_id_type SCMDetailedTriAssemblyMeshGenerator::_elem_id
protected

counter for element numbering

Definition at line 81 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and generatePin().

◆ _flat_to_flat

const Real SCMDetailedTriAssemblyMeshGenerator::_flat_to_flat
protected

Half of gap between adjacent assemblies.

Definition at line 53 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _heated_length

const Real SCMDetailedTriAssemblyMeshGenerator::_heated_length
protected

heated length of the fuel Pin

Definition at line 41 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by SCMDetailedTriAssemblyMeshGenerator().

◆ _n_cells

const unsigned int SCMDetailedTriAssemblyMeshGenerator::_n_cells
protected

Number of cells in the axial direction.

Definition at line 67 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), generatePin(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _n_channels

unsigned int SCMDetailedTriAssemblyMeshGenerator::_n_channels
protected

number of subchannels

Definition at line 75 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _n_rings

const unsigned int SCMDetailedTriAssemblyMeshGenerator::_n_rings
protected

Number of rings in the geometry.

Definition at line 51 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _nrods

unsigned int SCMDetailedTriAssemblyMeshGenerator::_nrods
protected

Number of pins.

Definition at line 69 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by SCMDetailedTriAssemblyMeshGenerator().

◆ _num_sectors

const unsigned int SCMDetailedTriAssemblyMeshGenerator::_num_sectors
protected

Number of azimuthal sectors used to discretize each circular pin cross section.

Definition at line 55 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and generatePin().

◆ _orientation_map

std::map<unsigned int, Real> SCMDetailedTriAssemblyMeshGenerator::_orientation_map
protected

map inner and outer rings

Definition at line 73 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _pin_block_id

const unsigned int SCMDetailedTriAssemblyMeshGenerator::_pin_block_id
protected

Pin subdomain ID.

Definition at line 65 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and generatePin().

◆ _pin_diameter

const Real SCMDetailedTriAssemblyMeshGenerator::_pin_diameter
protected

fuel Pin diameter

Definition at line 49 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), generatePin(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _pin_position

std::vector<Point> SCMDetailedTriAssemblyMeshGenerator::_pin_position
protected

x,y coordinates of the fuel pins

Definition at line 59 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), getPinPosition(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _pins_in_rings

std::vector<std::vector<unsigned int> > SCMDetailedTriAssemblyMeshGenerator::_pins_in_rings
protected

fuel pins that are belonging to each ring

Definition at line 71 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by SCMDetailedTriAssemblyMeshGenerator().

◆ _pitch

const Real SCMDetailedTriAssemblyMeshGenerator::_pitch
protected

Distance between the neighbor fuel pins, pitch.

Definition at line 47 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _subch_type

std::vector<EChannelType> SCMDetailedTriAssemblyMeshGenerator::_subch_type
protected

Subchannel type.

Definition at line 57 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by getSubchannelType(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _subchannel_block_id

const unsigned int SCMDetailedTriAssemblyMeshGenerator::_subchannel_block_id
protected

Subchannel subdomain ID.

Definition at line 63 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate().

◆ _subchannel_position

std::vector<std::vector<Real> > SCMDetailedTriAssemblyMeshGenerator::_subchannel_position
protected

x,y coordinates of the subchannels

Definition at line 61 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by getSubchannelPosition(), and SCMDetailedTriAssemblyMeshGenerator().

◆ _unheated_length_entry

const Real SCMDetailedTriAssemblyMeshGenerator::_unheated_length_entry
protected

unheated length of the fuel Pin at the entry of the assembly

Definition at line 39 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by SCMDetailedTriAssemblyMeshGenerator().

◆ _unheated_length_exit

const Real SCMDetailedTriAssemblyMeshGenerator::_unheated_length_exit
protected

unheated length of the fuel Pin at the exit of the assembly

Definition at line 43 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by SCMDetailedTriAssemblyMeshGenerator().

◆ _verbose

const bool SCMDetailedTriAssemblyMeshGenerator::_verbose
protected

Flag to print out the detailed mesh assembly and coordinates.

Definition at line 79 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate().

◆ _z_grid

std::vector<Real> SCMDetailedTriAssemblyMeshGenerator::_z_grid
protected

axial location of nodes

Definition at line 45 of file SCMDetailedTriAssemblyMeshGenerator.h.

Referenced by generate(), generatePin(), and SCMDetailedTriAssemblyMeshGenerator().


The documentation for this class was generated from the following files: