12 #include "libmesh/mesh_smoother_laplace.h" 23 "num_sectors_per_side",
"num_sectors_per_side>0",
"Number of azimuthal sectors per side.");
25 "background_intervals",
27 "background_intervals>0",
28 "Number of radial meshing intervals in background " 29 "region (region around the rings/pins in the assembly).");
31 "background_block_ids",
32 "background_block_ids>0",
33 "Optional block ids for the background regions in the pins.");
34 params.
addParam<std::vector<SubdomainName>>(
35 "background_block_names",
"Optional block names for the background regions in the pins.");
37 "ring_radii",
"ring_radii>0",
"Radii of the three sets of major concentric circles (pins).");
41 "Number of radial mesh intervals within each set of major concentric circles (pins).");
43 "ring_block_ids",
"ring_block_ids>0",
"Optional block ids for the ring (pin) regions.");
44 params.
addParam<std::vector<std::vector<SubdomainName>>>(
45 "ring_block_names",
"Optional block names for the ring (pin) regions.");
46 MooseEnum hexagon_size_style(
"apothem radius",
"radius");
49 "Style in which hexagon size is given (apothem = center to face, " 50 "radius = center to vertex).");
52 "hexagon_size",
"hexagon_size>0",
"Size parameter of the hexagon assembly to be generated.");
54 "ring_offset", 0.0,
"Offset of the ring (pin) center, shared by all three.");
58 "Volume of concentric circles (pins) can be preserved using this function.");
59 MooseEnum assembly_orientation(
"pin_up pin_down",
"pin_up");
61 "assembly_orientation", assembly_orientation,
"Orientation of the generated assembly.");
63 "external_boundary_id>0",
64 "Optional customized external boundary id.");
65 params.
addParam<std::string>(
"external_boundary_name",
66 "Optional customized external boundary name.");
68 "pin_id_name",
"Name of extra integer ID to be assigned to each of the three pin domains.");
69 params.
addParam<std::vector<dof_id_type>>(
71 "Values of extra integer ID to be assigned to each of the three pin domains.");
73 "background_block_names external_boundary_id external_boundary_name",
74 "Customized Subdomain/Boundary ids/names");
77 "This TriPinHexAssemblyGenerator object generates a hexagonal assembly " 78 "mesh with three circular pins in a triangle at the center.");
84 _ring_radii(getRingParamValues<
Real>(
"ring_radii")),
86 _ring_intervals(getRingParamValues<unsigned int>(
"ring_intervals")),
87 _ring_block_ids(getRingParamValues<subdomain_id_type>(
"ring_block_ids")),
89 isParamValid(
"ring_block_names")
90 ? (getParam<std::vector<std::vector<SubdomainName>>>(
"ring_block_names").size() == 1
91 ? std::vector<std::vector<SubdomainName>>(
93 getParam<std::vector<std::vector<SubdomainName>>>(
"ring_block_names")
95 : getParam<std::vector<std::vector<SubdomainName>>>(
"ring_block_names"))
96 : std::vector<std::vector<SubdomainName>>(3, std::vector<SubdomainName>())),
98 getParam<MooseEnum>(
"hexagon_size_style").
template getEnum<PolygonSizeStyle>()),
99 _side_length(_hexagon_size_style == PolygonSizeStyle::radius
100 ? getParam<Real>(
"hexagon_size")
101 : (getParam<Real>(
"hexagon_size") /
cos(M_PI / 6.0))),
102 _ring_offset(getParam<Real>(
"ring_offset")),
103 _preserve_volumes(getParam<bool>(
"preserve_volumes")),
104 _assembly_orientation(
105 getParam<MooseEnum>(
"assembly_orientation").
template getEnum<AssmOrient>()),
106 _num_sectors_per_side(getParam<unsigned int>(
"num_sectors_per_side")),
107 _background_intervals(getParam<unsigned int>(
"background_intervals")),
108 _background_block_ids(isParamValid(
"background_block_ids")
109 ? getParam<std::vector<subdomain_id_type>>(
"background_block_ids")
110 : std::vector<subdomain_id_type>()),
111 _background_block_names(isParamValid(
"background_block_names")
112 ? getParam<std::vector<SubdomainName>>(
"background_block_names")
113 : std::vector<SubdomainName>()),
114 _external_boundary_id(isParamValid(
"external_boundary_id")
115 ? getParam<boundary_id_type>(
"external_boundary_id")
117 _external_boundary_name(isParamValid(
"external_boundary_name")
118 ? getParam<std::string>(
"external_boundary_name")
120 _pin_id_name(isParamValid(
"pin_id_name") ? getParam<std::string>(
"pin_id_name")
122 _pin_id_values(isParamValid(
"pin_id_values")
123 ? getParam<std::vector<dof_id_type>>(
"pin_id_values")
124 : std::vector<dof_id_type>()),
125 _node_id_background_meta(declareMeshProperty<dof_id_type>(
"node_id_background_meta", 0))
127 declareMeshProperty<Real>(
"pitch_meta", _side_length * std::sqrt(3.0));
128 declareMeshProperty<Real>(
"pattern_pitch_meta", _side_length * std::sqrt(3.0));
129 declareMeshProperty<bool>(
"is_control_drum_meta",
false);
130 declareMeshProperty<unsigned int>(
"background_intervals_meta", _background_intervals);
131 declareMeshProperty<Real>(
"max_radius_meta", 0.0);
132 declareMeshProperty<std::vector<unsigned int>>(
"num_sectors_per_side_meta",
133 {_num_sectors_per_side,
134 _num_sectors_per_side,
135 _num_sectors_per_side,
136 _num_sectors_per_side,
137 _num_sectors_per_side,
138 _num_sectors_per_side});
141 for (
unsigned int i = 0; i < 3; i++)
142 if (_ring_intervals[i].size() != _ring_radii[i].size())
143 paramError(
"ring_intervals",
"The parameter must be consistent with ring_radii.");
144 for (
unsigned int i = 0; i < 3; i++)
146 if (!_has_rings[i] && !_ring_block_ids[i].empty())
147 paramError(
"ring_block_ids",
"The parameter must be consistent with ring_radii if provided.");
148 else if (!_ring_block_ids[i].empty() &&
149 _ring_block_ids[i].size() != (_ring_radii[i].size() + (_ring_intervals[i][0] > 1)))
150 paramError(
"ring_block_ids",
"The parameter must be consistent with ring_radii if provided.");
151 if (!_has_rings[i] && !_ring_block_names[i].empty())
152 paramError(
"ring_block_names",
153 "The parameter must be consistent with ring_radii if provided.");
154 else if (!_ring_block_names[i].empty() &&
155 _ring_block_names[i].size() != (_ring_radii[i].size() + (_ring_intervals[i][0] > 1)))
156 paramError(
"ring_block_names",
157 "The parameter must be consistent with ring_radii if provided.");
159 if (!_background_block_ids.empty())
161 if (_has_rings[0] && _has_rings[1] && _has_rings[2] && _background_block_ids.size() != 1)
162 paramError(
"background_block_ids",
163 "If provided, the size of this parameter must be one if all sections have rings.");
164 else if (!_has_rings[0] && !_has_rings[1] && !_has_rings[2] && _background_intervals == 1 &&
165 _background_block_ids.size() != 1)
166 paramError(
"background_block_ids",
167 "If provided, the size of this parameter must be one if no sections have rings " 168 "and background_intervals is one.");
169 else if ((!_has_rings[0] || !_has_rings[1] || !_has_rings[2]) &&
170 _background_block_ids.size() != 2)
172 "background_block_ids",
173 "If provided, the size of this parameter must be two if ring-free section exists.");
175 if (!_background_block_names.empty())
177 if (_has_rings[0] && _has_rings[1] && _has_rings[2] && _background_block_names.size() != 1)
178 paramError(
"background_block_names",
179 "If provided, the size of this parameter must be one if all sections have rings.");
180 else if (!_has_rings[0] && !_has_rings[1] && !_has_rings[2] && _background_intervals == 1 &&
181 _background_block_names.size() != 1)
182 paramError(
"background_block_names",
183 "If provided, the size of this parameter must be one if no sections have rings " 184 "and background_intervals is one.");
185 else if ((!_has_rings[0] || !_has_rings[1] || !_has_rings[2]) &&
186 _background_block_names.size() != 2)
188 "background_block_names",
189 "If provided, the size of this parameter must be two if ring-free section exists.");
191 if (_pin_id_name.empty())
193 if (!_pin_id_values.empty())
194 paramError(
"pin_id_values",
195 "This parameter cannot be used when pin_id_name is not provided.");
197 else if (_pin_id_values.size() != 3)
200 "If pin_id_name is provided, this parameter must be provided with a length of three.");
204 if (std::abs(_ring_offset) >= _side_length / 2.0)
207 "This parameter cannot translate the ring center out of the hexagon assembly region.");
210 std::unique_ptr<MeshBase>
214 std::set<subdomain_id_type> tmp_block_ids;
215 std::set<SubdomainName> tmp_block_names;
216 std::vector<std::pair<subdomain_id_type, SubdomainName>> block_info;
217 for (
unsigned int i = 0; i < 3; i++)
222 if (tmp_block_names.size() != tmp_block_ids.size())
224 "The block name assignment must be compatible with the existing block ids.");
226 block_info.push_back(std::make_pair(
236 if (tmp_block_names.size() != tmp_block_ids.size())
238 "The block name assignment must be compatible with the existing block ids.");
244 std::vector<std::vector<subdomain_id_type>> block_ids_new(3, std::vector<subdomain_id_type>());
245 for (
unsigned int i = 0; i < 3; i++)
262 std::vector<std::unique_ptr<ReplicatedMesh>> meshes;
263 for (
unsigned int i = 0; i < 3; i++)
278 getParam<std::string>(
"sector_id_name"),
284 getParam<std::string>(
"ring_id_name"),
288 getParam<MooseEnum>(
"ring_id_assign_type") ==
"ring_wise",
295 MeshTools::Modification::rotate(*meshes[i], 120.0 * (
Real)i, 0, 0);
296 meshes[0]->stitch_meshes(*std::move(meshes[i]),
305 MeshTools::Modification::rotate(*meshes[0], 90, 0, 0);
307 MeshTools::Modification::rotate(*meshes[0], 270, 0, 0);
309 for (
const auto & block_info_pair : block_info)
310 meshes[0]->subdomain_name(block_info_pair.first) = block_info_pair.second;
315 meshes[0]->get_boundary_info().sideset_name(
318 meshes[0]->get_boundary_info().nodeset_name(
322 meshes[0]->set_isnt_prepared();
326 std::unique_ptr<ReplicatedMesh>
328 const Real side_length,
329 const Real ring_offset,
331 const std::vector<unsigned int> ring_intervals,
332 const bool has_rings,
333 const bool preserve_volumes,
334 const unsigned int num_sectors_per_side,
335 const unsigned int background_intervals,
336 const std::vector<subdomain_id_type> block_ids_new,
343 const Real secondary_side_length_0(side_length / 2.0 - ring_offset);
344 const Real secondary_side_length_1(
345 std::sqrt(side_length * side_length / 4.0 * 3.0 + ring_offset * ring_offset));
346 const Real primary_side_length_0(
347 std::sqrt(side_length * side_length / 4.0 * 3.0 + ring_offset * ring_offset));
348 const Real primary_side_length_1(side_length / 2.0 + ring_offset);
350 const Real azimuthal_angle_0(
351 acos((secondary_side_length_0 * secondary_side_length_0 +
352 primary_side_length_0 * primary_side_length_0 - side_length * side_length) /
353 2.0 / primary_side_length_0 / secondary_side_length_0) /
355 const Real azimuthal_angle_1(
356 acos((secondary_side_length_1 * secondary_side_length_1 +
357 primary_side_length_1 * primary_side_length_1 - side_length * side_length) /
358 2.0 / primary_side_length_1 / secondary_side_length_1) /
362 const Real rotation_angle_0(azimuthal_angle_0 - 90.0);
363 const Real rotation_angle_1(azimuthal_angle_0 + azimuthal_angle_1 - 90.0);
366 const Real alpha_angle_0(
367 acos((primary_side_length_0 * primary_side_length_0 + side_length * side_length -
368 secondary_side_length_0 * secondary_side_length_0) /
369 2.0 / primary_side_length_0 / side_length) /
371 const Real alpha_angle_1(
372 acos((primary_side_length_1 * primary_side_length_1 + side_length * side_length -
373 secondary_side_length_1 * secondary_side_length_1) /
374 2.0 / primary_side_length_1 / side_length) /
379 std::vector<Real> azimuthal_list;
380 for (
unsigned int i = 0; i < num_sectors_per_side; i++)
382 azimuthal_list.push_back(
383 atan((
Real)i * side_length / num_sectors_per_side *
sin(alpha_angle_0 / 180.0 * M_PI) /
384 (primary_side_length_0 -
385 (
Real)i * side_length / num_sectors_per_side *
cos(alpha_angle_0 / 180.0 * M_PI))) /
388 for (
unsigned int i = 0; i < num_sectors_per_side; i++)
390 azimuthal_list.push_back(
392 atan((
Real)i * side_length / num_sectors_per_side *
sin(alpha_angle_1 / 180.0 * M_PI) /
393 (primary_side_length_1 -
394 (
Real)i * side_length / num_sectors_per_side *
cos(alpha_angle_1 / 180.0 * M_PI))) /
397 for (
unsigned int i = 0; i < num_sectors_per_side * 2; i++)
399 azimuthal_list.push_back(azimuthal_list[i] + 180.0);
402 std::vector<Real> ring_radii_corr;
405 if (preserve_volumes)
408 for (
unsigned int i = 0; i <
ring_radii.size(); i++)
409 ring_radii_corr.push_back(
ring_radii[i] * corr_factor);
413 if (ring_radii_corr.back() > (side_length / 2.0 - std::abs(ring_offset)) * std::sqrt(3.0) / 2.0)
415 "The radii of the rings cannot exceed the boundary of the diamond section.");
422 std::vector<Real>(ring_radii_corr.size(), 1.0),
423 {std::vector<Real>(ring_radii_corr.size(), 0.0),
424 std::vector<Real>(ring_radii_corr.size(), 0.0),
425 std::vector<unsigned int>(ring_radii_corr.size(), 0),
426 std::vector<Real>(ring_radii_corr.size(), 1.0)},
427 {std::vector<Real>(ring_radii_corr.size(), 0.0),
428 std::vector<Real>(ring_radii_corr.size(), 0.0),
429 std::vector<unsigned int>(ring_radii_corr.size(), 0),
430 std::vector<Real>(ring_radii_corr.size(), 1.0)},
432 std::vector<unsigned int>(),
434 {std::vector<Real>(), std::vector<Real>(), std::vector<unsigned int>(), std::vector<Real>()},
435 {std::vector<Real>(), std::vector<Real>(), std::vector<unsigned int>(), std::vector<Real>()},
436 primary_side_length_0,
437 secondary_side_length_0,
438 num_sectors_per_side,
439 background_intervals,
443 node_id_background_meta,
455 std::vector<Real>(ring_radii_corr.size(), 1.0),
456 {std::vector<Real>(ring_radii_corr.size(), 0.0),
457 std::vector<Real>(ring_radii_corr.size(), 0.0),
458 std::vector<unsigned int>(ring_radii_corr.size(), 0),
459 std::vector<Real>(ring_radii_corr.size(), 1.0)},
460 {std::vector<Real>(ring_radii_corr.size(), 0.0),
461 std::vector<Real>(ring_radii_corr.size(), 0.0),
462 std::vector<unsigned int>(ring_radii_corr.size(), 0),
463 std::vector<Real>(ring_radii_corr.size(), 1.0)},
465 std::vector<unsigned int>(),
467 {std::vector<Real>(), std::vector<Real>(), std::vector<unsigned int>(), std::vector<Real>()},
468 {std::vector<Real>(), std::vector<Real>(), std::vector<unsigned int>(), std::vector<Real>()},
469 primary_side_length_1,
470 secondary_side_length_1,
471 num_sectors_per_side,
472 background_intervals,
476 node_id_background_meta,
485 mesh0->stitch_meshes(*mesh1,
493 MeshTools::Modification::rotate(*mesh2, 0, 180.0, 0);
494 mesh0->stitch_meshes(*mesh2,
499 MeshTools::Modification::translate(*mesh0, side_length / 2.0 + ring_offset, 0, 0);
501 for (
const auto & elem : mesh0->element_ptr_range())
502 elem->subdomain_id() = block_ids_new[elem->subdomain_id() - 1];
std::unique_ptr< ReplicatedMesh > buildGeneralSlice(std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< Real > ring_radial_biases, const multiBdryLayerParams &ring_inner_boundary_layer_params, const multiBdryLayerParams &ring_outer_boundary_layer_params, std::vector< Real > ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< Real > duct_radial_biases, const multiBdryLayerParams &duct_inner_boundary_layer_params, const multiBdryLayerParams &duct_outer_boundary_layer_params, const Real primary_side_length, const Real secondary_side_length, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const Real background_radial_bias, const singleBdryLayerParams &background_inner_boundary_layer_params, const singleBdryLayerParams &background_outer_boundary_layer_params, dof_id_type &node_id_background_meta, const Real azimuthal_angle, const std::vector< Real > azimuthal_tangent, const unsigned int side_index, const bool quad_center_elements, const Real center_quad_factor, const Real rotation_angle, const bool generate_side_specific_boundaries=true)
Creates a mesh of a general polygon slice with a triangular shape and circular regions on one of its ...
const std::string _external_boundary_name
Boundary name of mesh's external boundary.
registerMooseObject("ReactorApp", TriPinHexAssemblyGenerator)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
void setSectorExtraIDs(MeshBase &mesh, const std::string id_name, const unsigned int num_sides, const std::vector< unsigned int > num_sectors_per_side)
assign sector extra ids to polygon mesh
const std::vector< std::vector< unsigned int > > _ring_intervals
Numbers of radial layers in each ring region in the three diamond sections.
enum TriPinHexAssemblyGenerator::AssmOrient _assembly_orientation
const std::vector< subdomain_id_type > _background_block_ids
Block ids of the background region.
const unsigned int _num_sectors_per_side
Mesh sector number of each polygon side.
const std::vector< std::vector< SubdomainName > > _ring_block_names
Block names of the ring regions in the three diamond sections.
const Real _ring_offset
Offset distance of the circle centers from the center of each diamond section.
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
const bool _preserve_volumes
Whether the radii need to be corrected for polygonization during meshing.
void changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
bool isParamValid(const std::string &name) const
const std::vector< dof_id_type > _pin_id_values
Values of extra integer ID to be assigned to each of the three pin domains.
This TriPinHexAssemblyGenerator object is a base class to be inherited for polygon mesh generators...
static InputParameters validParams()
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
void setRingExtraIDs(MeshBase &mesh, const std::string id_name, const unsigned int num_sides, const std::vector< unsigned int > num_sectors_per_side, const std::vector< unsigned int > ring_intervals, const bool ring_wise_id, const bool quad_center_elements)
assign ring extra ids to polygon mesh
const unsigned int _background_intervals
Numbers of radial intervals of the background regions.
const std::vector< std::vector< Real > > _ring_radii
Radii of concentric circles in the three diamond sections.
const std::vector< bool > _has_rings
Whether the generated mesh contains ring regions.
dof_id_type & _node_id_background_meta
MeshMetaData: maximum node id of the background region.
void paramError(const std::string ¶m, Args... args) const
const std::vector< std::vector< subdomain_id_type > > _ring_block_ids
Block ids of the ring regions in the three diamond sections.
static void addRingAndSectorIDParams(InputParameters ¶ms)
Add InputParameters which are used by ring and sector IDs.
std::unique_ptr< MeshBase > generate() override
const boundary_id_type _external_boundary_id
Boundary ID of mesh's external boundary.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string ring_radii
const std::vector< SubdomainName > _background_block_names
Block names of the background region.
const Real _side_length
Length of the side of the hexagon.
std::unique_ptr< ReplicatedMesh > buildSinglePinSection(const Real side_length, const Real ring_offset, const std::vector< Real > ring_radii, const std::vector< unsigned int > ring_intervals, const bool has_rings, const bool preserve_volumes, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const std::vector< subdomain_id_type > block_ids_new, dof_id_type &node_id_background_meta)
Generates a single-pin diamond section mesh, which is one-third of the triple-pin hexagonal assembly ...
A base class that contains common members for Reactor module mesh generators.
TriPinHexAssemblyGenerator(const InputParameters ¶meters)
const std::string _pin_id_name
Name of extra integer ID to be assigned to each of the three pin domains.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Real radiusCorrectionFactor(const std::vector< Real > &azimuthal_list, const bool full_circle=true, const unsigned int order=1, const bool is_first_value_vertex=true)
Makes radial correction to preserve ring area.
static InputParameters validParams()