https://mooseframework.inl.gov
Loading...
Searching...
No Matches
TriPinHexAssemblyGenerator.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#include "libmesh/mesh_smoother_laplace.h"
13
14#include <cmath>
15
17
20{
22 params.addRequiredRangeCheckedParam<unsigned int>(
23 "num_sectors_per_side", "num_sectors_per_side>0", "Number of azimuthal sectors per side.");
24 params.addRangeCheckedParam<unsigned int>(
25 "background_intervals",
26 1,
27 "background_intervals>0",
28 "Number of radial meshing intervals in background "
29 "region (region around the rings/pins in the assembly).");
30 params.addRangeCheckedParam<std::vector<subdomain_id_type>>(
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.");
36 params.addRangeCheckedParam<std::vector<std::vector<Real>>>(
37 "ring_radii", "ring_radii>0", "Radii of the three sets of major concentric circles (pins).");
38 params.addRangeCheckedParam<std::vector<std::vector<unsigned int>>>(
39 "ring_intervals",
40 "ring_intervals>0",
41 "Number of radial mesh intervals within each set of major concentric circles (pins).");
42 params.addRangeCheckedParam<std::vector<std::vector<subdomain_id_type>>>(
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");
47 params.addParam<MooseEnum>("hexagon_size_style",
48 hexagon_size_style,
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.");
53 params.addParam<Real>(
54 "ring_offset", 0.0, "Offset of the ring (pin) center, shared by all three.");
55 params.addParam<bool>(
56 "preserve_volumes",
57 true,
58 "Volume of concentric circles (pins) can be preserved using this function.");
59 MooseEnum assembly_orientation("pin_up pin_down", "pin_up");
60 params.addParam<MooseEnum>(
61 "assembly_orientation", assembly_orientation, "Orientation of the generated assembly.");
62 params.addRangeCheckedParam<boundary_id_type>("external_boundary_id",
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.");
67 params.addParam<std::string>(
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>>(
70 "pin_id_values",
71 "Values of extra integer ID to be assigned to each of the three pin domains.");
72 params.addParamNamesToGroup("ring_block_ids ring_block_names background_block_ids "
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.");
79 return params;
80}
81
83 : PolygonMeshGeneratorBase(parameters),
84 _ring_radii(getRingParamValues<Real>("ring_radii")),
85 _has_rings({!_ring_radii[0].empty(), !_ring_radii[1].empty(), !_ring_radii[2].empty()}),
86 _ring_intervals(getRingParamValues<unsigned int>("ring_intervals")),
87 _ring_block_ids(getRingParamValues<subdomain_id_type>("ring_block_ids")),
88 _ring_block_names(
89 isParamValid("ring_block_names")
90 ? (getParam<std::vector<std::vector<SubdomainName>>>("ring_block_names").size() == 1
91 ? std::vector<std::vector<SubdomainName>>(
92 3,
93 getParam<std::vector<std::vector<SubdomainName>>>("ring_block_names")
94 .front())
95 : getParam<std::vector<std::vector<SubdomainName>>>("ring_block_names"))
96 : std::vector<std::vector<SubdomainName>>(3, std::vector<SubdomainName>())),
97 _hexagon_size_style(
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")
116 : 0),
117 _external_boundary_name(isParamValid("external_boundary_name")
118 ? getParam<std::string>("external_boundary_name")
119 : std::string()),
120 _pin_id_name(isParamValid("pin_id_name") ? getParam<std::string>("pin_id_name")
121 : std::string()),
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))
126{
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",
139
140 /* Parameter checks */
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++)
145 {
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.");
158 }
159 if (!_background_block_ids.empty())
160 {
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.");
174 }
175 if (!_background_block_names.empty())
176 {
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.");
190 }
191 if (_pin_id_name.empty())
192 {
193 if (!_pin_id_values.empty())
194 paramError("pin_id_values",
195 "This parameter cannot be used when pin_id_name is not provided.");
196 }
197 else if (_pin_id_values.size() != 3)
199 "pin_id_values",
200 "If pin_id_name is provided, this parameter must be provided with a length of three.");
201
202 // Just perform a simple and straightforward check for `ring_offset` here.
203 // A more comprehensive check for both `ring_offset` and `ring_radii` is done later.
204 if (std::abs(_ring_offset) >= _side_length / 2.0)
206 "ring_offset",
207 "This parameter cannot translate the ring center out of the hexagon assembly region.");
208}
209
210std::unique_ptr<MeshBase>
212{
213 /* Pair specified block names and ids */
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++)
218 for (unsigned int j = 0; j < _ring_block_names[i].size(); j++)
219 {
220 tmp_block_names.emplace(_ring_block_names[i][j]);
221 tmp_block_ids.emplace(_ring_block_ids[i].empty() ? (j + 1) : _ring_block_ids[i][j]);
222 if (tmp_block_names.size() != tmp_block_ids.size())
223 paramError("ring_block_names",
224 "The block name assignment must be compatible with the existing block ids.");
225 else
226 block_info.push_back(std::make_pair(
227 _ring_block_ids[i].empty() ? (j + 1) : _ring_block_ids[i][j], _ring_block_names[i][j]));
228 }
229 const subdomain_id_type max_ring_radii_size =
230 std::max({_ring_radii[0].size(), _ring_radii[1].size(), _ring_radii[2].size()});
231 for (unsigned int i = 0; i < _background_block_names.size(); i++)
232 {
233 tmp_block_names.emplace(_background_block_names[i]);
234 tmp_block_ids.emplace(_background_block_ids.empty() ? (max_ring_radii_size + i)
236 if (tmp_block_names.size() != tmp_block_ids.size())
237 paramError("background_block_names",
238 "The block name assignment must be compatible with the existing block ids.");
239 else
240 block_info.push_back(std::make_pair(_background_block_ids.empty() ? (max_ring_radii_size + i)
243 }
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++)
246 {
247 if (_has_rings[i])
248 {
249 for (unsigned int j = 0; j < (_ring_radii[i].size() + (_ring_intervals[i][0] > 1)); j++)
250 block_ids_new[i].push_back(_ring_block_ids[i].empty() ? j + 1 : _ring_block_ids[i][j]);
251 block_ids_new[i].push_back(_background_block_ids.empty() ? max_ring_radii_size + 1
252 : _background_block_ids.back());
253 }
254 else
255 {
256 block_ids_new[i].push_back(_background_block_ids.empty() ? (max_ring_radii_size + 1)
257 : _background_block_ids.front());
258 block_ids_new[i].push_back(_background_block_ids.empty() ? (max_ring_radii_size + 2)
259 : _background_block_ids.back());
260 }
261 }
262 std::vector<std::unique_ptr<ReplicatedMesh>> meshes;
263 for (unsigned int i = 0; i < 3; i++)
264 {
265 meshes.push_back(buildSinglePinSection(_side_length,
267 _ring_radii[i],
269 _has_rings[i],
273 block_ids_new[i],
275 // add sector ids
276 if (isParamValid("sector_id_name"))
277 setSectorExtraIDs(*meshes[i],
278 getParam<std::string>("sector_id_name"),
279 4,
280 std::vector<unsigned int>(4, _num_sectors_per_side));
281 // add ring ids
282 if (isParamValid("ring_id_name") && _has_rings[i])
283 setRingExtraIDs(*meshes[i],
284 getParam<std::string>("ring_id_name"),
285 4,
286 std::vector<unsigned int>(4, _num_sectors_per_side),
288 getParam<MooseEnum>("ring_id_assign_type") == "ring_wise",
289 false);
290
291 if (!_pin_id_name.empty())
292 meshes[i]->add_elem_integer(_pin_id_name, true, _pin_id_values[i]);
293 if (i > 0)
294 {
295 MeshTools::Modification::rotate(*meshes[i], 120.0 * (Real)i, 0, 0);
296 meshes[0]->stitch_meshes(*std::move(meshes[i]),
299 TOLERANCE,
300 /*clear_stitched_boundary_ids=*/true);
301 }
302 }
303
305 MeshTools::Modification::rotate(*meshes[0], 90, 0, 0);
306 else
307 MeshTools::Modification::rotate(*meshes[0], 270, 0, 0);
308 /* Add subdomain names */
309 for (const auto & block_info_pair : block_info)
310 meshes[0]->set_subdomain_name(block_info_pair.first, block_info_pair.second);
311 if (_external_boundary_id > 0)
312 MooseMesh::changeBoundaryId(*meshes[0], OUTER_SIDESET_ID, _external_boundary_id, false);
313 if (!_external_boundary_name.empty())
314 {
315 meshes[0]->get_boundary_info().sideset_name(
318 meshes[0]->get_boundary_info().nodeset_name(
321 }
322 meshes[0]->unset_is_prepared();
323 return dynamic_pointer_cast<MeshBase>(meshes[0]);
324}
325
326std::unique_ptr<ReplicatedMesh>
328 const Real side_length,
329 const Real ring_offset,
330 const std::vector<Real> ring_radii,
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,
337 dof_id_type & node_id_background_meta)
338{
339 // Each SinglePinSection, which has a diamond shape, is composed of four general slices.
340 // Considering symmetry, two unique general slices (0 and 1) need to be generated.
341 // For each slice, the center of the pin is one of its vertices; primary and secondary sides are
342 // the two sides that contain the pin center.
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);
349 // Azimuthal angle is the included angle defined by the primary and secondary sides
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) /
354 M_PI * 180.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) /
359 M_PI * 180.0);
360 // The primary side is parallel to y-axis by default (i.e., rotation_angle is zero). So the
361 // general slices need to be rotated before stitching,
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);
364 // Alpha angle is the other included angle of the slice defined by the primary side and the third
365 // side.
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) /
370 M_PI * 180.0);
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) /
375 M_PI * 180.0);
376
377 // azimuthal_list is a list of azimuthal intervals of the mesh to support radius correction to
378 // ensure preserved volume.
379 std::vector<Real> azimuthal_list;
380 for (unsigned int i = 0; i < num_sectors_per_side; i++)
381 {
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))) /
386 M_PI * 180.0);
387 }
388 for (unsigned int i = 0; i < num_sectors_per_side; i++)
389 {
390 azimuthal_list.push_back(
391 azimuthal_angle_0 +
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))) /
395 M_PI * 180.0);
396 }
397 for (unsigned int i = 0; i < num_sectors_per_side * 2; i++)
398 {
399 azimuthal_list.push_back(azimuthal_list[i] + 180.0);
400 }
401
402 std::vector<Real> ring_radii_corr;
403 if (has_rings)
404 {
405 if (preserve_volumes)
406 {
407 const Real corr_factor = PolygonalMeshGenerationUtils::radiusCorrectionFactor(azimuthal_list);
408 for (unsigned int i = 0; i < ring_radii.size(); i++)
409 ring_radii_corr.push_back(ring_radii[i] * corr_factor);
410 }
411 else
412 ring_radii_corr = ring_radii;
413 if (ring_radii_corr.back() > (side_length / 2.0 - std::abs(ring_offset)) * std::sqrt(3.0) / 2.0)
414 paramError("ring_radii",
415 "The radii of the rings cannot exceed the boundary of the diamond section.");
416 }
417
418 // build the first slice of the polygon.
419 auto mesh0 = buildGeneralSlice(
420 ring_radii_corr,
421 ring_intervals,
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)},
431 std::vector<Real>(),
432 std::vector<unsigned int>(),
433 std::vector<Real>(),
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,
440 1.0,
441 {0.0, 0.0, 0, 1.0},
442 {0.0, 0.0, 0, 1.0},
443 node_id_background_meta,
444 azimuthal_angle_0,
445 std::vector<Real>(),
446 /* side_index = */ 1,
447 false,
448 0.0,
449 rotation_angle_0,
450 false);
451
452 auto mesh1 = buildGeneralSlice(
453 ring_radii_corr,
454 ring_intervals,
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)},
464 std::vector<Real>(),
465 std::vector<unsigned int>(),
466 std::vector<Real>(),
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,
473 1.0,
474 {0.0, 0.0, 0, 1.0},
475 {0.0, 0.0, 0, 1.0},
476 node_id_background_meta,
477 azimuthal_angle_1,
478 std::vector<Real>(),
479 /* side_index = */ 1,
480 false,
481 0.0,
482 rotation_angle_1,
483 false);
484
485 mesh0->stitch_meshes(*mesh1,
487 SLICE_END,
488 TOLERANCE,
489 /*clear_stitched_boundary_ids=*/true);
490 MooseMesh::changeBoundaryId(*mesh0, SLICE_BEGIN, SLICE_END, true);
491
492 auto mesh2 = dynamic_pointer_cast<ReplicatedMesh>(mesh0->clone());
493 MeshTools::Modification::rotate(*mesh2, 0, 180.0, 0);
494 mesh0->stitch_meshes(*mesh2,
495 SLICE_END,
496 SLICE_END,
497 TOLERANCE,
498 /*clear_stitched_boundary_ids=*/true);
499 MeshTools::Modification::translate(*mesh0, side_length / 2.0 + ring_offset, 0, 0);
500
501 for (const auto & elem : mesh0->element_ptr_range())
502 elem->subdomain_id() = block_ids_new[elem->subdomain_id() - 1];
503 mesh0->unset_has_cached_elem_data();
504
505 return mesh0;
506}
registerMooseObject("ReactorApp", TriPinHexAssemblyGenerator)
void ErrorVector unsigned int
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, 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 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 isParamValid(const std::string &name) const
A base class that contains common members for Reactor module mesh generators.
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
static void addRingAndSectorIDParams(InputParameters &params)
Add InputParameters which are used by ring and sector IDs.
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
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 ...
static InputParameters validParams()
This TriPinHexAssemblyGenerator object is a base class to be inherited for polygon mesh generators.
const Real _side_length
Length of the side of the hexagon.
static InputParameters validParams()
const std::vector< std::vector< SubdomainName > > _ring_block_names
Block names of the ring regions in the three diamond sections.
enum TriPinHexAssemblyGenerator::AssmOrient _assembly_orientation
const std::vector< std::vector< unsigned int > > _ring_intervals
Numbers of radial layers in each ring region in the three diamond sections.
dof_id_type & _node_id_background_meta
MeshMetaData: maximum node id of the background region.
std::unique_ptr< MeshBase > generate() override
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.
TriPinHexAssemblyGenerator(const InputParameters &parameters)
const unsigned int _background_intervals
Numbers of radial intervals of the background regions.
const std::vector< bool > _has_rings
Whether the generated mesh contains ring regions.
const std::string _external_boundary_name
Boundary name of mesh's external boundary.
const std::string _pin_id_name
Name of extra integer ID to be assigned to each of the three pin domains.
const std::vector< std::vector< Real > > _ring_radii
Radii of concentric circles in the three diamond sections.
const boundary_id_type _external_boundary_id
Boundary ID of mesh's external boundary.
const std::vector< dof_id_type > _pin_id_values
Values of extra integer ID to be assigned to each of the three pin domains.
const Real _ring_offset
Offset distance of the circle centers from the center of each diamond section.
const std::vector< SubdomainName > _background_block_names
Block names of the background region.
const std::vector< std::vector< subdomain_id_type > > _ring_block_ids
Block ids of the ring regions in the three diamond sections.
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 ...
const bool _preserve_volumes
Whether the radii need to be corrected for polygonization during meshing.
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.
const Real radius