LCOV - code coverage report
Current view: top level - src/meshgenerators - ConcentricCircleMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 466 610 76.4 %
Date: 2025-07-17 01:28:37 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "ConcentricCircleMeshGenerator.h"
      11             : #include "CastUniquePointer.h"
      12             : #include "libmesh/replicated_mesh.h"
      13             : #include "libmesh/face_quad4.h"
      14             : #include "libmesh/mesh_modification.h"
      15             : #include "libmesh/serial_mesh.h"
      16             : #include "libmesh/boundary_info.h"
      17             : #include "libmesh/utility.h"
      18             : #include "libmesh/mesh_smoother_laplace.h"
      19             : 
      20             : // C++ includes
      21             : #include <cmath> // provides round, not std::round (see http://www.cplusplus.com/reference/cmath/round/)
      22             : 
      23             : registerMooseObject("MooseApp", ConcentricCircleMeshGenerator);
      24             : 
      25             : InputParameters
      26       14743 : ConcentricCircleMeshGenerator::validParams()
      27             : {
      28       14743 :   InputParameters params = MeshGenerator::validParams();
      29             :   MooseEnum portion(
      30             :       "full top_right top_left bottom_left bottom_right right_half left_half top_half bottom_half",
      31       14743 :       "full");
      32       14743 :   params.addRequiredParam<unsigned int>("num_sectors",
      33             :                                         "num_sectors % 2 = 0, num_sectors > 0"
      34             :                                         "Number of azimuthal sectors in each quadrant"
      35             :                                         "'num_sectors' must be an even number.");
      36       14743 :   params.addRequiredParam<std::vector<Real>>("radii", "Radii of major concentric circles");
      37       14743 :   params.addRequiredParam<std::vector<unsigned int>>(
      38             :       "rings", "Number of rings in each circle or in the enclosing square");
      39       14743 :   params.addRequiredParam<bool>(
      40             :       "has_outer_square",
      41             :       "It determines if meshes for a outer square are added to concentric circle meshes.");
      42       44229 :   params.addRangeCheckedParam<Real>(
      43             :       "pitch",
      44       29486 :       0.0,
      45             :       "pitch>=0.0",
      46             :       "The enclosing square can be added to the completed concentric circle mesh."
      47             :       "Elements are quad meshes.");
      48       14743 :   params.addParam<MooseEnum>("portion", portion, "Control of which part of mesh is created");
      49       14743 :   params.addRequiredParam<bool>(
      50             :       "preserve_volumes", "Volume of concentric circles can be preserved using this function.");
      51       14743 :   params.addParam<unsigned int>("smoothing_max_it", 1, "Number of Laplacian smoothing iterations");
      52       14743 :   params.addClassDescription(
      53             :       "This ConcentricCircleMeshGenerator source code is to generate concentric "
      54             :       "circle meshes.");
      55             : 
      56       29486 :   return params;
      57       14743 : }
      58             : 
      59         220 : ConcentricCircleMeshGenerator::ConcentricCircleMeshGenerator(const InputParameters & parameters)
      60             :   : MeshGenerator(parameters),
      61         220 :     _num_sectors(getParam<unsigned int>("num_sectors")),
      62         220 :     _radii(getParam<std::vector<Real>>("radii")),
      63         220 :     _rings(getParam<std::vector<unsigned int>>("rings")),
      64         220 :     _has_outer_square(getParam<bool>("has_outer_square")),
      65         220 :     _pitch(getParam<Real>("pitch")),
      66         220 :     _preserve_volumes(getParam<bool>("preserve_volumes")),
      67         220 :     _smoothing_max_it(getParam<unsigned int>("smoothing_max_it")),
      68         440 :     _portion(getParam<MooseEnum>("portion"))
      69             : {
      70         220 :   declareMeshProperty("use_distributed_mesh", false);
      71             : 
      72         220 :   if (_num_sectors % 2 != 0)
      73           0 :     paramError("num_sectors", "must be an even number.");
      74             : 
      75             :   // radii data check
      76         558 :   for (unsigned i = 0; i < _radii.size() - 1; ++i)
      77             :   {
      78         338 :     if (_radii[i] == 0.0)
      79           0 :       paramError("radii", "must be positive numbers.");
      80         338 :     if (_radii[i] > _radii[i + 1])
      81           0 :       paramError("radii",
      82             :                  "must be provided in order by starting with the smallest radius providing the "
      83             :                  "following gradual radii.");
      84             :   }
      85             : 
      86             :   // size of 'rings' check
      87         220 :   if (_has_outer_square)
      88             :   {
      89         106 :     if (_rings.size() != _radii.size() + 1)
      90           0 :       paramError("rings", "The size of 'rings' must be equal to the size of 'radii' plus 1.");
      91             :   }
      92             :   else
      93             :   {
      94         114 :     if (_rings.size() != _radii.size())
      95           0 :       paramError("rings", "The size of 'rings' must be equal to the size of 'radii'.");
      96             :   }
      97             :   // pitch / 2 must be bigger than any raddi.
      98         220 :   if (_has_outer_square)
      99         454 :     for (unsigned i = 0; i < _radii.size(); ++i)
     100         348 :       if (_pitch / 2 < _radii[i])
     101           0 :         paramError("pitch", "The pitch / 2 must be larger than any radii.");
     102         220 : }
     103             : 
     104             : std::unique_ptr<MeshBase>
     105         218 : ConcentricCircleMeshGenerator::generate()
     106             : {
     107         218 :   auto mesh = buildReplicatedMesh(2);
     108         218 :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
     109             : 
     110             :   // Creating real mesh concentric circles
     111             :   // i: index for _rings, j: index for _radii
     112         218 :   std::vector<Real> total_concentric_circles;
     113         218 :   unsigned int j = 0;
     114         766 :   while (j < _radii.size())
     115             :   {
     116         548 :     unsigned int i = 0;
     117         548 :     if (j == 0)
     118         582 :       while (i < _rings[j])
     119             :       {
     120         364 :         total_concentric_circles.push_back(_radii[j] / (_num_sectors / 2 + _rings[j]) *
     121         364 :                                            (i + _num_sectors / 2 + 1));
     122         364 :         ++i;
     123             :       }
     124             :     else
     125         988 :       while (i < _rings[j])
     126             :       {
     127         658 :         total_concentric_circles.push_back(_radii[j - 1] +
     128         658 :                                            (_radii[j] - _radii[j - 1]) / _rings[j] * (i + 1));
     129         658 :         ++i;
     130             :       }
     131         548 :     ++j;
     132             :   }
     133             : 
     134             :   // volume preserving function is used to conserve volume.
     135         218 :   const Real d_angle = M_PI / 2 / _num_sectors;
     136             : 
     137         218 :   if (_preserve_volumes)
     138             :   {
     139          32 :     Real original_radius = 0.0;
     140         272 :     for (unsigned i = 0; i < total_concentric_circles.size(); ++i)
     141             :     {
     142             :       // volume preserving function for the center circle
     143         240 :       if (i == 0)
     144             :       {
     145          32 :         const Real target_area = M_PI * Utility::pow<2>(total_concentric_circles[i]);
     146          32 :         Real modified_radius = std::sqrt(2 * target_area / std::sin(d_angle) / _num_sectors / 4);
     147          32 :         original_radius = total_concentric_circles[i];
     148          32 :         total_concentric_circles[i] = modified_radius;
     149             :       }
     150             :       else
     151             :       {
     152             :         // volume preserving functions for outer circles
     153         208 :         const Real target_area = M_PI * (Utility::pow<2>(total_concentric_circles[i]) -
     154         208 :                                          Utility::pow<2>(original_radius));
     155         416 :         Real modified_radius = std::sqrt(target_area / std::sin(d_angle) / _num_sectors / 2 +
     156         208 :                                          Utility::pow<2>(total_concentric_circles[i - 1]));
     157         208 :         original_radius = total_concentric_circles[i];
     158         208 :         total_concentric_circles[i] = modified_radius;
     159             :       }
     160             :     }
     161             :   }
     162             : 
     163             :   // number of total nodes
     164         218 :   unsigned num_total_nodes = 0;
     165             : 
     166         218 :   if (_has_outer_square)
     167         106 :     num_total_nodes = Utility::pow<2>(_num_sectors / 2 + 1) +
     168         106 :                       (_num_sectors + 1) * total_concentric_circles.size() +
     169         106 :                       Utility::pow<2>(_rings.back() + 2) + _num_sectors * (_rings.back() + 1) - 1;
     170             :   else
     171         224 :     num_total_nodes = Utility::pow<2>(_num_sectors / 2 + 1) +
     172         112 :                       (_num_sectors + 1) * total_concentric_circles.size();
     173             : 
     174         218 :   std::vector<Node *> nodes(num_total_nodes);
     175             : 
     176         218 :   unsigned node_id = 0;
     177             : 
     178             :   // for adding nodes for the square at the center of the circle
     179         218 :   Real xx = total_concentric_circles[0] / (_num_sectors / 2 + 1) * _num_sectors / 2;
     180         218 :   Point p1 = Point(xx, 0, 0);
     181         218 :   Point p2 = Point(0, xx, 0);
     182         218 :   Point p3 = Point(xx * std::sqrt(2.0) / 2, xx * std::sqrt(2.0) / 2, 0);
     183        1122 :   for (unsigned i = 0; i <= _num_sectors / 2; ++i)
     184             :   {
     185         904 :     Real fx = i / (_num_sectors / 2.0);
     186        4840 :     for (unsigned j = 0; j <= _num_sectors / 2; ++j)
     187             :     {
     188        3936 :       Real fy = j / (_num_sectors / 2.0);
     189        3936 :       Point p = p1 * fx * (1 - fy) + p2 * fy * (1 - fx) + p3 * fx * fy;
     190        3936 :       nodes[node_id] = mesh->add_point(p, node_id);
     191        3936 :       ++node_id;
     192             :     }
     193             :   }
     194             : 
     195             :   // for adding the outer layers of the square
     196         218 :   Real current_radius = total_concentric_circles[0];
     197             : 
     198             :   // for adding the outer circles of the square.
     199        1240 :   for (unsigned layers = 0; layers < total_concentric_circles.size(); ++layers)
     200             :   {
     201        1022 :     current_radius = total_concentric_circles[layers];
     202        8556 :     for (unsigned num_outer_nodes = 0; num_outer_nodes <= _num_sectors; ++num_outer_nodes)
     203             :     {
     204        7534 :       const Real x = current_radius * std::cos(num_outer_nodes * d_angle);
     205        7534 :       const Real y = current_radius * std::sin(num_outer_nodes * d_angle);
     206        7534 :       nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
     207        7534 :       ++node_id;
     208             :     }
     209             :   }
     210             : 
     211             :   // adding nodes for the enclosing square.
     212             :   // adding nodes for the left edge of the square.
     213             :   // applying the method for partitioning the line segments.
     214             : 
     215         218 :   if (_has_outer_square)
     216             :   {
     217             :     // putting nodes for the left side of the enclosing square.
     218         470 :     for (unsigned i = 0; i <= _num_sectors / 2; ++i)
     219             :     {
     220         364 :       const Real a1 = (_pitch / 2) * i / (_num_sectors / 2 + _rings.back() + 1);
     221         364 :       const Real b1 = _pitch / 2;
     222             : 
     223         364 :       const Real a2 = total_concentric_circles.back() * std::cos(M_PI / 2 - i * d_angle);
     224         364 :       const Real b2 = total_concentric_circles.back() * std::sin(M_PI / 2 - i * d_angle);
     225             : 
     226        1508 :       for (unsigned j = 0; j <= _rings.back(); ++j)
     227             :       {
     228        1144 :         Real x = ((_rings.back() + 1 - j) * a1 + j * a2) / (_rings.back() + 1);
     229        1144 :         Real y = ((_rings.back() + 1 - j) * b1 + j * b2) / (_rings.back() + 1);
     230        1144 :         nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
     231        1144 :         ++node_id;
     232             :       }
     233             :     }
     234             :     // putting nodes for the center part of the enclosing square.
     235         106 :     unsigned k = 1;
     236         422 :     for (unsigned i = 1; i <= _rings.back() + 1; ++i)
     237             :     {
     238             :       const Real a1 =
     239         316 :           (_pitch / 2) * (i + _num_sectors / 2) / (_num_sectors / 2 + _rings.back() + 1);
     240         316 :       const Real b1 = _pitch / 2;
     241             : 
     242         316 :       const Real a2 = _pitch / 2;
     243         316 :       const Real b2 = (_pitch / 2) * (_num_sectors / 2) / (_num_sectors / 2 + _rings.back() + 1);
     244             : 
     245         316 :       const Real a3 = total_concentric_circles.back() * std::cos(M_PI / 4);
     246         316 :       const Real b3 = total_concentric_circles.back() * std::sin(M_PI / 4);
     247             : 
     248         316 :       const Real a4 = ((_rings.back() + 1 - k) * a3 + k * a2) / (_rings.back() + 1);
     249         316 :       const Real b4 = ((_rings.back() + 1 - k) * b3 + k * b2) / (_rings.back() + 1);
     250             : 
     251        1768 :       for (unsigned j = 0; j <= _rings.back() + 1; ++j)
     252             :       {
     253        1452 :         Real x = ((_rings.back() + 1 - j) * a1 + j * a4) / (_rings.back() + 1);
     254        1452 :         Real y = ((_rings.back() + 1 - j) * b1 + j * b4) / (_rings.back() + 1);
     255        1452 :         nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
     256        1452 :         ++node_id;
     257             :       }
     258         316 :       ++k;
     259             :     }
     260             : 
     261             :     // putting nodes for the right part of the enclosing square.
     262         364 :     for (unsigned i = 1; i <= _num_sectors / 2; ++i)
     263             :     {
     264         258 :       const Real a1 = _pitch / 2;
     265             :       const Real b1 =
     266         258 :           (_pitch / 2) * (_num_sectors / 2 - i) / (_num_sectors / 2 + _rings.back() + 1);
     267             : 
     268         258 :       const Real a2 = total_concentric_circles.back() * std::cos(M_PI / 4 - i * d_angle);
     269         258 :       const Real b2 = total_concentric_circles.back() * std::sin(M_PI / 4 - i * d_angle);
     270             : 
     271        1086 :       for (unsigned j = 0; j <= _rings.back(); ++j)
     272             :       {
     273         828 :         Real x = ((_rings.back() + 1 - j) * a1 + j * a2) / (_rings.back() + 1);
     274         828 :         Real y = ((_rings.back() + 1 - j) * b1 + j * b2) / (_rings.back() + 1);
     275         828 :         nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
     276         828 :         ++node_id;
     277             :       }
     278             :     }
     279             :   }
     280             : 
     281             :   // Currently, index, limit, counter variables use the int type because of the 'modulo' function.
     282             :   // adding elements
     283         218 :   int index = 0;
     284         218 :   int limit = 0;
     285         218 :   int standard = static_cast<int>(_num_sectors);
     286             : 
     287             :   // This is to set the limit for the index
     288         218 :   if (standard > 4)
     289             :   {
     290         158 :     int additional_term = 0;
     291         158 :     int counter = standard;
     292         418 :     while (counter > 4)
     293             :     {
     294         260 :       counter = counter - 2;
     295         260 :       additional_term = additional_term + counter;
     296             :     }
     297         158 :     limit = standard + additional_term;
     298             :   }
     299          60 :   else if (standard == 4)
     300          50 :     limit = standard;
     301             : 
     302             :   // SubdomainIDs set up
     303         218 :   std::vector<unsigned int> subdomainIDs;
     304             : 
     305         218 :   if (_has_outer_square)
     306         454 :     for (unsigned int i = 0; i < _rings.size() - 1; ++i)
     307        1020 :       for (unsigned int j = 0; j < _rings[i]; ++j)
     308         672 :         subdomainIDs.push_back(i + 1);
     309             :   else
     310         312 :     for (unsigned int i = 0; i < _rings.size(); ++i)
     311         550 :       for (unsigned int j = 0; j < _rings[i]; ++j)
     312         350 :         subdomainIDs.push_back(i + 1);
     313             : 
     314             :   // adding elements in the square
     315        2564 :   while (index <= limit)
     316             :   {
     317             :     // inner circle area (polygonal core)
     318        2346 :     Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     319        2346 :     elem->set_node(0, nodes[index]);
     320        2346 :     elem->set_node(1, nodes[index + _num_sectors / 2 + 1]);
     321        2346 :     elem->set_node(2, nodes[index + _num_sectors / 2 + 2]);
     322        2346 :     elem->set_node(3, nodes[index + 1]);
     323        2346 :     elem->subdomain_id() = subdomainIDs[0];
     324             : 
     325        2346 :     if (index < standard / 2)
     326         686 :       boundary_info.add_side(elem, 3, 1);
     327        2346 :     if (index % (standard / 2 + 1) == 0)
     328         686 :       boundary_info.add_side(elem, 0, 2);
     329             : 
     330        2346 :     ++index;
     331             : 
     332             :     // increment by 2 indices is necessary depending on where the index points to.
     333        2346 :     if ((index - standard / 2) % (standard / 2 + 1) == 0)
     334         686 :       ++index;
     335             :   }
     336             : 
     337         218 :   index = (_num_sectors / 2 + 1) * (_num_sectors / 2);
     338         218 :   limit = (_num_sectors / 2) * (_num_sectors / 2 + 2);
     339             : 
     340             :   // adding elements in one outer layer of the square (right side)
     341         904 :   while (index < limit)
     342             :   {
     343             :     // inner circle elements touching B
     344         686 :     Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     345         686 :     elem->set_node(0, nodes[index]);
     346         686 :     elem->set_node(1, nodes[index + _num_sectors / 2 + 1]);
     347         686 :     elem->set_node(2, nodes[index + _num_sectors / 2 + 2]);
     348         686 :     elem->set_node(3, nodes[index + 1]);
     349         686 :     elem->subdomain_id() = subdomainIDs[0];
     350             : 
     351         686 :     if (index == (standard / 2 + 1) * (standard / 2))
     352         218 :       boundary_info.add_side(elem, 0, 2);
     353             : 
     354         686 :     ++index;
     355             :   }
     356             : 
     357             :   // adding elements in one outer layer of the square (left side)
     358         218 :   int counter = 0;
     359         904 :   while (index != standard / 2)
     360             :   {
     361             :     // inner circle elements touching C
     362         686 :     Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     363         686 :     elem->set_node(0, nodes[index]);
     364         686 :     elem->set_node(1, nodes[index + (_num_sectors / 2 + 1) + counter * (_num_sectors / 2 + 2)]);
     365         686 :     elem->set_node(2, nodes[index + (_num_sectors / 2 + 1) + counter * (_num_sectors / 2 + 2) + 1]);
     366         686 :     elem->set_node(3, nodes[index - _num_sectors / 2 - 1]);
     367         686 :     elem->subdomain_id() = subdomainIDs[0];
     368             : 
     369         686 :     if (index == standard + 1)
     370         218 :       boundary_info.add_side(elem, 2, 1);
     371             : 
     372         686 :     index = index - _num_sectors / 2 - 1;
     373         686 :     ++counter;
     374             :   }
     375             : 
     376         218 :   counter = 0;
     377             :   // adding elements for other concentric circles
     378         218 :   index = Utility::pow<2>(standard / 2 + 1);
     379         218 :   limit = Utility::pow<2>(standard / 2 + 1) +
     380         218 :           (_num_sectors + 1) * (total_concentric_circles.size() - 1);
     381             : 
     382         218 :   int num_nodes_boundary = Utility::pow<2>(standard / 2 + 1) + standard + 1;
     383             : 
     384        5358 :   while (index < limit)
     385             :   {
     386        5140 :     Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     387        5140 :     elem->set_node(0, nodes[index]);
     388        5140 :     elem->set_node(1, nodes[index + standard + 1]);
     389        5140 :     elem->set_node(2, nodes[index + standard + 2]);
     390        5140 :     elem->set_node(3, nodes[index + 1]);
     391             : 
     392       56152 :     for (int i = 0; i < static_cast<int>(subdomainIDs.size() - 1); ++i)
     393       51012 :       if (index < limit - (standard + 1) * i && index >= limit - (standard + 1) * (i + 1))
     394        5140 :         elem->subdomain_id() = subdomainIDs[subdomainIDs.size() - 1 - i];
     395             : 
     396        5140 :     const int initial = Utility::pow<2>(standard / 2 + 1);
     397        5140 :     const int final = Utility::pow<2>(standard / 2 + 1) + standard - 1;
     398             : 
     399        5140 :     if ((index - initial) % (standard + 1) == 0)
     400         804 :       boundary_info.add_side(elem, 0, 2);
     401        5140 :     if ((index - final) % (standard + 1) == 0)
     402         804 :       boundary_info.add_side(elem, 2, 1);
     403        5140 :     if (!_has_outer_square)
     404        1824 :       if (index >= limit - (standard + 1))
     405         376 :         boundary_info.add_side(elem, 1, 3);
     406             : 
     407             :     // index increment is for adding nodes for a next element.
     408        5140 :     ++index;
     409             : 
     410             :     // increment by 2 indices may be necessary depending on where the index points to.
     411             :     // this varies based on the algorithms provided for the specific element and node placement.
     412        5140 :     if (index == (num_nodes_boundary + counter * (standard + 1)) - 1)
     413             :     {
     414         804 :       ++index;
     415         804 :       ++counter;
     416             :     }
     417             :   }
     418             : 
     419             :   // Enclosing square sections
     420             :   //  ABCA
     421             :   //  C  B
     422             :   //  B  C
     423             :   //  ACBA
     424             : 
     425             :   // adding elements for the enclosing square. (top left)
     426             :   int initial =
     427         218 :       Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size();
     428             : 
     429             :   int initial2 =
     430         218 :       Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size();
     431             : 
     432         218 :   if (_has_outer_square)
     433             :   {
     434         106 :     if (_rings.back() != 0) // this must be condition up front.
     435             :     {
     436         106 :       index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size();
     437         106 :       limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     438         106 :               (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 3 -
     439         106 :               _rings.back() * (_rings.back() + 2) - (_rings.back() + 1);
     440         992 :       while (index <= limit)
     441             :       {
     442             :         // outer square sector C
     443         780 :         Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     444         780 :         elem->set_node(0, nodes[index]);
     445         780 :         elem->set_node(1, nodes[index + 1]);
     446         780 :         elem->set_node(2, nodes[index + 1 + _rings.back() + 1]);
     447         780 :         elem->set_node(3, nodes[index + 1 + _rings.back()]);
     448         780 :         elem->subdomain_id() = subdomainIDs.back() + 1;
     449             : 
     450         780 :         if (index < (initial2 + static_cast<int>(_rings.back())))
     451         210 :           boundary_info.add_side(elem, 0, 1);
     452             : 
     453         780 :         if (index == initial)
     454         364 :           boundary_info.add_side(elem, 3, 4);
     455             : 
     456         780 :         ++index;
     457             : 
     458             :         // As mentioned before, increment by 2 indices may be required depending on where the index
     459             :         // points to.
     460         780 :         if ((index - initial) % static_cast<int>(_rings.back()) == 0)
     461             :         {
     462         364 :           ++index;
     463         364 :           initial = initial + (static_cast<int>(_rings.back()) + 1);
     464             :         }
     465             :       }
     466             : 
     467             :       // adding elements for the enclosing square. (top right)
     468         106 :       initial = Utility::pow<2>(standard / 2 + 1) +
     469         318 :                 (standard + 1) * total_concentric_circles.size() +
     470         106 :                 (_rings.back() + 1) * (standard / 2 + 1);
     471             : 
     472         106 :       limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     473         106 :               (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 3 -
     474         106 :               (_rings.back() + 2);
     475             : 
     476        1032 :       while (index <= limit)
     477             :       {
     478             :         // outer square sector A
     479         820 :         Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     480         820 :         elem->set_node(3, nodes[index]);
     481         820 :         elem->set_node(2, nodes[index + _rings.back() + 2]);
     482         820 :         elem->set_node(1, nodes[index + _rings.back() + 3]);
     483         820 :         elem->set_node(0, nodes[index + 1]);
     484         820 :         elem->subdomain_id() = subdomainIDs.back() + 1;
     485             : 
     486         820 :         if (index >= static_cast<int>(limit - (_rings.back() + 1)))
     487         316 :           boundary_info.add_side(elem, 1, 3);
     488             : 
     489         820 :         if ((index - initial) % static_cast<int>(_rings.back() + 2) == 0)
     490         210 :           boundary_info.add_side(elem, 2, 4);
     491             : 
     492         820 :         ++index;
     493             : 
     494         820 :         if ((index - initial) % static_cast<int>(_rings.back() + 1) == 0)
     495             :         {
     496         210 :           ++index;
     497         210 :           initial = initial + (static_cast<int>(_rings.back()) + 2);
     498             :         }
     499             :       }
     500             : 
     501             :       // adding elements for the enclosing square. (one center quad)
     502         106 :       int index1 = Utility::pow<2>(standard / 2 + 1) +
     503         106 :                    (standard + 1) * (total_concentric_circles.size() - 1) + standard / 2;
     504             : 
     505         106 :       int index2 = Utility::pow<2>(standard / 2 + 1) +
     506         318 :                    (standard + 1) * total_concentric_circles.size() +
     507         106 :                    (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 3 -
     508         106 :                    _rings.back() * (_rings.back() + 2) - (_rings.back() + 1);
     509             : 
     510             :       // pointy tips of the A sectors, touching the inner circle
     511         106 :       Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     512         106 :       elem->set_node(3, nodes[index1]);
     513         106 :       elem->set_node(2, nodes[index2]);
     514         106 :       elem->set_node(1, nodes[index2 + _rings.back() + 1]);
     515         106 :       elem->set_node(0, nodes[index2 + _rings.back() + 2]);
     516         106 :       elem->subdomain_id() = subdomainIDs.back() + 1;
     517             : 
     518             :       // adding elements for the left mid part.
     519         106 :       index = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
     520         106 :               (standard + 1) * (total_concentric_circles.size() - 1);
     521         106 :       limit = index + standard / 2 - 1;
     522             : 
     523         364 :       while (index <= limit)
     524             :       {
     525             :         // outer square elements in sector C touching the inner circle
     526         258 :         Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     527         258 :         elem->set_node(3, nodes[index]);
     528         258 :         elem->set_node(2, nodes[index + 1]);
     529         258 :         elem->set_node(1, nodes[index2 - _rings.back() - 1]);
     530         258 :         elem->set_node(0, nodes[index2]);
     531         258 :         elem->subdomain_id() = subdomainIDs.back() + 1;
     532             : 
     533         258 :         if (index == limit)
     534         106 :           boundary_info.add_side(elem, 1, 1);
     535             : 
     536         258 :         ++index;
     537             : 
     538             :         // two different indices are used to add nodes for an element.
     539         258 :         index2 = index2 - _rings.back() - 1;
     540             :       }
     541             : 
     542             :       // adding elements for the right mid part.
     543         106 :       index1 = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
     544         106 :                (standard + 1) * (total_concentric_circles.size() - 1);
     545         106 :       index2 = Utility::pow<2>(standard / 2 + 1) +
     546         318 :                (standard + 1) * total_concentric_circles.size() +
     547         106 :                (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2 +
     548         106 :                (_rings.back() + 1);
     549             :       int index3 =
     550         106 :           Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     551         106 :           (_rings.back() + 1) * (standard / 2) - 1 + (_rings.back() + 1) + (_rings.back() + 2);
     552             : 
     553             :       // elements clockwise from the A sector tips
     554         106 :       elem = mesh->add_elem(std::make_unique<Quad4>());
     555         106 :       elem->set_node(0, nodes[index1]);
     556         106 :       elem->set_node(1, nodes[index1 - 1]);
     557         106 :       elem->set_node(2, nodes[index2]);
     558         106 :       elem->set_node(3, nodes[index3]);
     559         106 :       elem->subdomain_id() = subdomainIDs.back() + 1;
     560             : 
     561         106 :       if (standard == 2)
     562          10 :         boundary_info.add_side(elem, 1, 2);
     563             : 
     564             :       // adding elements for the right mid bottom part.
     565             : 
     566         106 :       index = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
     567         106 :               (standard + 1) * (total_concentric_circles.size() - 1) - 2;
     568         106 :       index1 = Utility::pow<2>(standard / 2 + 1) +
     569         318 :                (standard + 1) * total_concentric_circles.size() +
     570         106 :                (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2 +
     571         106 :                (_rings.back() + 1) * 2;
     572             : 
     573         106 :       limit = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
     574         106 :               (standard + 1) * (total_concentric_circles.size() - 1) - standard / 2;
     575             : 
     576         106 :       if (standard != 2)
     577             :       {
     578         248 :         while (index >= limit)
     579             :         {
     580             :           // outer square elements in sector B touching the inner circle
     581         152 :           Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     582         152 :           elem->set_node(0, nodes[index]);
     583         152 :           elem->set_node(1, nodes[index1]);
     584         152 :           elem->set_node(2, nodes[index1 - (_rings.back() + 1)]);
     585         152 :           elem->set_node(3, nodes[index + 1]);
     586         152 :           elem->subdomain_id() = subdomainIDs.back() + 1;
     587             : 
     588         152 :           if (index == limit)
     589          96 :             boundary_info.add_side(elem, 0, 2);
     590         152 :           --index;
     591         152 :           index1 = index1 + (_rings.back() + 1);
     592             :         }
     593             :       }
     594             : 
     595             :       // adding elements for the right low part.
     596         106 :       index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     597         106 :               (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2;
     598             : 
     599         106 :       index1 = index - (_rings.back() + 2);
     600             :       // dummy condition for elem definition
     601         106 :       if (standard >= 2)
     602             :       {
     603             :         // single elements between A and B on the outside of the square
     604         106 :         Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     605         106 :         elem->set_node(3, nodes[index]);
     606         106 :         elem->set_node(2, nodes[index + 1]);
     607         106 :         elem->set_node(1, nodes[index + 2]);
     608         106 :         elem->set_node(0, nodes[index1]);
     609         106 :         elem->subdomain_id() = subdomainIDs.back() + 1;
     610             : 
     611         106 :         boundary_info.add_side(elem, 2, 3);
     612             : 
     613         106 :         if (standard == 2)
     614          10 :           boundary_info.add_side(elem, 1, 2);
     615             :       }
     616             : 
     617         106 :       index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     618         106 :               (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2 -
     619         106 :               (_rings.back() + 2);
     620             : 
     621         106 :       limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     622         106 :               (_rings.back() + 1) * (standard / 2) + (_rings.back() + 2) * 2 - 2;
     623             : 
     624         106 :       int k = 1;
     625         210 :       while (index > limit)
     626             :       {
     627         104 :         Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     628         104 :         elem->set_node(3, nodes[index]);
     629         104 :         elem->set_node(2, nodes[index + (_rings.back() + 2) * k + k + 1]);
     630         104 :         elem->set_node(1, nodes[index + (_rings.back() + 2) * k + k + 2]);
     631         104 :         elem->set_node(0, nodes[index - _rings.back() - 2]);
     632         104 :         elem->subdomain_id() = subdomainIDs.back() + 1;
     633         104 :         index = index - (_rings.back() + 2);
     634         104 :         ++k;
     635             : 
     636         104 :         if (standard == 2)
     637           0 :           boundary_info.add_side(elem, 1, 2);
     638             :       }
     639             : 
     640         106 :       index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     641         106 :               (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 1;
     642         106 :       initial = Utility::pow<2>(standard / 2 + 1) +
     643         318 :                 (standard + 1) * total_concentric_circles.size() +
     644         106 :                 (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 1;
     645         106 :       limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
     646         106 :               (_rings.back() + 1) * (standard / 2) * 2 + Utility::pow<2>(_rings.back() + 2) - 2 -
     647         106 :               _rings.back() - 1;
     648             : 
     649         106 :       initial2 = Utility::pow<2>(standard / 2 + 1) +
     650         318 :                  (standard + 1) * total_concentric_circles.size() +
     651         106 :                  (_rings.back() + 1) * (standard / 2) * 2 + Utility::pow<2>(_rings.back() + 2) - 2 -
     652         106 :                  (_rings.back() + 1) * 2;
     653             : 
     654         106 :       if (standard > 2)
     655             :       {
     656         552 :         while (index < limit)
     657             :         {
     658         360 :           Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
     659         360 :           elem->set_node(0, nodes[index]);
     660         360 :           elem->set_node(1, nodes[index + 1]);
     661         360 :           elem->set_node(2, nodes[index + 1 + _rings.back() + 1]);
     662         360 :           elem->set_node(3, nodes[index + 1 + _rings.back()]);
     663         360 :           elem->subdomain_id() = subdomainIDs.back() + 1;
     664             : 
     665         360 :           if (index > initial2)
     666         200 :             boundary_info.add_side(elem, 2, 2);
     667             : 
     668         360 :           if ((index - initial) == 0)
     669         152 :             boundary_info.add_side(elem, 3, 3);
     670             : 
     671         360 :           ++index;
     672             : 
     673         360 :           if ((index - initial) % static_cast<int>(_rings.back()) == 0)
     674             :           {
     675         152 :             ++index;
     676         152 :             initial = initial + (static_cast<int>(_rings.back()) + 1);
     677             :           }
     678             :         }
     679             :       }
     680             :     }
     681             :   }
     682             : 
     683             :   // This is to set boundary names.
     684         218 :   boundary_info.sideset_name(1) = "left";
     685         218 :   boundary_info.sideset_name(2) = "bottom";
     686             : 
     687         218 :   if (!_has_outer_square)
     688         112 :     boundary_info.sideset_name(3) = "outer";
     689             :   else
     690             :   {
     691         106 :     boundary_info.sideset_name(3) = "right";
     692         106 :     boundary_info.sideset_name(4) = "top";
     693             :   }
     694             : 
     695         218 :   if (_portion == "top_left")
     696             :   {
     697          10 :     MeshTools::Modification::rotate(*mesh, 90, 0, 0);
     698          10 :     boundary_info.sideset_name(1) = "bottom";
     699          10 :     boundary_info.sideset_name(2) = "right";
     700             : 
     701          10 :     if (!_has_outer_square)
     702          10 :       boundary_info.sideset_name(3) = "outer";
     703             :     else
     704             :     {
     705           0 :       boundary_info.sideset_name(3) = "top";
     706           0 :       boundary_info.sideset_name(4) = "left";
     707             :     }
     708             :   }
     709         208 :   else if (_portion == "bottom_left")
     710             :   {
     711          10 :     MeshTools::Modification::rotate(*mesh, 180, 0, 0);
     712          10 :     boundary_info.sideset_name(1) = "right";
     713          10 :     boundary_info.sideset_name(2) = "top";
     714             : 
     715          10 :     if (!_has_outer_square)
     716          10 :       boundary_info.sideset_name(3) = "outer";
     717             :     else
     718             :     {
     719           0 :       boundary_info.sideset_name(3) = "left";
     720           0 :       boundary_info.sideset_name(4) = "bottom";
     721             :     }
     722             :   }
     723         198 :   else if (_portion == "bottom_right")
     724             :   {
     725          10 :     MeshTools::Modification::rotate(*mesh, 270, 0, 0);
     726          10 :     boundary_info.sideset_name(1) = "top";
     727          10 :     boundary_info.sideset_name(2) = "left";
     728             : 
     729          10 :     if (!_has_outer_square)
     730          10 :       boundary_info.sideset_name(3) = "outer";
     731             :     else
     732             :     {
     733           0 :       boundary_info.sideset_name(3) = "bottom";
     734           0 :       boundary_info.sideset_name(4) = "right";
     735             :     }
     736             :   }
     737             : 
     738         188 :   else if (_portion == "top_half")
     739             :   {
     740           0 :     ReplicatedMesh other_mesh(*mesh);
     741             :     // This is to rotate the mesh and also to reset boundary IDs.
     742           0 :     MeshTools::Modification::rotate(other_mesh, 90, 0, 0);
     743           0 :     if (_has_outer_square)
     744             :     {
     745           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
     746           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
     747           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
     748           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 4, 1);
     749           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
     750           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 6, 3);
     751           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 7, 4);
     752           0 :       mesh->prepare_for_use();
     753           0 :       other_mesh.prepare_for_use();
     754           0 :       mesh->stitch_meshes(other_mesh, 1, 3, TOLERANCE, true, /*verbose=*/false);
     755           0 :       mesh->get_boundary_info().sideset_name(1) = "left";
     756           0 :       mesh->get_boundary_info().sideset_name(2) = "bottom";
     757           0 :       mesh->get_boundary_info().sideset_name(3) = "right";
     758           0 :       mesh->get_boundary_info().sideset_name(4) = "top";
     759             :     }
     760             :     else
     761             :     {
     762           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
     763           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 2, 1);
     764           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
     765           0 :       mesh->prepare_for_use();
     766           0 :       other_mesh.prepare_for_use();
     767           0 :       mesh->stitch_meshes(other_mesh, 1, 1, TOLERANCE, true, /*verbose=*/false);
     768             : 
     769           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
     770           0 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
     771           0 :       mesh->get_boundary_info().sideset_name(1) = "bottom";
     772           0 :       mesh->get_boundary_info().sideset_name(2) = "outer";
     773             :     }
     774           0 :     other_mesh.clear();
     775           0 :   }
     776             : 
     777         188 :   else if (_portion == "right_half")
     778             :   {
     779           0 :     ReplicatedMesh other_mesh(*mesh);
     780             :     // This is to rotate the mesh and also to reset boundary IDs.
     781           0 :     MeshTools::Modification::rotate(other_mesh, 270, 0, 0);
     782           0 :     if (_has_outer_square)
     783             :     {
     784           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
     785           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
     786           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
     787           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 4, 3);
     788           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 5, 4);
     789           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 6, 1);
     790           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 7, 2);
     791           0 :       mesh->prepare_for_use();
     792           0 :       other_mesh.prepare_for_use();
     793           0 :       mesh->stitch_meshes(other_mesh, 2, 4, TOLERANCE, true, /*verbose=*/false);
     794           0 :       mesh->get_boundary_info().sideset_name(1) = "left";
     795           0 :       mesh->get_boundary_info().sideset_name(2) = "bottom";
     796           0 :       mesh->get_boundary_info().sideset_name(3) = "right";
     797           0 :       mesh->get_boundary_info().sideset_name(4) = "top";
     798             :     }
     799             :     else
     800             :     {
     801           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
     802           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 2, 1);
     803           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
     804           0 :       mesh->prepare_for_use();
     805           0 :       other_mesh.prepare_for_use();
     806           0 :       mesh->stitch_meshes(other_mesh, 2, 2, TOLERANCE, true, /*verbose=*/false);
     807             : 
     808           0 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
     809           0 :       mesh->get_boundary_info().sideset_name(1) = "left";
     810           0 :       mesh->get_boundary_info().sideset_name(2) = "outer";
     811             :     }
     812           0 :     other_mesh.clear();
     813           0 :   }
     814         188 :   else if (_portion == "left_half")
     815             :   {
     816           0 :     ReplicatedMesh other_mesh(*mesh);
     817             : 
     818             :     // This is to rotate the mesh and to reset boundary IDs.
     819           0 :     MeshTools::Modification::rotate(other_mesh, 90, 0, 0);
     820           0 :     MeshTools::Modification::rotate(*mesh, 180, 0, 0);
     821           0 :     if (_has_outer_square)
     822             :     {
     823             :       // The other mesh is created by rotating the original mesh about 90 degrees.
     824           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
     825           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
     826           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
     827           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 4, 1);
     828           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
     829           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 6, 3);
     830           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 7, 4);
     831             :       // The original mesh is then rotated about 180 degrees.
     832           0 :       MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
     833           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 6);
     834           0 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 7);
     835           0 :       MeshTools::Modification::change_boundary_id(*mesh, 4, 2);
     836           0 :       MeshTools::Modification::change_boundary_id(*mesh, 5, 3);
     837           0 :       MeshTools::Modification::change_boundary_id(*mesh, 6, 4);
     838           0 :       MeshTools::Modification::change_boundary_id(*mesh, 7, 1);
     839           0 :       mesh->prepare_for_use();
     840           0 :       other_mesh.prepare_for_use();
     841           0 :       mesh->stitch_meshes(other_mesh, 4, 2, TOLERANCE, true, /*verbose=*/false);
     842           0 :       mesh->get_boundary_info().sideset_name(1) = "left";
     843           0 :       mesh->get_boundary_info().sideset_name(2) = "bottom";
     844           0 :       mesh->get_boundary_info().sideset_name(3) = "right";
     845           0 :       mesh->get_boundary_info().sideset_name(4) = "top";
     846             :     }
     847             :     else
     848             :     {
     849           0 :       MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
     850           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
     851           0 :       MeshTools::Modification::change_boundary_id(*mesh, 5, 2);
     852           0 :       mesh->prepare_for_use();
     853           0 :       other_mesh.prepare_for_use();
     854           0 :       mesh->stitch_meshes(other_mesh, 1, 1, TOLERANCE, true, /*verbose=*/false);
     855             : 
     856           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
     857           0 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
     858           0 :       mesh->get_boundary_info().sideset_name(1) = "right";
     859           0 :       mesh->get_boundary_info().sideset_name(2) = "outer";
     860             :     }
     861           0 :     other_mesh.clear();
     862           0 :   }
     863         188 :   else if (_portion == "bottom_half")
     864             :   {
     865           0 :     ReplicatedMesh other_mesh(*mesh);
     866             :     // This is to rotate the mesh and also to reset boundary IDs.
     867           0 :     MeshTools::Modification::rotate(other_mesh, 180, 0, 0);
     868           0 :     MeshTools::Modification::rotate(*mesh, 270, 0, 0);
     869           0 :     if (_has_outer_square)
     870             :     {
     871             :       // The other mesh is created by rotating the original mesh about 180 degrees.
     872           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
     873           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
     874           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
     875           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 4, 2);
     876           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 5, 3);
     877           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 6, 4);
     878           0 :       MeshTools::Modification::change_boundary_id(other_mesh, 7, 1);
     879             :       // The original mesh is rotated about 270 degrees.
     880           0 :       MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
     881           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 6);
     882           0 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 7);
     883           0 :       MeshTools::Modification::change_boundary_id(*mesh, 4, 3);
     884           0 :       MeshTools::Modification::change_boundary_id(*mesh, 5, 4);
     885           0 :       MeshTools::Modification::change_boundary_id(*mesh, 6, 1);
     886           0 :       MeshTools::Modification::change_boundary_id(*mesh, 7, 2);
     887           0 :       mesh->prepare_for_use();
     888           0 :       other_mesh.prepare_for_use();
     889           0 :       mesh->stitch_meshes(other_mesh, 1, 3, TOLERANCE, true, /*verbose=*/false);
     890           0 :       mesh->get_boundary_info().sideset_name(1) = "left";
     891           0 :       mesh->get_boundary_info().sideset_name(2) = "bottom";
     892           0 :       mesh->get_boundary_info().sideset_name(3) = "right";
     893           0 :       mesh->get_boundary_info().sideset_name(4) = "top";
     894             :     }
     895             :     else
     896             :     {
     897           0 :       MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
     898           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
     899           0 :       MeshTools::Modification::change_boundary_id(*mesh, 5, 2);
     900           0 :       mesh->prepare_for_use();
     901           0 :       other_mesh.prepare_for_use();
     902           0 :       mesh->stitch_meshes(other_mesh, 1, 1, TOLERANCE, true, /*verbose=*/false);
     903             : 
     904           0 :       MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
     905           0 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
     906           0 :       mesh->get_boundary_info().sideset_name(1) = "top";
     907           0 :       mesh->get_boundary_info().sideset_name(2) = "outer";
     908             :     }
     909           0 :     other_mesh.clear();
     910           0 :   }
     911         188 :   else if (_portion == "full")
     912             :   {
     913          98 :     ReplicatedMesh portion_two(*mesh);
     914             : 
     915             :     // This is to rotate the mesh and also to reset boundary IDs.
     916          98 :     MeshTools::Modification::rotate(portion_two, 90, 0, 0);
     917             : 
     918          98 :     if (_has_outer_square)
     919             :     {
     920             :       // Portion 2: 2nd quadrant
     921          66 :       MeshTools::Modification::change_boundary_id(portion_two, 1, 5);
     922          66 :       MeshTools::Modification::change_boundary_id(portion_two, 2, 6);
     923          66 :       MeshTools::Modification::change_boundary_id(portion_two, 3, 7);
     924          66 :       MeshTools::Modification::change_boundary_id(portion_two, 4, 1);
     925          66 :       MeshTools::Modification::change_boundary_id(portion_two, 5, 2);
     926          66 :       MeshTools::Modification::change_boundary_id(portion_two, 6, 3);
     927          66 :       MeshTools::Modification::change_boundary_id(portion_two, 7, 4);
     928          66 :       mesh->prepare_for_use();
     929          66 :       portion_two.prepare_for_use();
     930             :       // 'top_half'
     931          66 :       mesh->stitch_meshes(portion_two, 1, 3, TOLERANCE, true, /*verbose=*/false);
     932             : 
     933             :       // 'bottom_half'
     934          66 :       ReplicatedMesh portion_bottom(*mesh);
     935          66 :       MeshTools::Modification::rotate(portion_bottom, 180, 0, 0);
     936          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 1, 5);
     937          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 2, 6);
     938          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 3, 7);
     939          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 4, 2);
     940          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 5, 3);
     941          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 6, 4);
     942          66 :       MeshTools::Modification::change_boundary_id(portion_bottom, 7, 1);
     943          66 :       mesh->prepare_for_use();
     944          66 :       portion_bottom.prepare_for_use();
     945             :       // 'full'
     946          66 :       mesh->stitch_meshes(portion_bottom, 2, 4, TOLERANCE, true, /*verbose=*/false);
     947             : 
     948          66 :       mesh->get_boundary_info().sideset_name(1) = "left";
     949          66 :       mesh->get_boundary_info().sideset_name(2) = "bottom";
     950          66 :       mesh->get_boundary_info().sideset_name(3) = "right";
     951          66 :       mesh->get_boundary_info().sideset_name(4) = "top";
     952          66 :       portion_bottom.clear();
     953          66 :     }
     954             :     else
     955             :     {
     956          32 :       MeshTools::Modification::change_boundary_id(portion_two, 1, 5);
     957          32 :       MeshTools::Modification::change_boundary_id(portion_two, 2, 1);
     958          32 :       MeshTools::Modification::change_boundary_id(portion_two, 5, 2);
     959             :       // 'top half'
     960          32 :       mesh->prepare_for_use();
     961          32 :       portion_two.prepare_for_use();
     962          32 :       mesh->stitch_meshes(portion_two, 1, 1, TOLERANCE, true, /*verbose=*/false);
     963             :       // 'bottom half'
     964          32 :       ReplicatedMesh portion_bottom(*mesh);
     965          32 :       MeshTools::Modification::rotate(portion_bottom, 180, 0, 0);
     966             :       // 'full'
     967          32 :       mesh->prepare_for_use();
     968          32 :       portion_bottom.prepare_for_use();
     969          32 :       mesh->stitch_meshes(portion_bottom, 2, 2, TOLERANCE, true, /*verbose=*/false);
     970          32 :       MeshTools::Modification::change_boundary_id(*mesh, 3, 1);
     971          32 :       mesh->get_boundary_info().sideset_name(1) = "outer";
     972          32 :       portion_bottom.clear();
     973          32 :     }
     974          98 :     portion_two.clear();
     975          98 :   }
     976             : 
     977         436 :   if (_portion != "top_half" && _portion != "right_half" && _portion != "left_half" &&
     978         436 :       _portion != "bottom_half" && _portion != "full")
     979         120 :     mesh->prepare_for_use();
     980             : 
     981             :   // Laplace smoothing
     982         218 :   libMesh::LaplaceMeshSmoother lms(*mesh);
     983         218 :   lms.smooth(_smoothing_max_it);
     984             : 
     985         218 :   mesh->prepare_for_use();
     986         436 :   return dynamic_pointer_cast<MeshBase>(mesh);
     987         218 : }

Generated by: LCOV version 1.14