https://mooseframework.inl.gov
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.");
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");
158  params.addParamNamesToGroup(
159  "rect_patterns rect_pitches_x rect_pitches_y rect_origins rect_rotations",
160  "Rectangular Pattern");
161  params.addParamNamesToGroup(
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");
170  params.addParamNamesToGroup(
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")
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())
368  paramError(
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())
372  paramError(
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())
435  paramError(
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())
439  paramError(
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())
487  paramError(
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())
491  paramError(
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);
610  if (_background_subdomain_name.size())
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 
627 std::unique_ptr<MeshBase>
629 {
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)->set_isnt_prepared();
652  return std::move(*_build_mesh);
653 }
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
registerMooseObject("ReactorApp", FlexiblePatternGenerator)
BdryType
Type of boundary mesh to be used for the background region.
const bool _delete_default_external_boundary_from_inputs
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
This FlexiblePatternGenerator object is designed to generate a complex mesh with a background region ...
const BoundaryID INVALID_BOUNDARY_ID
const BoundaryName _external_boundary_name
Boundary Name of the external boundary.
const std::vector< MeshGeneratorName > & _input_names
Names of input meshes that are used as unit meshes in patterning.
static InputParameters validParams()
const std::vector< std::vector< std::vector< unsigned int > > > _hex_patterns
Hexagonal patterns.
T & set(const std::string &name, bool quiet_mode=false)
const std::vector< std::vector< std::vector< unsigned int > > > _rect_patterns
Rectangular patterns.
InputParameters getValidParams(const std::string &name) const
const ExtraElementIDName _pattern_id_name
Name of the extra element id to be assigned to distinguish input unit meshes.
const subdomain_id_type _background_subdomain_id
const std::vector< Point > _circ_origins
List of origins of the circular patterns.
const Real _boundary_size
Pitch size of the hexagonal or cartesian background region; or diameter of the circular region...
void changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
const SubdomainName _background_subdomain_name
std::unique_ptr< MeshBase > generate() override
const std::vector< Real > _hex_rotations
List of rotation angles of the hexagonal patterns.
virtual const std::string & name() const
const ExtraElementIDName _cell_id_name
Name of the extra element id to be assigned to distinguish component unit cell meshes.
const boundary_id_type _external_boundary_id
Boundary ID of the external boundary.
void addRequiredParam(const std::string &name, const std::string &doc_string)
Factory & getFactory()
void nodeCoordRotate(Real &x, Real &y, const Real theta) const
Calculates x and y coordinates after rotating by theta angle.
void declareMeshForSub(const std::string &param_name)
const SubdomainID INVALID_BLOCK_ID
const std::vector< Real > _rect_pitches_y
List of pitches of the rectangular patterns in y direction.
static InputParameters validParams()
const std::vector< std::vector< unsigned int > > _circ_patterns
Circular patterns.
int8_t boundary_id_type
const std::vector< Real > _rect_rotations
List of rotation angles of the rectangular patterns.
const std::vector< Real > _hex_pitches
List of pitches of the hexagonal patterns.
std::unique_ptr< MeshBase > * _build_mesh
The final mesh that is generated by the subgenerators; This mesh is generated by the subgenerators wi...
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
const unsigned int _boundary_sectors
Number of sectors on each side of the hexagonal or cartesian background region or on the circular bou...
FlexiblePatternGenerator(const InputParameters &parameters)
const T & getParam(const std::string &name) const
void paramError(const std::string &param, Args... args) const
const std::vector< Real > _circ_radii
List of radii of the circular patterns.
const std::vector< Real > _circ_rotations
List of rotation angles of the circular patterns.
bool isParamSetByUser(const std::string &nm) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::pair< Point, unsigned int > > _positions
Positions of all the unit meshes after patterning.
MooseApp & _app
A base class that contains common members for Reactor module mesh generators.
const dof_id_type _cell_id_shift
Shift value to be added to the extra element id to distinguish component unit cell meshes...
void addClassDescription(const std::string &doc_string)
T & declareMeshProperty(const std::string &data_name, Args &&... args)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const std::vector< Point > _hex_origins
List of origins of the hexagonal patterns.
MeshGeneratorName _boundary_mesh_name
Name of the input mesh that defines the external boundary of the background region.
const std::vector< Real > _rect_pitches_x
List of pitches of the rectangular patterns in x direction.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void declareMeshesForSub(const std::string &param_name)
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< Point > _rect_origins
List of origins of the rectangular patterns.
void ErrorVector unsigned int
enum FlexiblePatternGenerator::BdryType _boundary_type
uint8_t dof_id_type
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)