www.mooseframework.org
ConcentricCircleMesh.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "ConcentricCircleMesh.h"
11 #include "libmesh/face_quad4.h"
12 #include "MooseMesh.h"
13 #include "libmesh/mesh_modification.h"
14 #include "libmesh/serial_mesh.h"
15 #include "libmesh/boundary_info.h"
16 #include "libmesh/utility.h"
17 // C++ includes
18 #include <cmath> // provides round, not std::round (see http://www.cplusplus.com/reference/cmath/round/)
19 
21 
22 template <>
25 {
27  MooseEnum portion(
28  "full top_right top_left bottom_left bottom_right right_half left_half top_half bottom_half",
29  "full");
30  params.addRequiredParam<unsigned int>("num_sectors",
31  "num_sectors % 2 = 0, num_sectors > 0"
32  "Number of azimuthal sectors in each quadrant"
33  "'num_sectors' must be an even number.");
34  params.addRequiredParam<std::vector<Real>>("radii", "Radii of major concentric circles");
35  params.addRequiredParam<std::vector<unsigned int>>(
36  "rings", "Number of rings in each circle or in the moderator");
37  params.addRequiredParam<Real>("inner_mesh_fraction",
38  "Length of inner square / radius of the innermost circle");
39  params.addRequiredParam<bool>(
40  "has_outer_square",
41  "It determines if meshes for a outer square are added to concentric circle meshes.");
42  params.addRangeCheckedParam<Real>(
43  "pitch",
44  0.0,
45  "pitch>=0.0",
46  "The moderator can be added to complete meshes for one unit cell of fuel assembly."
47  "Elements are quad meshes.");
48  params.addParam<MooseEnum>("portion", portion, "Control of which part of mesh is created");
49  params.addRequiredParam<bool>(
50  "preserve_volumes", "Volume of concentric circles can be preserved using this function.");
51  params.addClassDescription("This ConcentricCircleMesh source code is to generate concentric "
52  "circle meshes.");
53  return params;
54 }
55 
57  : MooseMesh(parameters),
58  _num_sectors(getParam<unsigned int>("num_sectors")),
59  _radii(getParam<std::vector<Real>>("radii")),
60  _rings(getParam<std::vector<unsigned int>>("rings")),
61  _inner_mesh_fraction(getParam<Real>("inner_mesh_fraction")),
62  _has_outer_square(getParam<bool>("has_outer_square")),
63  _pitch(getParam<Real>("pitch")),
64  _preserve_volumes(getParam<bool>("preserve_volumes")),
65  _portion(getParam<MooseEnum>("portion"))
66 {
67 
68  if (_num_sectors % 2 != 0)
69  mooseError("ConcentricCircleMesh: num_sectors must be an even number.");
70 
71  // radii data check
72  for (unsigned i = 0; i < _radii.size() - 1; ++i)
73  if (_radii[i] > _radii[i + 1])
74  mooseError("Radii must be provided in order by starting with the smallest radius and "
75  "providing the following gradual radii.");
76 
77  // condition for setting the size of inner squares.
78  if (_inner_mesh_fraction > std::cos(M_PI / 4))
79  mooseError("The aspect ratio can not be larger than cos(PI/4).");
80 
81  // size of 'rings' check
83  {
84  if (_rings.size() != _radii.size() + 1)
85  mooseError("The size of 'rings' must be equal to the size of 'radii' plus 1.");
86  }
87  else
88  {
89  if (_rings.size() != _radii.size())
90  mooseError("The size of 'rings' must be equal to the size of 'radii'.");
91  }
92  // pitch / 2 must be bigger than any raddi.
94  for (unsigned i = 0; i < _radii.size(); ++i)
95  if (_pitch / 2 < _radii[i])
96  mooseError("The pitch / 2 must be larger than any radii.");
97 }
98 
99 void
101 {
102  // Get the actual libMesh mesh
103  ReplicatedMesh & mesh = cast_ref<ReplicatedMesh &>(getMesh());
104  // Set dimension of mesh
105  mesh.set_mesh_dimension(2);
106  mesh.set_spatial_dimension(2);
107  BoundaryInfo & boundary_info = mesh.get_boundary_info();
108 
109  // Creating real mesh concentric circles
110  // i: index for _rings, j: index for _radii
111  std::vector<Real> total_concentric_circles;
112  unsigned int j = 0;
113  while (j < _radii.size())
114  {
115  unsigned int i = 0;
116  if (j == 0)
117  while (i < _rings[j])
118  {
119  total_concentric_circles.push_back(_inner_mesh_fraction * _radii[j] +
120  (_radii[j] - _inner_mesh_fraction * _radii[j]) /
121  _rings[j] * (i + 1));
122  ++i;
123  }
124  else
125  while (i < _rings[j])
126  {
127  total_concentric_circles.push_back(_radii[j - 1] +
128  (_radii[j] - _radii[j - 1]) / _rings[j] * (i + 1));
129  ++i;
130  }
131  ++j;
132  }
133 
134  // volume preserving function is used to conserve volume.
135  const Real d_angle = M_PI / 2 / _num_sectors;
136 
137  if (_preserve_volumes)
138  {
139  Real original_radius = 0.0;
140  for (unsigned i = 0; i < total_concentric_circles.size(); ++i)
141  {
142  // volume preserving function for the center circle
143  if (i == 0)
144  {
145  const Real target_area = M_PI * Utility::pow<2>(total_concentric_circles[i]);
146  Real modified_radius = std::sqrt(2 * target_area / std::sin(d_angle) / _num_sectors / 4);
147  original_radius = total_concentric_circles[i];
148  total_concentric_circles[i] = modified_radius;
149  }
150  else
151  {
152  // volume preserving functions for outer circles
153  const Real target_area = M_PI * (Utility::pow<2>(total_concentric_circles[i]) -
154  Utility::pow<2>(original_radius));
155  Real modified_radius = std::sqrt(target_area / std::sin(d_angle) / _num_sectors / 2 +
156  Utility::pow<2>(total_concentric_circles[i - 1]));
157  original_radius = total_concentric_circles[i];
158  total_concentric_circles[i] = modified_radius;
159  }
160  }
161  }
162 
163  // number of total nodes
164  unsigned num_total_nodes = 0;
165  if (_has_outer_square)
166  num_total_nodes = Utility::pow<2>(_num_sectors / 2 + 1) +
167  (_num_sectors + 1) * (total_concentric_circles.size() + _rings.back()) +
168  (_num_sectors + 1);
169  else
170  num_total_nodes = Utility::pow<2>(_num_sectors / 2 + 1) +
171  (_num_sectors + 1) * total_concentric_circles.size();
172 
173  std::vector<Node *> nodes(num_total_nodes);
174  unsigned node_id = 0;
175 
176  // for adding nodes for the square at the center of the circle
177  for (unsigned i = 0; i <= _num_sectors / 2; ++i)
178  {
179  const Real x = i * _inner_mesh_fraction * total_concentric_circles[0] / (_num_sectors / 2);
180  for (unsigned j = 0; j <= _num_sectors / 2; ++j)
181  {
182  const Real y = j * _inner_mesh_fraction * total_concentric_circles[0] / (_num_sectors / 2);
183  nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
184  ++node_id;
185  }
186  }
187 
188  // for adding the outer nodes of the square
189  Real current_radius = 0.0;
190 
191  for (unsigned layers = 0; layers < total_concentric_circles.size(); ++layers)
192  {
193  current_radius = total_concentric_circles[layers];
194  for (unsigned num_outer_nodes = 0; num_outer_nodes <= _num_sectors; ++num_outer_nodes)
195  {
196  const Real x = current_radius * std::cos(num_outer_nodes * d_angle);
197  const Real y = current_radius * std::sin(num_outer_nodes * d_angle);
198  nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
199  ++node_id;
200  }
201  }
202 
203  // adding nodes for the unit cell of fuel assembly.
204  if (_has_outer_square)
205  {
206  Real current_radius_moderator = 0.0;
207  for (unsigned i = 1; i <= _rings.back(); ++i)
208  {
209  current_radius_moderator =
210  _radii.back() + i * (_pitch / 2 - _radii.back()) / (_rings.back() + 1);
211  total_concentric_circles.push_back(current_radius_moderator);
212  for (unsigned num_outer_nodes = 0; num_outer_nodes <= _num_sectors; ++num_outer_nodes)
213  {
214  const Real x = current_radius_moderator * std::cos(num_outer_nodes * d_angle);
215  const Real y = current_radius_moderator * std::sin(num_outer_nodes * d_angle);
216  nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
217  ++node_id;
218  }
219  }
220 
221  for (unsigned j = 0; j < _num_sectors / 2 + 1; ++j)
222  {
223  const Real x = _pitch / 2;
224  const Real y = _pitch / 2 * std::tan(j * d_angle);
225  nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
226  ++node_id;
227  }
228 
229  for (unsigned i = 0; i < _num_sectors / 2; ++i)
230  {
231  const Real x = _pitch / 2 * std::cos((i + _num_sectors / 2 + 1) * d_angle) /
232  std::sin((i + _num_sectors / 2 + 1) * d_angle);
233  const Real y = _pitch / 2;
234  nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
235  ++node_id;
236  }
237  }
238  // Currently, index, limit, counter variables use the int type because of the 'modulo' function.
239  // adding elements
240  int index = 0;
241  int limit = 0;
242  int standard = static_cast<int>(_num_sectors);
243 
244  // This is to set the limit for the index
245  if (standard > 4)
246  {
247  int additional_term = 0;
248  int counter = standard;
249  while (counter > 4)
250  {
251  counter = counter - 2;
252  additional_term = additional_term + counter;
253  }
254  limit = standard + additional_term;
255  }
256  else if (standard == 4)
257  limit = standard;
258 
259  // SubdomainIDs set up
260  std::vector<unsigned int> subdomainIDs;
261  for (unsigned int i = 0; i < _rings.size(); ++i)
262  for (unsigned int j = 0; j < _rings[i]; ++j)
263  subdomainIDs.push_back(i + 1);
264 
265  if (_has_outer_square)
266  subdomainIDs.push_back(subdomainIDs.back());
267  // adding elements in the square
268  while (index <= limit)
269  {
270  Elem * elem = mesh.add_elem(new Quad4);
271  elem->set_node(0) = nodes[index];
272  elem->set_node(1) = nodes[index + _num_sectors / 2 + 1];
273  elem->set_node(2) = nodes[index + _num_sectors / 2 + 2];
274  elem->set_node(3) = nodes[index + 1];
275  elem->subdomain_id() = subdomainIDs[0];
276 
277  if (index < standard / 2)
278  boundary_info.add_side(elem, 3, 1);
279  if (index % (standard / 2 + 1) == 0)
280  boundary_info.add_side(elem, 0, 2);
281 
282  ++index;
283  if ((index - standard / 2) % (standard / 2 + 1) == 0)
284  ++index;
285  }
286 
287  index = (_num_sectors / 2 + 1) * (_num_sectors / 2);
288  limit = (_num_sectors / 2) * (_num_sectors / 2 + 2);
289 
290  // adding elements in one outer layer of the square (right side)
291  while (index < limit)
292  {
293  Elem * elem = mesh.add_elem(new Quad4);
294  elem->set_node(0) = nodes[index];
295  elem->set_node(1) = nodes[index + _num_sectors / 2 + 1];
296  elem->set_node(2) = nodes[index + _num_sectors / 2 + 2];
297  elem->set_node(3) = nodes[index + 1];
298  elem->subdomain_id() = subdomainIDs[0];
299 
300  if (index == (standard / 2 + 1) * (standard / 2))
301  boundary_info.add_side(elem, 0, 2);
302 
303  ++index;
304  }
305 
306  // adding elements in one outer layer of the square (left side)
307  int counter = 0;
308  while (index != standard / 2)
309  {
310  Elem * elem = mesh.add_elem(new Quad4);
311  elem->set_node(0) = nodes[index];
312  elem->set_node(1) = nodes[index + (_num_sectors / 2 + 1) + counter * (_num_sectors / 2 + 2)];
313  elem->set_node(2) =
314  nodes[index + (_num_sectors / 2 + 1) + counter * (_num_sectors / 2 + 2) + 1];
315  elem->set_node(3) = nodes[index - _num_sectors / 2 - 1];
316  elem->subdomain_id() = subdomainIDs[0];
317 
318  if (index == standard + 1)
319  boundary_info.add_side(elem, 2, 1);
320 
321  index = index - _num_sectors / 2 - 1;
322  ++counter;
323  }
324 
325  // adding elements for other concentric circles
326  index = Utility::pow<2>(_num_sectors / 2 + 1);
327  limit = static_cast<int>(num_total_nodes) - standard - 2;
328  int num_nodes_boundary = Utility::pow<2>(_num_sectors / 2 + 1) + _num_sectors + 1;
329 
330  counter = 0;
331  while (index < limit)
332  {
333 
334  Elem * elem = mesh.add_elem(new Quad4);
335  elem->set_node(0) = nodes[index];
336  elem->set_node(1) = nodes[index + _num_sectors + 1];
337  elem->set_node(2) = nodes[index + _num_sectors + 2];
338  elem->set_node(3) = nodes[index + 1];
339 
340  for (int i = 0; i < static_cast<int>(subdomainIDs.size()) - 1; ++i)
341  if (index < limit - (standard + 1) * i && index >= limit - (standard + 1) * (i + 1))
342  elem->subdomain_id() = subdomainIDs[subdomainIDs.size() - 1 - i];
343 
344  int const initial = Utility::pow<2>(standard / 2 + 1);
345  int const final = Utility::pow<2>(standard / 2 + 1) + _num_sectors - 1;
346 
347  if ((index - initial) % (standard + 1) == 0)
348  boundary_info.add_side(elem, 0, 2);
349  if ((index - final) % (standard + 1) == 0)
350  boundary_info.add_side(elem, 2, 1);
351  if (index > limit - (standard + 1))
352  {
353  if (_has_outer_square)
354  {
355  if (index < limit - standard + standard / 2)
356  boundary_info.add_side(elem, 1, 3);
357  else
358  boundary_info.add_side(elem, 1, 4);
359  }
360  else
361  {
362  boundary_info.add_side(elem, 1, 3);
363  }
364  }
365  ++index;
366  if (index == (num_nodes_boundary + counter * (standard + 1)) - 1)
367  {
368  ++index;
369  ++counter;
370  }
371  }
372 
373  // This is to set boundary names.
374  boundary_info.sideset_name(1) = "left";
375  boundary_info.sideset_name(2) = "bottom";
376 
377  if (!_has_outer_square)
378  boundary_info.sideset_name(3) = "outer";
379  else
380  {
381  boundary_info.sideset_name(3) = "right";
382  boundary_info.sideset_name(4) = "top";
383  }
384 
385  if (_portion == "top_left")
386  {
387  MeshTools::Modification::rotate(mesh, 90, 0, 0);
388  boundary_info.sideset_name(1) = "bottom";
389  boundary_info.sideset_name(2) = "right";
390 
391  if (!_has_outer_square)
392  boundary_info.sideset_name(3) = "outer";
393  else
394  {
395  boundary_info.sideset_name(3) = "top";
396  boundary_info.sideset_name(4) = "left";
397  }
398  }
399  else if (_portion == "bottom_left")
400  {
401  MeshTools::Modification::rotate(mesh, 180, 0, 0);
402  boundary_info.sideset_name(1) = "right";
403  boundary_info.sideset_name(2) = "top";
404 
405  if (!_has_outer_square)
406  boundary_info.sideset_name(3) = "outer";
407  else
408  {
409  boundary_info.sideset_name(3) = "left";
410  boundary_info.sideset_name(4) = "bottom";
411  }
412  }
413  else if (_portion == "bottom_right")
414  {
415  MeshTools::Modification::rotate(mesh, 270, 0, 0);
416  boundary_info.sideset_name(1) = "top";
417  boundary_info.sideset_name(2) = "left";
418 
419  if (!_has_outer_square)
420  boundary_info.sideset_name(3) = "outer";
421  else
422  {
423  boundary_info.sideset_name(3) = "bottom";
424  boundary_info.sideset_name(4) = "right";
425  }
426  }
427 
428  else if (_portion == "top_half")
429  {
430  ReplicatedMesh other_mesh(mesh);
431  // This is to rotate the mesh and also to reset boundary IDs.
432  MeshTools::Modification::rotate(other_mesh, 90, 0, 0);
433  if (_has_outer_square)
434  {
435  MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
436  MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
437  MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
438  MeshTools::Modification::change_boundary_id(other_mesh, 4, 1);
439  MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
440  MeshTools::Modification::change_boundary_id(other_mesh, 6, 3);
441  MeshTools::Modification::change_boundary_id(other_mesh, 7, 4);
442  mesh.prepare_for_use(false);
443  other_mesh.prepare_for_use(false);
444  mesh.stitch_meshes(other_mesh, 1, 3, TOLERANCE, true);
445  mesh.get_boundary_info().sideset_name(1) = "left";
446  mesh.get_boundary_info().sideset_name(2) = "bottom";
447  mesh.get_boundary_info().sideset_name(3) = "right";
448  mesh.get_boundary_info().sideset_name(4) = "top";
449  }
450  else
451  {
452  MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
453  MeshTools::Modification::change_boundary_id(other_mesh, 2, 1);
454  MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
455  mesh.prepare_for_use(false);
456  other_mesh.prepare_for_use(false);
457  mesh.stitch_meshes(other_mesh, 1, 1, TOLERANCE, true);
458 
459  MeshTools::Modification::change_boundary_id(mesh, 2, 1);
460  MeshTools::Modification::change_boundary_id(mesh, 3, 2);
461  mesh.get_boundary_info().sideset_name(1) = "bottom";
462  mesh.get_boundary_info().sideset_name(2) = "outer";
463  }
464  other_mesh.clear();
465  }
466 
467  else if (_portion == "right_half")
468  {
469  ReplicatedMesh other_mesh(mesh);
470  // This is to rotate the mesh and also to reset boundary IDs.
471  MeshTools::Modification::rotate(other_mesh, 270, 0, 0);
472  if (_has_outer_square)
473  {
474  MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
475  MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
476  MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
477  MeshTools::Modification::change_boundary_id(other_mesh, 4, 3);
478  MeshTools::Modification::change_boundary_id(other_mesh, 5, 4);
479  MeshTools::Modification::change_boundary_id(other_mesh, 6, 1);
480  MeshTools::Modification::change_boundary_id(other_mesh, 7, 2);
481  mesh.prepare_for_use(false);
482  other_mesh.prepare_for_use(false);
483  mesh.stitch_meshes(other_mesh, 2, 4, TOLERANCE, true);
484  mesh.get_boundary_info().sideset_name(1) = "left";
485  mesh.get_boundary_info().sideset_name(2) = "bottom";
486  mesh.get_boundary_info().sideset_name(3) = "right";
487  mesh.get_boundary_info().sideset_name(4) = "top";
488  }
489  else
490  {
491  MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
492  MeshTools::Modification::change_boundary_id(other_mesh, 2, 1);
493  MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
494  mesh.prepare_for_use(false);
495  other_mesh.prepare_for_use(false);
496  mesh.stitch_meshes(other_mesh, 2, 2, TOLERANCE, true);
497 
498  MeshTools::Modification::change_boundary_id(mesh, 3, 2);
499  mesh.get_boundary_info().sideset_name(1) = "left";
500  mesh.get_boundary_info().sideset_name(2) = "outer";
501  }
502  other_mesh.clear();
503  }
504  else if (_portion == "left_half")
505  {
506  ReplicatedMesh other_mesh(mesh);
507 
508  // This is to rotate the mesh and to reset boundary IDs.
509  MeshTools::Modification::rotate(other_mesh, 90, 0, 0);
510  MeshTools::Modification::rotate(mesh, 180, 0, 0);
511  if (_has_outer_square)
512  {
513  // The other mesh is created by rotating the original mesh about 90 degrees.
514  MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
515  MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
516  MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
517  MeshTools::Modification::change_boundary_id(other_mesh, 4, 1);
518  MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
519  MeshTools::Modification::change_boundary_id(other_mesh, 6, 3);
520  MeshTools::Modification::change_boundary_id(other_mesh, 7, 4);
521  // The original mesh is then rotated about 180 degrees.
522  MeshTools::Modification::change_boundary_id(mesh, 1, 5);
523  MeshTools::Modification::change_boundary_id(mesh, 2, 6);
524  MeshTools::Modification::change_boundary_id(mesh, 3, 7);
525  MeshTools::Modification::change_boundary_id(mesh, 4, 2);
526  MeshTools::Modification::change_boundary_id(mesh, 5, 3);
527  MeshTools::Modification::change_boundary_id(mesh, 6, 4);
528  MeshTools::Modification::change_boundary_id(mesh, 7, 1);
529  mesh.prepare_for_use(false);
530  other_mesh.prepare_for_use(false);
531  mesh.stitch_meshes(other_mesh, 4, 2, TOLERANCE, true);
532  mesh.get_boundary_info().sideset_name(1) = "left";
533  mesh.get_boundary_info().sideset_name(2) = "bottom";
534  mesh.get_boundary_info().sideset_name(3) = "right";
535  mesh.get_boundary_info().sideset_name(4) = "top";
536  }
537  else
538  {
539  MeshTools::Modification::change_boundary_id(mesh, 1, 5);
540  MeshTools::Modification::change_boundary_id(mesh, 2, 1);
541  MeshTools::Modification::change_boundary_id(mesh, 5, 2);
542  mesh.prepare_for_use(false);
543  other_mesh.prepare_for_use(false);
544  mesh.stitch_meshes(other_mesh, 1, 1, TOLERANCE, true);
545 
546  MeshTools::Modification::change_boundary_id(mesh, 2, 1);
547  MeshTools::Modification::change_boundary_id(mesh, 3, 2);
548  mesh.get_boundary_info().sideset_name(1) = "right";
549  mesh.get_boundary_info().sideset_name(2) = "outer";
550  }
551  other_mesh.clear();
552  }
553  else if (_portion == "bottom_half")
554  {
555  ReplicatedMesh other_mesh(mesh);
556  // This is to rotate the mesh and also to reset boundary IDs.
557  MeshTools::Modification::rotate(other_mesh, 180, 0, 0);
558  MeshTools::Modification::rotate(mesh, 270, 0, 0);
559  if (_has_outer_square)
560  {
561  // The other mesh is created by rotating the original mesh about 180 degrees.
562  MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
563  MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
564  MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
565  MeshTools::Modification::change_boundary_id(other_mesh, 4, 2);
566  MeshTools::Modification::change_boundary_id(other_mesh, 5, 3);
567  MeshTools::Modification::change_boundary_id(other_mesh, 6, 4);
568  MeshTools::Modification::change_boundary_id(other_mesh, 7, 1);
569  // The original mesh is rotated about 270 degrees.
570  MeshTools::Modification::change_boundary_id(mesh, 1, 5);
571  MeshTools::Modification::change_boundary_id(mesh, 2, 6);
572  MeshTools::Modification::change_boundary_id(mesh, 3, 7);
573  MeshTools::Modification::change_boundary_id(mesh, 4, 3);
574  MeshTools::Modification::change_boundary_id(mesh, 5, 4);
575  MeshTools::Modification::change_boundary_id(mesh, 6, 1);
576  MeshTools::Modification::change_boundary_id(mesh, 7, 2);
577  mesh.prepare_for_use(false);
578  other_mesh.prepare_for_use(false);
579  mesh.stitch_meshes(other_mesh, 1, 3, TOLERANCE, true);
580  mesh.get_boundary_info().sideset_name(1) = "left";
581  mesh.get_boundary_info().sideset_name(2) = "bottom";
582  mesh.get_boundary_info().sideset_name(3) = "right";
583  mesh.get_boundary_info().sideset_name(4) = "top";
584  }
585  else
586  {
587  MeshTools::Modification::change_boundary_id(mesh, 1, 5);
588  MeshTools::Modification::change_boundary_id(mesh, 2, 1);
589  MeshTools::Modification::change_boundary_id(mesh, 5, 2);
590  mesh.prepare_for_use(false);
591  other_mesh.prepare_for_use(false);
592  mesh.stitch_meshes(other_mesh, 1, 1, TOLERANCE, true);
593 
594  MeshTools::Modification::change_boundary_id(mesh, 2, 1);
595  MeshTools::Modification::change_boundary_id(mesh, 3, 2);
596  mesh.get_boundary_info().sideset_name(1) = "top";
597  mesh.get_boundary_info().sideset_name(2) = "outer";
598  }
599  other_mesh.clear();
600  }
601  else if (_portion == "full")
602  {
603  ReplicatedMesh portion_two(mesh);
604 
605  // This is to rotate the mesh and also to reset boundary IDs.
606  MeshTools::Modification::rotate(portion_two, 90, 0, 0);
607 
608  if (_has_outer_square)
609  {
610  // Portion 2: 2nd quadrant
611  MeshTools::Modification::change_boundary_id(portion_two, 1, 5);
612  MeshTools::Modification::change_boundary_id(portion_two, 2, 6);
613  MeshTools::Modification::change_boundary_id(portion_two, 3, 7);
614  MeshTools::Modification::change_boundary_id(portion_two, 4, 1);
615  MeshTools::Modification::change_boundary_id(portion_two, 5, 2);
616  MeshTools::Modification::change_boundary_id(portion_two, 6, 3);
617  MeshTools::Modification::change_boundary_id(portion_two, 7, 4);
618  mesh.prepare_for_use(false);
619  portion_two.prepare_for_use(false);
620  // 'top_half'
621  mesh.stitch_meshes(portion_two, 1, 3, TOLERANCE, true);
622 
623  // 'bottom_half'
624  ReplicatedMesh portion_bottom(mesh);
625  MeshTools::Modification::rotate(portion_bottom, 180, 0, 0);
626  MeshTools::Modification::change_boundary_id(portion_bottom, 1, 5);
627  MeshTools::Modification::change_boundary_id(portion_bottom, 2, 6);
628  MeshTools::Modification::change_boundary_id(portion_bottom, 3, 7);
629  MeshTools::Modification::change_boundary_id(portion_bottom, 4, 2);
630  MeshTools::Modification::change_boundary_id(portion_bottom, 5, 3);
631  MeshTools::Modification::change_boundary_id(portion_bottom, 6, 4);
632  MeshTools::Modification::change_boundary_id(portion_bottom, 7, 1);
633  mesh.prepare_for_use(false);
634  portion_bottom.prepare_for_use(false);
635  // 'full'
636  mesh.stitch_meshes(portion_bottom, 2, 4, TOLERANCE, true);
637 
638  mesh.get_boundary_info().sideset_name(1) = "left";
639  mesh.get_boundary_info().sideset_name(2) = "bottom";
640  mesh.get_boundary_info().sideset_name(3) = "right";
641  mesh.get_boundary_info().sideset_name(4) = "top";
642  portion_bottom.clear();
643  }
644  else
645  {
646  MeshTools::Modification::change_boundary_id(portion_two, 1, 5);
647  MeshTools::Modification::change_boundary_id(portion_two, 2, 1);
648  MeshTools::Modification::change_boundary_id(portion_two, 5, 2);
649  // 'top half'
650  mesh.prepare_for_use(false);
651  portion_two.prepare_for_use(false);
652  mesh.stitch_meshes(portion_two, 1, 1, TOLERANCE, true);
653  // 'bottom half'
654  ReplicatedMesh portion_bottom(mesh);
655  MeshTools::Modification::rotate(portion_bottom, 180, 0, 0);
656  // 'full'
657  mesh.prepare_for_use(false);
658  portion_bottom.prepare_for_use(false);
659  mesh.stitch_meshes(portion_bottom, 2, 2, TOLERANCE, true);
660  MeshTools::Modification::change_boundary_id(mesh, 3, 1);
661  mesh.get_boundary_info().sideset_name(1) = "outer";
662  portion_bottom.clear();
663  }
664  portion_two.clear();
665  }
666  if (_portion != "top_half" && _portion != "right_half" && _portion != "left_half" &&
667  _portion != "bottom_half" && _portion != "full")
668  mesh.prepare_for_use(false);
669 }
Real _inner_mesh_fraction
Size of inner square in relation to radius of the innermost concentric circle.
virtual void buildMesh() override
Must be overridden by child classes.
unsigned int _num_sectors
Number of sectors in one quadrant.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void mooseError(Args &&... args) const
Definition: MooseObject.h:147
static PetscErrorCode Vec x
std::vector< Real > _radii
Radii of concentric circles.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
InputParameters validParams< MooseMesh >()
Definition: MooseMesh.C:63
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:74
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
ConcentricCircleMesh(const InputParameters &parameters)
bool _has_outer_square
Adding the moderator is optional.
std::vector< unsigned int > _rings
Number of rings in each circle or in the moderator.
registerMooseObject("MooseApp", ConcentricCircleMesh)
Mesh generated from parameters.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
virtual Elem * elem(const dof_id_type i)
Various accessors (pointers/references) for Elem "i".
Definition: MooseMesh.C:2253
bool _preserve_volumes
Volume preserving function is optional.
MooseEnum _portion
Control of which portion of mesh will be developed.
InputParameters validParams< ConcentricCircleMesh >()