https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FlexiblePatternGenerator.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
11
12// C++ includes
13#include <cmath>
14
16
19{
21
22 params.addRequiredParam<std::vector<MeshGeneratorName>>("inputs", "The input MeshGenerators.");
23 MooseEnum boundary_type("HEXAGON CARTESIAN CIRCLE CUSTOM", "CUSTOM");
24 params.addParam<MooseEnum>("boundary_type",
25 boundary_type,
26 "what type of boundary is used as background for patterning.");
27 params.addParam<MeshGeneratorName>(
28 "boundary_mesh",
29 "The boundary mesh consisting of EDGE2 elements to be used as the 'CUSTOM' boundary.");
30 params.addRangeCheckedParam<unsigned int>(
31 "boundary_sectors",
32 "boundary_sectors>0",
33 "The number of sectors on each side of the HEXAGON or CARTESIAN boundary mesh or on the "
34 "circular boundary of the CIRCLE boundary mesh.");
35 params.addRangeCheckedParam<Real>("boundary_size",
36 "boundary_size>0",
37 "The pitch size of the HEXAGON or CARTESIAN boundary mesh; or "
38 "the diameter of the CIRCLE boundary mesh.");
39
40 params.addParam<std::vector<Point>>(
41 "extra_positions", {}, "The extra non-patterned positions to set the input MeshGenerators.");
42 params.addParam<std::vector<unsigned int>>(
43 "extra_positions_mg_indices",
44 {},
45 "the indices of the input mesh generators for the extra position.");
46
47 params.addParam<std::vector<std::vector<std::vector<unsigned int>>>>("hex_patterns",
48 "Hexagonal patterns set.");
49 params.addRangeCheckedParam<std::vector<Real>>(
50 "hex_pitches", "hex_pitches>0", "pitch sizes used to generate the hexagonal patterns.");
51 params.addParam<std::vector<Point>>("hex_origins",
52 "the origin positions of the hexagonal patterns,");
53 params.addParam<std::vector<Real>>("hex_rotations",
54 "the rotation angles of the hexagonal patterns,");
55
56 params.addParam<std::vector<std::vector<std::vector<unsigned int>>>>("rect_patterns",
57 "Rectangular patterns set.");
58 params.addRangeCheckedParam<std::vector<Real>>(
59 "rect_pitches_x",
60 "rect_pitches_x>0",
61 "pitch sizes in x direction used to generate the rectangular patterns.");
62 params.addRangeCheckedParam<std::vector<Real>>(
63 "rect_pitches_y",
64 "rect_pitches_y>0",
65 "pitch sizes in y direction used to generate the rectangular patterns.");
66 params.addParam<std::vector<Point>>("rect_origins",
67 "the origin positions of the rectangular patterns,");
68 params.addParam<std::vector<Real>>("rect_rotations",
69 "the rotation angles of the rectangular patterns.");
70
71 params.addParam<std::vector<std::vector<unsigned int>>>("circular_patterns",
72 "Circular patterns set.");
73 params.addRangeCheckedParam<std::vector<Real>>(
74 "circular_radii", "circular_radii>0", "the radii of the circular patterns.");
75 params.addParam<std::vector<Point>>("circular_origins",
76 "the origin positions of the circular patterns,");
77 params.addParam<std::vector<Real>>(
78 "circular_rotations",
79 "the rotation angles of the circular patterns (the azimuthal angle of the first unit mesh).");
80
81 // Parameters directly passed to XYDelaunayMeshGenerator
82 params.addParam<Real>("desired_area", 0.0, "Desired are for the background area meshing.");
83 params.addParam<std::string>(
84 "desired_area_func",
85 std::string(),
86 "Desired area as a function of x,y; omit to skip non-uniform refinement");
87
88 params.addParam<bool>("use_auto_area_func",
89 false,
90 "Use the automatic area function for triangle-meshing in the background.");
91 params.addParam<Real>(
92 "auto_area_func_default_size",
93 0,
94 "Background size for automatic area function, or 0 to use non background size");
95 params.addParam<Real>("auto_area_func_default_size_dist",
96 -1.0,
97 "Effective distance of background size for automatic area "
98 "function, or negative to use non background size");
99 params.addParam<unsigned int>("auto_area_function_num_points",
100 10,
101 "Maximum number of nearest points used for the inverse distance "
102 "interpolation algorithm for automatic area function calculation.");
103 params.addRangeCheckedParam<Real>(
104 "auto_area_function_power",
105 1.0,
106 "auto_area_function_power>0",
107 "Polynomial power of the inverse distance interpolation algorithm for automatic area "
108 "function calculation.");
109
110 params.addParam<bool>("verify_holes", true, "Whether the holes are verified.");
111 params.addRangeCheckedParam<subdomain_id_type>(
112 "background_subdomain_id",
113 "background_subdomain_id>0",
114 "Subdomain id to set on the background area meshed by Delaunay algorithm.");
115 params.addParam<SubdomainName>(
116 "background_subdomain_name",
117 "Subdomain name to set on the background area meshed by Delaunay algorithm.");
118 MooseEnum tri_elem_type("TRI3 TRI6 TRI7 DEFAULT", "DEFAULT");
119 params.addParam<MooseEnum>(
120 "tri_element_type", tri_elem_type, "Type of the triangular elements to be generated.");
121
122 params.addParam<boundary_id_type>(
123 "external_boundary_id",
124 "The boundary id of the external boundary in addition to the default 10000.");
125 params.addParam<BoundaryName>("external_boundary_name",
126 "Optional boundary name for the external boundary.");
127
128 params.addParam<bool>("delete_default_external_boundary_from_inputs",
129 true,
130 "Whether to delete the default external boundary from the input meshes.");
131
132 params.addParam<ExtraElementIDName>(
133 "cell_id_name",
134 "The name of the extra element id to be assigned for each component "
135 "unit mesh in sequential order.");
136
137 params.addParam<dof_id_type>(
138 "cell_id_shift",
139 0,
140 "The shift value to be added to the cell id to avoid conflicts with ids in other meshes.");
141
142 params.addParam<ExtraElementIDName>(
143 "pattern_id_name",
144 "The name of the extra element id to be assigned based on the ID of "
145 "the input meshes in sequential order.");
146
147 params.addParam<dof_id_type>(
148 "pattern_id_shift",
149 0,
150 "The shift value to be added to the pattern id to avoid conflicts with ids in other meshes.");
151
152 params.addClassDescription("This FlexiblePatternGenerator object is designed to generate a "
153 "mesh with a background region with dispersed unit meshes in "
154 "it and distributed based on a series of flexible patterns.");
155
156 params.addParamNamesToGroup("hex_patterns hex_pitches hex_origins hex_rotations",
157 "Hexagonal Pattern");
159 "rect_patterns rect_pitches_x rect_pitches_y rect_origins rect_rotations",
160 "Rectangular Pattern");
162 "circular_patterns circular_radii circular_origins circular_rotations", "Circular Pattern");
163 params.addParamNamesToGroup("extra_positions extra_positions_mg_indices",
164 "Extra Positions (Free-Style Patterns)");
165 params.addParamNamesToGroup("desired_area desired_area_func verify_holes background_subdomain_id "
166 "background_subdomain_name use_auto_area_func "
167 "auto_area_func_default_size auto_area_func_default_size_dist "
168 "auto_area_function_num_points auto_area_function_power",
169 "Background Area Delaunay");
171 "boundary_type boundary_mesh boundary_sectors boundary_size "
172 "delete_default_external_boundary_from_inputs external_boundary_id external_boundary_name",
173 "Boundary");
174 params.addParamNamesToGroup("cell_id_name cell_id_shift pattern_id_name pattern_id_shift",
175 "Reporting Id");
176
177 return params;
178}
179
181 : PolygonMeshGeneratorBase(parameters),
182 _input_names(getParam<std::vector<MeshGeneratorName>>("inputs")),
183 _boundary_type(getParam<MooseEnum>("boundary_type").template getEnum<BdryType>()),
184 _boundary_mesh_name(isParamValid("boundary_mesh") ? getParam<MeshGeneratorName>("boundary_mesh")
185 : MeshGeneratorName()),
186 _boundary_sectors(isParamValid("boundary_sectors") ? getParam<unsigned int>("boundary_sectors")
187 : 0),
188 _boundary_size(isParamValid("boundary_size") ? getParam<Real>("boundary_size") : 0.0),
189 _hex_patterns(
190 isParamValid("hex_patterns")
191 ? getParam<std::vector<std::vector<std::vector<unsigned int>>>>("hex_patterns")
192 : std::vector<std::vector<std::vector<unsigned int>>>()),
193 _hex_pitches(isParamValid("hex_pitches") ? getParam<std::vector<Real>>("hex_pitches")
194 : std::vector<Real>()),
195 _hex_origins(isParamValid("hex_origins")
196 ? getParam<std::vector<Point>>("hex_origins")
197 : std::vector<Point>(_hex_patterns.size(), Point(0.0, 0.0, 0.0))),
198 _hex_rotations(isParamValid("hex_rotations") ? getParam<std::vector<Real>>("hex_rotations")
199 : std::vector<Real>(_hex_patterns.size(), 0.0)),
200 _rect_patterns(
201 isParamValid("rect_patterns")
202 ? getParam<std::vector<std::vector<std::vector<unsigned int>>>>("rect_patterns")
203 : std::vector<std::vector<std::vector<unsigned int>>>()),
204 _rect_pitches_x(isParamValid("rect_pitches_x") ? getParam<std::vector<Real>>("rect_pitches_x")
205 : std::vector<Real>()),
206 _rect_pitches_y(isParamValid("rect_pitches_y") ? getParam<std::vector<Real>>("rect_pitches_y")
207 : std::vector<Real>()),
208 _rect_origins(isParamValid("rect_origins")
209 ? getParam<std::vector<Point>>("rect_origins")
210 : std::vector<Point>(_rect_patterns.size(), Point(0.0, 0.0, 0.0))),
211 _rect_rotations(isParamValid("rect_rotations") ? getParam<std::vector<Real>>("rect_rotations")
212 : std::vector<Real>(_rect_patterns.size(), 0.0)),
213 _circ_patterns(isParamValid("circular_patterns")
214 ? getParam<std::vector<std::vector<unsigned int>>>("circular_patterns")
215 : std::vector<std::vector<unsigned int>>()),
216 _circ_radii(isParamValid("circular_radii") ? getParam<std::vector<Real>>("circular_radii")
217 : std::vector<Real>()),
218 _circ_origins(isParamValid("circular_origins")
219 ? getParam<std::vector<Point>>("circular_origins")
220 : std::vector<Point>(_circ_patterns.size(), Point(0.0, 0.0, 0.0))),
221 _circ_rotations(isParamValid("circular_rotations")
222 ? getParam<std::vector<Real>>("circular_rotations")
223 : std::vector<Real>(_circ_patterns.size(), 0.0)),
224 _background_subdomain_id(isParamValid("background_subdomain_id")
225 ? getParam<subdomain_id_type>("background_subdomain_id")
226 : Moose::INVALID_BLOCK_ID),
227 _background_subdomain_name(isParamValid("background_subdomain_name")
228 ? getParam<SubdomainName>("background_subdomain_name")
229 : SubdomainName()),
230 _delete_default_external_boundary_from_inputs(
231 getParam<bool>("delete_default_external_boundary_from_inputs")),
232 _cell_id_name(isParamValid("cell_id_name") ? getParam<ExtraElementIDName>("cell_id_name")
233 : ExtraElementIDName()),
234 _cell_id_shift(getParam<dof_id_type>("cell_id_shift")),
235 _pattern_id_name(isParamValid("pattern_id_name")
236 ? getParam<ExtraElementIDName>("pattern_id_name")
237 : ExtraElementIDName()),
238 _pattern_id_shift(getParam<dof_id_type>("pattern_id_shift")),
239 _external_boundary_id(isParamValid("external_boundary_id")
240 ? getParam<boundary_id_type>("external_boundary_id")
241 : (boundary_id_type)OUTER_SIDESET_ID),
242 _external_boundary_name(isParamValid("external_boundary_name")
243 ? getParam<BoundaryName>("external_boundary_name")
244 : BoundaryName())
245
246{
247 declareMeshesForSub("inputs");
248
249 if (_cell_id_name.empty() && isParamSetByUser("cell_id_name"))
250 paramError("cell_id_name", "This parameter must be non empty if provided.");
251 if (_cell_id_name.empty() && isParamSetByUser("cell_id_shift"))
252 paramError("cell_id_name", "This parameter must be provided if cell_id_shift is set.");
253 if (_pattern_id_name.empty() && isParamSetByUser("pattern_id_name"))
254 paramError("pattern_id_name", "This parameter must be non empty if provided.");
255 if (_pattern_id_name.empty() && isParamSetByUser("pattern_id_shift"))
256 paramError("pattern_id_name", "This parameter must be provided if pattern_id_shift is set.");
257
258 const std::vector<Point> extra_positions(getParam<std::vector<Point>>("extra_positions"));
259 const std::vector<unsigned int> extra_positions_mg_indices(
260 getParam<std::vector<unsigned int>>("extra_positions_mg_indices"));
261 if (extra_positions.size() != extra_positions_mg_indices.size())
262 paramError("extra_positions_mg_indices",
263 "This parameter must have the same size as extra_positions.");
264 std::vector<unsigned int> input_usage_count(_input_names.size(), 0);
265 for (unsigned int i = 0; i < extra_positions.size(); i++)
266 {
267 if (extra_positions_mg_indices[i] >= _input_names.size())
268 paramError("extra_positions_mg_indices",
269 "the index used for extra positions must be available in 'inputs'.");
270 input_usage_count[extra_positions_mg_indices[i]]++;
271 _positions.push_back(std::make_pair(extra_positions[i], extra_positions_mg_indices[i]));
272 }
273
275 paramError("background_subdomain_id",
276 "This parameter must be provided if background_subdomain_name is provided.");
277
279 {
280 if (_boundary_mesh_name.empty())
281 paramError("boundary_mesh", "boundary_mesh must be specified for CUSTOM boundary_type.");
282 declareMeshForSub("boundary_mesh");
283 if (_boundary_sectors > 0)
284 paramError("boundary_sectors",
285 "this parameter should not be provided for CUSTOM boundary_type.");
286 if (_boundary_size > 0.0)
287 paramError("boundary_size",
288 "this parameter should not be provided for CUSTOM boundary_type.");
289 }
290 else
291 {
292 if (!_boundary_mesh_name.empty())
293 paramError("boundary_mesh",
294 "this parameter should not be provided for non-CUSTOM "
295 "boundary_type.");
296 if (_boundary_sectors == 0)
297 paramError("boundary_sectors",
298 "this parameter must be provided for non-CUSTOM "
299 "boundary_type.");
300 if (_boundary_size == 0.0)
301 paramError("boundary_size", "this parameter must be provided for non-CUSTOM boundary_type.");
302
304 {
305 _boundary_mesh_name = name() + "_hexagon_boundary";
306 // create a submeshgenerator for the hexagon boundary
307 auto params = _app.getFactory().getValidParams("PolyLineMeshGenerator");
308 params.set<bool>("loop") = true;
309 params.set<unsigned int>("num_edges_between_points") = _boundary_sectors;
310 params.set<std::vector<Point>>("points") = {
311 Point(0.0, _boundary_size / std::sqrt(3.0), 0.0),
312 Point(_boundary_size / 2.0, _boundary_size / std::sqrt(3.0) / 2.0, 0.0),
313 Point(_boundary_size / 2.0, -_boundary_size / std::sqrt(3.0) / 2.0, 0.0),
314 Point(0.0, -_boundary_size / std::sqrt(3.0), 0.0),
315 Point(-_boundary_size / 2.0, -_boundary_size / std::sqrt(3.0) / 2.0, 0.0),
316 Point(-_boundary_size / 2.0, _boundary_size / std::sqrt(3.0) / 2.0, 0.0)};
317
318 addMeshSubgenerator("PolyLineMeshGenerator", _boundary_mesh_name, params);
319 }
321 {
322 _boundary_mesh_name = name() + "_cartesian_boundary";
323 // create a submeshgenerator for the cartesian boundary
324 auto params = _app.getFactory().getValidParams("PolyLineMeshGenerator");
325 params.set<bool>("loop") = true;
326 params.set<unsigned int>("num_edges_between_points") = _boundary_sectors;
327 params.set<std::vector<Point>>("points") = {
328 Point(_boundary_size / 2.0, _boundary_size / 2.0, 0.0),
329 Point(_boundary_size / 2.0, -_boundary_size / 2.0, 0.0),
330 Point(-_boundary_size / 2.0, -_boundary_size / 2.0, 0.0),
331 Point(-_boundary_size / 2.0, _boundary_size / 2.0, 0.0)};
332
333 addMeshSubgenerator("PolyLineMeshGenerator", _boundary_mesh_name, params);
334 }
335 else
336 {
337 _boundary_mesh_name = name() + "_circle_boundary";
338 // create a submeshgenerator for the circle boundary
339 // As we are inducing polygonization anyway, PolyLineMeshGenerator is used
340 auto params = _app.getFactory().getValidParams("PolyLineMeshGenerator");
341 params.set<bool>("loop") = true;
342 params.set<unsigned int>("num_edges_between_points") = 1;
343 // We enforce radius correction here for area preservation
344 const Real corr_factor = std::sqrt(2 * M_PI / (Real)_boundary_sectors /
345 std::sin(2 * M_PI / (Real)_boundary_sectors));
346 std::vector<Point> circular_points;
347 for (unsigned int i = 0; i < _boundary_sectors; i++)
348 {
349 const Real angle = 2.0 * M_PI * (Real)i / (Real)_boundary_sectors;
350 circular_points.push_back(Point(_boundary_size * corr_factor * std::cos(angle) / 2.0,
351 _boundary_size * corr_factor * std::sin(angle) / 2.0,
352 0.0));
353 }
354 params.set<std::vector<Point>>("points") = circular_points;
355
356 addMeshSubgenerator("PolyLineMeshGenerator", _boundary_mesh_name, params);
357 }
358 // Set metadata of an assembly mesh
359 declareMeshProperty("pattern_pitch_meta", _boundary_size);
360 declareMeshProperty<bool>("is_control_drum_meta", false);
361 }
362
363 // Hexagonal Pattern
364 if (_hex_pitches.size() != _hex_patterns.size())
365 paramError("hex_pitches",
366 "The length of this parameter must be the same as that of hex_patterns.");
367 if (_hex_origins.size() != _hex_patterns.size())
369 "hex_origins",
370 "if provided, the length of this parameter must be the same as that of hex_patterns.");
371 if (_hex_rotations.size() != _hex_patterns.size())
373 "hex_rotations",
374 "if provided, the length of this parameter must be the same as that of hex_patterns.");
375 std::vector<Point> hex_positions;
376 if (!_hex_patterns.empty())
377 {
378 unsigned int hex_index = 0;
379 for (const auto & hex_pattern : _hex_patterns)
380 {
381 const unsigned int n_hex_pattern_layers = hex_pattern.size();
382 if (n_hex_pattern_layers % 2 == 0)
383 paramError("hex_patterns",
384 "The length (layer number) of each element of this parameter must be odd to "
385 "ensure hexagonal shapes.");
386 if (n_hex_pattern_layers == 1)
387 paramError("hex_patterns",
388 "The length (layer number) of each element of this parameter must be larger "
389 "than unity.");
390 for (unsigned int i = 0; i <= n_hex_pattern_layers / 2; i++)
391 {
392 if (hex_pattern[i].size() != n_hex_pattern_layers / 2 + i + 1 ||
393 hex_pattern[n_hex_pattern_layers - 1 - i].size() != n_hex_pattern_layers / 2 + i + 1)
394 paramError("hex_patterns",
395 "The two-dimentional array element of this parameter must have a correct "
396 "hexagonal shape.");
397 }
398
399 const Point unit_shift_1 = Point(_hex_pitches[hex_index], 0.0, 0.0);
400 const Point unit_shift_2 =
401 Point(_hex_pitches[hex_index] / 2.0, _hex_pitches[hex_index] / 2.0 * std::sqrt(3.0), 0.0);
402
403 for (unsigned int i = 0; i < hex_pattern.size(); i++)
404 {
405 const Real param_2 = ((Real)hex_pattern.size() - 1.0) / 2.0 - (Real)i;
406 const Real param_1_init = -((Real)hex_pattern.size() - 1.0) / 2.0 -
407 ((i <= (hex_pattern.size() - 1) / 2)
408 ? 0.0
409 : (((Real)(hex_pattern.size() - 1) / 2) - (Real)i));
410 for (unsigned int j = 0; j < hex_pattern[i].size(); j++)
411 {
412 // Any numbers exceeding the size of inputs are used as dummy units
413 if (hex_pattern[i][j] < _input_names.size())
414 {
415 input_usage_count[hex_pattern[i][j]]++;
416 Point pt_buffer = unit_shift_1 * (param_1_init + (Real)j) + unit_shift_2 * param_2;
417 nodeCoordRotate(pt_buffer(0), pt_buffer(1), _hex_rotations[hex_index]);
418 _positions.push_back(
419 std::make_pair(pt_buffer + _hex_origins[hex_index], hex_pattern[i][j]));
420 }
421 }
422 }
423 hex_index++;
424 }
425 }
426
427 // Rectangular Pattern
428 if (_rect_pitches_x.size() != _rect_patterns.size())
429 paramError("rect_pitches_x",
430 "The length of this parameter must be the same as that of rect_patterns.");
431 if (_rect_pitches_y.size() != _rect_patterns.size())
432 paramError("rect_pitches_y",
433 "The length of this parameter must be the same as that of rect_patterns.");
434 if (_rect_origins.size() != _rect_patterns.size())
436 "rect_origins",
437 "if provided, the length of this parameter must be the same as that of rect_patterns.");
438 if (_rect_rotations.size() != _rect_patterns.size())
440 "rect_rotations",
441 "if provided, the length of this parameter must be the same as that of rect_patterns.");
442 if (!_rect_patterns.empty())
443 {
444 unsigned int rect_index = 0;
445 for (const auto & rect_pattern : _rect_patterns)
446 {
447 std::set<unsigned int> rect_pattern_elem_size;
448 for (const auto & rect_pattern_elem : rect_pattern)
449 {
450 if (rect_pattern_elem.empty())
451 paramError("rect_patterns", "Each row of the element pattern must not be empty.");
452 rect_pattern_elem_size.emplace(rect_pattern_elem.size());
453 }
454 if (rect_pattern_elem_size.size() > 1)
455 paramError("rect_patterns",
456 "The two-dimensional array element of this parameter must have a correct "
457 "rectangular shape.");
458
459 const Point unit_shift_1 = Point(_rect_pitches_x[rect_index], 0.0, 0.0);
460 const Point unit_shift_2 = Point(0.0, _rect_pitches_y[rect_index], 0.0);
461
462 for (unsigned int i = 0; i < rect_pattern.size(); i++)
463 {
464 const Real param_2 = ((Real)rect_pattern.size() - 1.0) / 2.0 - (Real)i;
465 const Real param_1_init = -((Real)rect_pattern[i].size() - 1.0) / 2.0;
466 for (unsigned int j = 0; j < rect_pattern[i].size(); j++)
467 {
468 if (rect_pattern[i][j] < _input_names.size())
469 {
470 input_usage_count[rect_pattern[i][j]]++;
471 Point pt_buffer = unit_shift_1 * (param_1_init + (Real)j) + unit_shift_2 * param_2;
472 nodeCoordRotate(pt_buffer(0), pt_buffer(1), _rect_rotations[rect_index]);
473 _positions.push_back(
474 std::make_pair(pt_buffer + _rect_origins[rect_index], rect_pattern[i][j]));
475 }
476 }
477 }
478 rect_index++;
479 }
480 }
481
482 // Circular Pattern
483 if (_circ_radii.size() != _circ_patterns.size())
484 paramError("circular_radii",
485 "The length of this parameter must be the same as that of circular_patterns.");
486 if (_circ_origins.size() != _circ_patterns.size())
488 "circular_origins",
489 "if provided, the length of this parameter must be the same as that of circular_patterns.");
490 if (_circ_rotations.size() != _circ_patterns.size())
492 "circular_rotations",
493 "if provided, the length of this parameter must be the same as that of circular_patterns.");
494 if (!_circ_patterns.empty())
495 {
496 unsigned int circ_index = 0;
497 for (const auto & circ_pattern : _circ_patterns)
498 {
499 const Real angle_step = 2.0 * M_PI / (Real)circ_pattern.size();
500
501 for (unsigned int i = 0; i < circ_pattern.size(); i++)
502 {
503 if (circ_pattern[i] < _input_names.size())
504 {
505 input_usage_count[circ_pattern[i]]++;
506 Point pt_buffer = Point(_circ_radii[circ_index] * std::cos((Real)i * angle_step),
507 _circ_radii[circ_index] * std::sin((Real)i * angle_step),
508 0.0);
509 nodeCoordRotate(pt_buffer(0), pt_buffer(1), _circ_rotations[circ_index]);
510 _positions.push_back(
511 std::make_pair(pt_buffer + _circ_origins[circ_index], circ_pattern[i]));
512 }
513 }
514 circ_index++;
515 }
516 }
517
518 if (std::count(input_usage_count.begin(), input_usage_count.end(), 0))
519 paramError("inputs", "All the input mesh generator names are not used.");
520
522 {
523 for (const auto & input_name : _input_names)
524 {
525 auto params = _app.getFactory().getValidParams("BoundaryDeletionGenerator");
526 params.set<MeshGeneratorName>("input") = input_name;
527 params.set<std::vector<BoundaryName>>("boundary_names") = {std::to_string(OUTER_SIDESET_ID)};
528
529 addMeshSubgenerator("BoundaryDeletionGenerator",
530 input_name +
531 static_cast<MeshGeneratorName>("_" + name() + "_del_ext_bdry"),
532 params);
533 }
534 }
535
536 std::vector<MeshGeneratorName> patterned_pin_mg_series;
537 for (unsigned int i = 0; i < _positions.size(); i++)
538 {
539 auto params = _app.getFactory().getValidParams("TransformGenerator");
540 params.set<MeshGeneratorName>("input") =
541 _input_names[_positions[i].second] +
542 static_cast<MeshGeneratorName>(
543 _delete_default_external_boundary_from_inputs ? ("_" + name() + "_del_ext_bdry") : "");
544 params.set<MooseEnum>("transform") = 1;
545 params.set<RealVectorValue>("vector_value") = _positions[i].first;
546
547 patterned_pin_mg_series.push_back(name() + "_pos_" + std::to_string(i));
548
549 addMeshSubgenerator("TransformGenerator", patterned_pin_mg_series.back(), params);
550
551 if (_cell_id_name.size())
552 {
553 auto params = _app.getFactory().getValidParams("ParsedExtraElementIDGenerator");
554 params.set<MeshGeneratorName>("input") = patterned_pin_mg_series.back();
555 params.set<std::string>("expression") = std::to_string(i + _cell_id_shift);
556 params.set<std::string>("extra_elem_integer_name") = _cell_id_name;
557
558 patterned_pin_mg_series.back() = name() + "_ceeid_" + std::to_string(i);
559 addMeshSubgenerator("ParsedExtraElementIDGenerator", patterned_pin_mg_series.back(), params);
560 }
561 if (_pattern_id_name.size())
562 {
563 auto params = _app.getFactory().getValidParams("ParsedExtraElementIDGenerator");
564 params.set<MeshGeneratorName>("input") = patterned_pin_mg_series.back();
565 params.set<std::string>("expression") =
566 std::to_string(_positions[i].second + _pattern_id_shift);
567 params.set<std::string>("extra_elem_integer_name") = _pattern_id_name;
568
569 patterned_pin_mg_series.back() = name() + "_peeid_" + std::to_string(i);
570 addMeshSubgenerator("ParsedExtraElementIDGenerator", patterned_pin_mg_series.back(), params);
571 }
572 }
573
574 auto params = _app.getFactory().getValidParams("XYDelaunayGenerator");
575 params.set<MeshGeneratorName>("boundary") = _boundary_mesh_name;
576 params.set<std::vector<MeshGeneratorName>>("holes") = patterned_pin_mg_series;
577 params.set<bool>("refine_boundary") = false;
578 // XYDelaunay's intrinsic checks
579 params.set<bool>("verify_holes") = getParam<bool>("verify_holes");
580 params.set<std::vector<bool>>("stitch_holes") =
581 std::vector<bool>(patterned_pin_mg_series.size(), true);
582 params.set<std::vector<bool>>("refine_holes") =
583 std::vector<bool>(patterned_pin_mg_series.size(), false);
584 params.set<Real>("desired_area") = getParam<Real>("desired_area");
585 params.set<std::string>("desired_area_func") = getParam<std::string>("desired_area_func");
586 params.set<bool>("use_auto_area_func") = getParam<bool>("use_auto_area_func");
587 if (isParamSetByUser("auto_area_func_default_size"))
588 params.set<Real>("auto_area_func_default_size") = getParam<Real>("auto_area_func_default_size");
589 if (isParamSetByUser("auto_area_func_default_size_dist"))
590 params.set<Real>("auto_area_func_default_size_dist") =
591 getParam<Real>("auto_area_func_default_size_dist");
592 if (isParamSetByUser("auto_area_function_num_points"))
593 params.set<unsigned int>("auto_area_function_num_points") =
594 getParam<unsigned int>("auto_area_function_num_points");
595 if (isParamSetByUser("auto_area_function_power"))
596 params.set<Real>("auto_area_function_power") = getParam<Real>("auto_area_function_power");
597 params.set<BoundaryName>("output_boundary") = std::to_string(OUTER_SIDESET_ID);
598 params.set<MooseEnum>("tri_element_type") = getParam<MooseEnum>("tri_element_type");
599 addMeshSubgenerator("XYDelaunayGenerator", name() + "_pattern", params);
600
601 MeshGeneratorName final_mg_name(name() + "_pattern");
603 {
604 auto params = _app.getFactory().getValidParams("RenameBlockGenerator");
605 params.set<MeshGeneratorName>("input") = name() + "_pattern";
606 params.set<std::vector<SubdomainName>>("old_block") = {"0"};
607 params.set<std::vector<SubdomainName>>("new_block") = {
608 std::to_string(_background_subdomain_id)};
609 addMeshSubgenerator("RenameBlockGenerator", name() + "_back_rename_1", params);
611 {
612 auto params = _app.getFactory().getValidParams("RenameBlockGenerator");
613 params.set<MeshGeneratorName>("input") = name() + "_back_rename_1";
614 params.set<std::vector<SubdomainName>>("old_block") = {
615 std::to_string(_background_subdomain_id)};
616 params.set<std::vector<SubdomainName>>("new_block") = {_background_subdomain_name};
617 addMeshSubgenerator("RenameBlockGenerator", name() + "_back_rename_2", params);
618 final_mg_name = name() + "_back_rename_2";
619 }
620 else
621 final_mg_name = name() + "_back_rename_1";
622 }
623
624 _build_mesh = &getMeshByName(final_mg_name);
625}
626
627std::unique_ptr<MeshBase>
629{
631 MooseMesh::changeBoundaryId(**_build_mesh, OUTER_SIDESET_ID, _external_boundary_id, false);
632 if (!_external_boundary_name.empty())
633 {
634 // Check if _external_boundary_name has been assigned to another boundary id
635 const auto external_id_by_name =
636 (*_build_mesh)->get_boundary_info().get_id_by_name(_external_boundary_name);
637 if ((external_id_by_name != Moose::INVALID_BOUNDARY_ID) &&
638 (external_id_by_name != _external_boundary_id))
639 paramError("external_boundary_name",
640 "External boundary name " + _external_boundary_name +
641 " is already associated with id " + std::to_string(external_id_by_name) +
642 ", which differs from the user-specified external_boundary_id " +
643 std::to_string(_external_boundary_id));
644
645 (*_build_mesh)->get_boundary_info().sideset_name(_external_boundary_id) =
647 (*_build_mesh)->get_boundary_info().nodeset_name(_external_boundary_id) =
649 }
650 (*_build_mesh)->find_neighbors();
651 (*_build_mesh)->unset_is_prepared();
652 return std::move(*_build_mesh);
653}
registerMooseObject("ReactorApp", FlexiblePatternGenerator)
void ErrorVector unsigned int
InputParameters getValidParams(const std::string &name) const
This FlexiblePatternGenerator object is designed to generate a complex mesh with a background region ...
const bool _delete_default_external_boundary_from_inputs
const std::vector< Real > _circ_radii
List of radii of the circular patterns.
const std::vector< Real > _rect_pitches_x
List of pitches of the rectangular patterns in x direction.
const dof_id_type _cell_id_shift
Shift value to be added to the extra element id to distinguish component unit cell meshes.
static InputParameters validParams()
const std::vector< Real > _rect_pitches_y
List of pitches of the rectangular patterns in y direction.
std::unique_ptr< MeshBase > * _build_mesh
The final mesh that is generated by the subgenerators; This mesh is generated by the subgenerators wi...
enum FlexiblePatternGenerator::BdryType _boundary_type
const BoundaryName _external_boundary_name
Boundary Name of the external boundary.
const Real _boundary_size
Pitch size of the hexagonal or cartesian background region; or diameter of the circular region.
const dof_id_type _pattern_id_shift
Shift value to be added to the extra element id to distinguish input unit meshes.
const std::vector< Real > _hex_pitches
List of pitches of the hexagonal patterns.
MeshGeneratorName _boundary_mesh_name
Name of the input mesh that defines the external boundary of the background region.
const unsigned int _boundary_sectors
Number of sectors on each side of the hexagonal or cartesian background region or on the circular bou...
const std::vector< std::vector< unsigned int > > _circ_patterns
Circular patterns.
const ExtraElementIDName _pattern_id_name
Name of the extra element id to be assigned to distinguish input unit meshes.
const std::vector< MeshGeneratorName > & _input_names
Names of input meshes that are used as unit meshes in patterning.
BdryType
Type of boundary mesh to be used for the background region.
const boundary_id_type _external_boundary_id
Boundary ID of the external boundary.
const SubdomainName _background_subdomain_name
const std::vector< Point > _rect_origins
List of origins of the rectangular patterns.
const ExtraElementIDName _cell_id_name
Name of the extra element id to be assigned to distinguish component unit cell meshes.
std::vector< std::pair< Point, unsigned int > > _positions
Positions of all the unit meshes after patterning.
const std::vector< std::vector< std::vector< unsigned int > > > _hex_patterns
Hexagonal patterns.
FlexiblePatternGenerator(const InputParameters &parameters)
const std::vector< Real > _circ_rotations
List of rotation angles of the circular patterns.
const std::vector< Real > _rect_rotations
List of rotation angles of the rectangular patterns.
std::unique_ptr< MeshBase > generate() override
const std::vector< Point > _circ_origins
List of origins of the circular patterns.
const std::vector< std::vector< std::vector< unsigned int > > > _rect_patterns
Rectangular patterns.
const std::vector< Real > _hex_rotations
List of rotation angles of the hexagonal patterns.
const std::vector< Point > _hex_origins
List of origins of the hexagonal patterns.
const subdomain_id_type _background_subdomain_id
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
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)
T & set(const std::string &name, bool quiet_mode=false)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void declareMeshForSub(const std::string &param_name)
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
void declareMeshesForSub(const std::string &param_name)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
Factory & getFactory()
const std::string & name() const
void paramError(const std::string &param, Args... args) const
bool isParamSetByUser(const std::string &name) const
const T & getParam(const std::string &name) const
MooseApp & _app
A base class that contains common members for Reactor module mesh generators.
void nodeCoordRotate(Real &x, Real &y, const Real theta) const
Calculates x and y coordinates after rotating by theta angle.
static InputParameters validParams()
const BoundaryID INVALID_BOUNDARY_ID
const SubdomainID INVALID_BLOCK_ID