Line data Source code
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 :
10 : #include "TriPinHexAssemblyGenerator.h"
11 : #include "PolygonalMeshGenerationUtils.h"
12 : #include "libmesh/mesh_smoother_laplace.h"
13 :
14 : #include <cmath>
15 :
16 : registerMooseObject("ReactorApp", TriPinHexAssemblyGenerator);
17 :
18 : InputParameters
19 132 : TriPinHexAssemblyGenerator::validParams()
20 : {
21 132 : InputParameters params = PolygonMeshGeneratorBase::validParams();
22 264 : params.addRequiredRangeCheckedParam<unsigned int>(
23 : "num_sectors_per_side", "num_sectors_per_side>0", "Number of azimuthal sectors per side.");
24 396 : params.addRangeCheckedParam<unsigned int>(
25 : "background_intervals",
26 264 : 1,
27 : "background_intervals>0",
28 : "Number of radial meshing intervals in background "
29 : "region (region around the rings/pins in the assembly).");
30 264 : 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 264 : params.addParam<std::vector<SubdomainName>>(
35 : "background_block_names", "Optional block names for the background regions in the pins.");
36 264 : params.addRangeCheckedParam<std::vector<std::vector<Real>>>(
37 : "ring_radii", "ring_radii>0", "Radii of the three sets of major concentric circles (pins).");
38 264 : 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 264 : 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 264 : params.addParam<std::vector<std::vector<SubdomainName>>>(
45 : "ring_block_names", "Optional block names for the ring (pin) regions.");
46 264 : MooseEnum hexagon_size_style("apothem radius", "radius");
47 264 : 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).");
51 264 : params.addRequiredRangeCheckedParam<Real>(
52 : "hexagon_size", "hexagon_size>0", "Size parameter of the hexagon assembly to be generated.");
53 264 : params.addParam<Real>(
54 264 : "ring_offset", 0.0, "Offset of the ring (pin) center, shared by all three.");
55 264 : params.addParam<bool>(
56 : "preserve_volumes",
57 264 : true,
58 : "Volume of concentric circles (pins) can be preserved using this function.");
59 264 : MooseEnum assembly_orientation("pin_up pin_down", "pin_up");
60 264 : params.addParam<MooseEnum>(
61 : "assembly_orientation", assembly_orientation, "Orientation of the generated assembly.");
62 264 : params.addRangeCheckedParam<boundary_id_type>("external_boundary_id",
63 : "external_boundary_id>0",
64 : "Optional customized external boundary id.");
65 264 : params.addParam<std::string>("external_boundary_name",
66 : "Optional customized external boundary name.");
67 264 : params.addParam<std::string>(
68 : "pin_id_name", "Name of extra integer ID to be assigned to each of the three pin domains.");
69 264 : 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 264 : 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");
75 132 : addRingAndSectorIDParams(params);
76 132 : params.addClassDescription(
77 : "This TriPinHexAssemblyGenerator object generates a hexagonal assembly "
78 : "mesh with three circular pins in a triangle at the center.");
79 132 : return params;
80 132 : }
81 :
82 83 : TriPinHexAssemblyGenerator::TriPinHexAssemblyGenerator(const InputParameters & parameters)
83 : : PolygonMeshGeneratorBase(parameters),
84 83 : _ring_radii(getRingParamValues<Real>("ring_radii")),
85 81 : _has_rings({!_ring_radii[0].empty(), !_ring_radii[1].empty(), !_ring_radii[2].empty()}),
86 81 : _ring_intervals(getRingParamValues<unsigned int>("ring_intervals")),
87 79 : _ring_block_ids(getRingParamValues<subdomain_id_type>("ring_block_ids")),
88 101 : _ring_block_names(
89 77 : isParamValid("ring_block_names")
90 154 : ? (getParam<std::vector<std::vector<SubdomainName>>>("ring_block_names").size() == 1
91 24 : ? std::vector<std::vector<SubdomainName>>(
92 : 3,
93 77 : getParam<std::vector<std::vector<SubdomainName>>>("ring_block_names")
94 : .front())
95 : : getParam<std::vector<std::vector<SubdomainName>>>("ring_block_names"))
96 77 : : std::vector<std::vector<SubdomainName>>(3, std::vector<SubdomainName>())),
97 77 : _hexagon_size_style(
98 77 : getParam<MooseEnum>("hexagon_size_style").template getEnum<PolygonSizeStyle>()),
99 154 : _side_length(_hexagon_size_style == PolygonSizeStyle::radius
100 145 : ? getParam<Real>("hexagon_size")
101 95 : : (getParam<Real>("hexagon_size") / cos(M_PI / 6.0))),
102 154 : _ring_offset(getParam<Real>("ring_offset")),
103 154 : _preserve_volumes(getParam<bool>("preserve_volumes")),
104 77 : _assembly_orientation(
105 77 : getParam<MooseEnum>("assembly_orientation").template getEnum<AssmOrient>()),
106 154 : _num_sectors_per_side(getParam<unsigned int>("num_sectors_per_side")),
107 154 : _background_intervals(getParam<unsigned int>("background_intervals")),
108 308 : _background_block_ids(isParamValid("background_block_ids")
109 77 : ? getParam<std::vector<subdomain_id_type>>("background_block_ids")
110 : : std::vector<subdomain_id_type>()),
111 202 : _background_block_names(isParamValid("background_block_names")
112 77 : ? getParam<std::vector<SubdomainName>>("background_block_names")
113 : : std::vector<SubdomainName>()),
114 209 : _external_boundary_id(isParamValid("external_boundary_id")
115 187 : ? getParam<boundary_id_type>("external_boundary_id")
116 : : 0),
117 264 : _external_boundary_name(isParamValid("external_boundary_name")
118 77 : ? getParam<std::string>("external_boundary_name")
119 : : std::string()),
120 251 : _pin_id_name(isParamValid("pin_id_name") ? getParam<std::string>("pin_id_name")
121 : : std::string()),
122 198 : _pin_id_values(isParamValid("pin_id_values")
123 77 : ? getParam<std::vector<dof_id_type>>("pin_id_values")
124 : : std::vector<dof_id_type>()),
125 160 : _node_id_background_meta(declareMeshProperty<dof_id_type>("node_id_background_meta", 0))
126 : {
127 77 : declareMeshProperty<Real>("pitch_meta", _side_length * std::sqrt(3.0));
128 77 : declareMeshProperty<Real>("pattern_pitch_meta", _side_length * std::sqrt(3.0));
129 77 : declareMeshProperty<bool>("is_control_drum_meta", false);
130 77 : declareMeshProperty<unsigned int>("background_intervals_meta", _background_intervals);
131 77 : declareMeshProperty<Real>("max_radius_meta", 0.0);
132 154 : declareMeshProperty<std::vector<unsigned int>>("num_sectors_per_side_meta",
133 77 : {_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});
139 :
140 : /* Parameter checks */
141 306 : for (unsigned int i = 0; i < 3; i++)
142 231 : if (_ring_intervals[i].size() != _ring_radii[i].size())
143 2 : paramError("ring_intervals", "The parameter must be consistent with ring_radii.");
144 292 : for (unsigned int i = 0; i < 3; i++)
145 : {
146 225 : if (!_has_rings[i] && !_ring_block_ids[i].empty())
147 2 : paramError("ring_block_ids", "The parameter must be consistent with ring_radii if provided.");
148 223 : else if (!_ring_block_ids[i].empty() &&
149 166 : _ring_block_ids[i].size() != (_ring_radii[i].size() + (_ring_intervals[i][0] > 1)))
150 2 : paramError("ring_block_ids", "The parameter must be consistent with ring_radii if provided.");
151 221 : if (!_has_rings[i] && !_ring_block_names[i].empty())
152 2 : paramError("ring_block_names",
153 : "The parameter must be consistent with ring_radii if provided.");
154 219 : else if (!_ring_block_names[i].empty() &&
155 50 : _ring_block_names[i].size() != (_ring_radii[i].size() + (_ring_intervals[i][0] > 1)))
156 2 : paramError("ring_block_names",
157 : "The parameter must be consistent with ring_radii if provided.");
158 : }
159 67 : if (!_background_block_ids.empty())
160 : {
161 67 : if (_has_rings[0] && _has_rings[1] && _has_rings[2] && _background_block_ids.size() != 1)
162 2 : paramError("background_block_ids",
163 : "If provided, the size of this parameter must be one if all sections have rings.");
164 65 : else if (!_has_rings[0] && !_has_rings[1] && !_has_rings[2] && _background_intervals == 1 &&
165 : _background_block_ids.size() != 1)
166 4 : 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 61 : else if ((!_has_rings[0] || !_has_rings[1] || !_has_rings[2]) &&
170 : _background_block_ids.size() != 2)
171 2 : paramError(
172 : "background_block_ids",
173 : "If provided, the size of this parameter must be two if ring-free section exists.");
174 : }
175 59 : if (!_background_block_names.empty())
176 : {
177 22 : if (_has_rings[0] && _has_rings[1] && _has_rings[2] && _background_block_names.size() != 1)
178 2 : paramError("background_block_names",
179 : "If provided, the size of this parameter must be one if all sections have rings.");
180 20 : else if (!_has_rings[0] && !_has_rings[1] && !_has_rings[2] && _background_intervals == 1 &&
181 : _background_block_names.size() != 1)
182 0 : 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 20 : else if ((!_has_rings[0] || !_has_rings[1] || !_has_rings[2]) &&
186 : _background_block_names.size() != 2)
187 2 : paramError(
188 : "background_block_names",
189 : "If provided, the size of this parameter must be two if ring-free section exists.");
190 : }
191 55 : if (_pin_id_name.empty())
192 : {
193 35 : if (!_pin_id_values.empty())
194 2 : paramError("pin_id_values",
195 : "This parameter cannot be used when pin_id_name is not provided.");
196 : }
197 20 : else if (_pin_id_values.size() != 3)
198 2 : paramError(
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 51 : if (std::abs(_ring_offset) >= _side_length / 2.0)
205 2 : paramError(
206 : "ring_offset",
207 : "This parameter cannot translate the ring center out of the hexagon assembly region.");
208 49 : }
209 :
210 : std::unique_ptr<MeshBase>
211 49 : TriPinHexAssemblyGenerator::generate()
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 192 : for (unsigned int i = 0; i < 3; i++)
218 241 : for (unsigned int j = 0; j < _ring_block_names[i].size(); j++)
219 : {
220 98 : tmp_block_names.emplace(_ring_block_names[i][j]);
221 98 : tmp_block_ids.emplace(_ring_block_ids[i].empty() ? (j + 1) : _ring_block_ids[i][j]);
222 98 : if (tmp_block_names.size() != tmp_block_ids.size())
223 2 : paramError("ring_block_names",
224 : "The block name assignment must be compatible with the existing block ids.");
225 : else
226 96 : block_info.push_back(std::make_pair(
227 96 : _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 47 : std::max({_ring_radii[0].size(), _ring_radii[1].size(), _ring_radii[2].size()});
231 74 : for (unsigned int i = 0; i < _background_block_names.size(); i++)
232 : {
233 27 : tmp_block_names.emplace(_background_block_names[i]);
234 27 : tmp_block_ids.emplace(_background_block_ids.empty() ? (max_ring_radii_size + i)
235 : : _background_block_ids[i]);
236 27 : if (tmp_block_names.size() != tmp_block_ids.size())
237 0 : paramError("background_block_names",
238 : "The block name assignment must be compatible with the existing block ids.");
239 : else
240 54 : block_info.push_back(std::make_pair(_background_block_ids.empty() ? (max_ring_radii_size + i)
241 : : _background_block_ids[i],
242 : _background_block_names[i]));
243 : }
244 47 : std::vector<std::vector<subdomain_id_type>> block_ids_new(3, std::vector<subdomain_id_type>());
245 188 : for (unsigned int i = 0; i < 3; i++)
246 : {
247 141 : if (_has_rings[i])
248 : {
249 392 : for (unsigned int j = 0; j < (_ring_radii[i].size() + (_ring_intervals[i][0] > 1)); j++)
250 280 : block_ids_new[i].push_back(_ring_block_ids[i].empty() ? j + 1 : _ring_block_ids[i][j]);
251 112 : 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 29 : block_ids_new[i].push_back(_background_block_ids.empty() ? (max_ring_radii_size + 1)
257 : : _background_block_ids.front());
258 29 : 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 182 : for (unsigned int i = 0; i < 3; i++)
264 : {
265 272 : meshes.push_back(buildSinglePinSection(_side_length,
266 137 : _ring_offset,
267 : _ring_radii[i],
268 : _ring_intervals[i],
269 : _has_rings[i],
270 137 : _preserve_volumes,
271 137 : _num_sectors_per_side,
272 137 : _background_intervals,
273 137 : block_ids_new[i],
274 : _node_id_background_meta));
275 : // add sector ids
276 270 : if (isParamValid("sector_id_name"))
277 54 : setSectorExtraIDs(*meshes[i],
278 : getParam<std::string>("sector_id_name"),
279 : 4,
280 54 : std::vector<unsigned int>(4, _num_sectors_per_side));
281 : // add ring ids
282 405 : if (isParamValid("ring_id_name") && _has_rings[i])
283 72 : setRingExtraIDs(*meshes[i],
284 : getParam<std::string>("ring_id_name"),
285 : 4,
286 36 : std::vector<unsigned int>(4, _num_sectors_per_side),
287 : _ring_intervals[i],
288 54 : getParam<MooseEnum>("ring_id_assign_type") == "ring_wise",
289 : false);
290 :
291 135 : if (!_pin_id_name.empty())
292 108 : meshes[i]->add_elem_integer(_pin_id_name, true, _pin_id_values[i]);
293 135 : if (i > 0)
294 : {
295 90 : MeshTools::Modification::rotate(*meshes[i], 120.0 * (Real)i, 0, 0);
296 90 : meshes[0]->stitch_meshes(*std::move(meshes[i]),
297 : OUTER_SIDESET_ID,
298 : OUTER_SIDESET_ID,
299 : TOLERANCE,
300 : /*clear_stitched_boundary_ids=*/true);
301 : }
302 : }
303 :
304 45 : if (_assembly_orientation == AssmOrient::pin_up)
305 36 : MeshTools::Modification::rotate(*meshes[0], 90, 0, 0);
306 : else
307 9 : MeshTools::Modification::rotate(*meshes[0], 270, 0, 0);
308 : /* Add subdomain names */
309 162 : for (const auto & block_info_pair : block_info)
310 117 : meshes[0]->subdomain_name(block_info_pair.first) = block_info_pair.second;
311 45 : if (_external_boundary_id > 0)
312 27 : MooseMesh::changeBoundaryId(*meshes[0], OUTER_SIDESET_ID, _external_boundary_id, false);
313 45 : if (!_external_boundary_name.empty())
314 : {
315 27 : meshes[0]->get_boundary_info().sideset_name(
316 27 : _external_boundary_id > 0 ? _external_boundary_id : (boundary_id_type)OUTER_SIDESET_ID) =
317 27 : _external_boundary_name;
318 27 : meshes[0]->get_boundary_info().nodeset_name(
319 27 : _external_boundary_id > 0 ? _external_boundary_id : (boundary_id_type)OUTER_SIDESET_ID) =
320 : _external_boundary_name;
321 : }
322 : meshes[0]->set_isnt_prepared();
323 90 : return dynamic_pointer_cast<MeshBase>(meshes[0]);
324 45 : }
325 :
326 : std::unique_ptr<ReplicatedMesh>
327 137 : TriPinHexAssemblyGenerator::buildSinglePinSection(
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 137 : const Real secondary_side_length_0(side_length / 2.0 - ring_offset);
344 : const Real secondary_side_length_1(
345 137 : std::sqrt(side_length * side_length / 4.0 * 3.0 + ring_offset * ring_offset));
346 : const Real primary_side_length_0(
347 137 : std::sqrt(side_length * side_length / 4.0 * 3.0 + ring_offset * ring_offset));
348 137 : 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 137 : acos((secondary_side_length_0 * secondary_side_length_0 +
352 137 : primary_side_length_0 * primary_side_length_0 - side_length * side_length) /
353 137 : 2.0 / primary_side_length_0 / secondary_side_length_0) /
354 137 : M_PI * 180.0);
355 : const Real azimuthal_angle_1(
356 137 : acos((secondary_side_length_1 * secondary_side_length_1 +
357 137 : primary_side_length_1 * primary_side_length_1 - side_length * side_length) /
358 137 : 2.0 / primary_side_length_1 / secondary_side_length_1) /
359 137 : 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 137 : const Real rotation_angle_0(azimuthal_angle_0 - 90.0);
363 137 : 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 137 : acos((primary_side_length_0 * primary_side_length_0 + side_length * side_length -
368 137 : secondary_side_length_0 * secondary_side_length_0) /
369 137 : 2.0 / primary_side_length_0 / side_length) /
370 137 : M_PI * 180.0);
371 : const Real alpha_angle_1(
372 137 : acos((primary_side_length_1 * primary_side_length_1 + side_length * side_length -
373 137 : secondary_side_length_1 * secondary_side_length_1) /
374 137 : 2.0 / primary_side_length_1 / side_length) /
375 137 : 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 1175 : for (unsigned int i = 0; i < num_sectors_per_side; i++)
381 : {
382 : azimuthal_list.push_back(
383 1038 : atan((Real)i * side_length / num_sectors_per_side * sin(alpha_angle_0 / 180.0 * M_PI) /
384 1038 : (primary_side_length_0 -
385 1038 : (Real)i * side_length / num_sectors_per_side * cos(alpha_angle_0 / 180.0 * M_PI))) /
386 1038 : M_PI * 180.0);
387 : }
388 1175 : for (unsigned int i = 0; i < num_sectors_per_side; i++)
389 : {
390 : azimuthal_list.push_back(
391 1038 : azimuthal_angle_0 +
392 1038 : atan((Real)i * side_length / num_sectors_per_side * sin(alpha_angle_1 / 180.0 * M_PI) /
393 1038 : (primary_side_length_1 -
394 1038 : (Real)i * side_length / num_sectors_per_side * cos(alpha_angle_1 / 180.0 * M_PI))) /
395 1038 : M_PI * 180.0);
396 : }
397 2213 : for (unsigned int i = 0; i < num_sectors_per_side * 2; i++)
398 : {
399 2076 : azimuthal_list.push_back(azimuthal_list[i] + 180.0);
400 : }
401 :
402 : std::vector<Real> ring_radii_corr;
403 137 : if (has_rings)
404 : {
405 110 : if (preserve_volumes)
406 : {
407 110 : const Real corr_factor = PolygonalMeshGenerationUtils::radiusCorrectionFactor(azimuthal_list);
408 330 : for (unsigned int i = 0; i < ring_radii.size(); i++)
409 220 : ring_radii_corr.push_back(ring_radii[i] * corr_factor);
410 : }
411 : else
412 0 : ring_radii_corr = ring_radii;
413 110 : if (ring_radii_corr.back() > (side_length / 2.0 - std::abs(ring_offset)) * std::sqrt(3.0) / 2.0)
414 2 : 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 135 : std::vector<Real>(ring_radii_corr.size(), 1.0),
423 135 : {std::vector<Real>(ring_radii_corr.size(), 0.0),
424 135 : std::vector<Real>(ring_radii_corr.size(), 0.0),
425 135 : std::vector<unsigned int>(ring_radii_corr.size(), 0),
426 135 : std::vector<Real>(ring_radii_corr.size(), 1.0)},
427 135 : {std::vector<Real>(ring_radii_corr.size(), 0.0),
428 135 : std::vector<Real>(ring_radii_corr.size(), 0.0),
429 135 : std::vector<unsigned int>(ring_radii_corr.size(), 0),
430 135 : std::vector<Real>(ring_radii_corr.size(), 1.0)},
431 270 : std::vector<Real>(),
432 135 : std::vector<unsigned int>(),
433 135 : 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 135 : std::vector<Real>(),
446 : /* side_index = */ 1,
447 : false,
448 : 0.0,
449 : rotation_angle_0,
450 405 : false);
451 :
452 : auto mesh1 = buildGeneralSlice(
453 : ring_radii_corr,
454 : ring_intervals,
455 135 : std::vector<Real>(ring_radii_corr.size(), 1.0),
456 135 : {std::vector<Real>(ring_radii_corr.size(), 0.0),
457 135 : std::vector<Real>(ring_radii_corr.size(), 0.0),
458 135 : std::vector<unsigned int>(ring_radii_corr.size(), 0),
459 135 : std::vector<Real>(ring_radii_corr.size(), 1.0)},
460 270 : {std::vector<Real>(ring_radii_corr.size(), 0.0),
461 135 : std::vector<Real>(ring_radii_corr.size(), 0.0),
462 135 : std::vector<unsigned int>(ring_radii_corr.size(), 0),
463 135 : std::vector<Real>(ring_radii_corr.size(), 1.0)},
464 270 : std::vector<Real>(),
465 135 : std::vector<unsigned int>(),
466 135 : 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 135 : std::vector<Real>(),
479 : /* side_index = */ 1,
480 : false,
481 : 0.0,
482 : rotation_angle_1,
483 405 : false);
484 :
485 135 : mesh0->stitch_meshes(*mesh1,
486 : SLICE_BEGIN,
487 : SLICE_END,
488 : TOLERANCE,
489 : /*clear_stitched_boundary_ids=*/true);
490 135 : MooseMesh::changeBoundaryId(*mesh0, SLICE_BEGIN, SLICE_END, true);
491 :
492 135 : auto mesh2 = dynamic_pointer_cast<ReplicatedMesh>(mesh0->clone());
493 135 : MeshTools::Modification::rotate(*mesh2, 0, 180.0, 0);
494 135 : mesh0->stitch_meshes(*mesh2,
495 : SLICE_END,
496 : SLICE_END,
497 : TOLERANCE,
498 : /*clear_stitched_boundary_ids=*/true);
499 135 : MeshTools::Modification::translate(*mesh0, side_length / 2.0 + ring_offset, 0, 0);
500 :
501 33102 : for (const auto & elem : mesh0->element_ptr_range())
502 16551 : elem->subdomain_id() = block_ids_new[elem->subdomain_id() - 1];
503 :
504 135 : return mesh0;
505 675 : }
|