LCOV - code coverage report
Current view: top level - src/meshgenerators - SCMDetailedQuadInterWrapperMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose subchannel: #31405 (292dce) with base fef103 Lines: 225 227 99.1 %
Date: 2025-09-04 07:58:06 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 "SCMDetailedQuadInterWrapperMeshGenerator.h"
      11             : #include <array>
      12             : #include <cmath>
      13             : #include "libmesh/cell_prism6.h"
      14             : #include "libmesh/unstructured_mesh.h"
      15             : 
      16             : registerMooseObject("SubChannelApp", SCMDetailedQuadInterWrapperMeshGenerator);
      17             : registerMooseObjectRenamed("SubChannelApp",
      18             :                            DetailedQuadInterWrapperMeshGenerator,
      19             :                            "06/30/2025 24:00",
      20             :                            SCMDetailedQuadInterWrapperMeshGenerator);
      21             : 
      22             : InputParameters
      23          48 : SCMDetailedQuadInterWrapperMeshGenerator::validParams()
      24             : {
      25          48 :   InputParameters params = MeshGenerator::validParams();
      26          48 :   params.addClassDescription(
      27             :       "Creates a detailed mesh of the inter-wrapper cells around square lattice subassemblies");
      28          96 :   params.addRequiredParam<Real>("assembly_pitch", "Assembly Pitch [m]");
      29          96 :   params.addRequiredParam<Real>("assembly_side_x",
      30             :                                 "Outer side lengths of assembly in x [m] - including duct");
      31          96 :   params.addRequiredParam<Real>("assembly_side_y",
      32             :                                 "Outer side lengths of assembly in y [m] - including duct");
      33          96 :   params.addParam<Real>("unheated_length_entry", 0.0, "Unheated length at entry [m]");
      34          96 :   params.addRequiredParam<Real>("heated_length", "Heated length [m]");
      35          96 :   params.addParam<Real>("unheated_length_exit", 0.0, "Unheated length at exit [m]");
      36          96 :   params.addRequiredParam<unsigned int>("n_cells", "The number of cells in the axial direction");
      37          96 :   params.addRequiredParam<unsigned int>("nx", "Number of channels in the x direction [-]");
      38          96 :   params.addRequiredParam<unsigned int>("ny", "Number of channels in the y direction [-]");
      39          96 :   params.addRequiredParam<Real>("side_bypass", "Half of assembly_pitch between assemblies [m]");
      40          96 :   params.addParam<unsigned int>("block_id", 0, "Block ID used for the mesh subdomain.");
      41          48 :   return params;
      42           0 : }
      43             : 
      44          24 : SCMDetailedQuadInterWrapperMeshGenerator::SCMDetailedQuadInterWrapperMeshGenerator(
      45          24 :     const InputParameters & parameters)
      46             :   : MeshGenerator(parameters),
      47          24 :     _unheated_length_entry(getParam<Real>("unheated_length_entry")),
      48          48 :     _heated_length(getParam<Real>("heated_length")),
      49          48 :     _unheated_length_exit(getParam<Real>("unheated_length_exit")),
      50          48 :     _assembly_pitch(getParam<Real>("assembly_pitch")),
      51          48 :     _assembly_side_x(getParam<Real>("assembly_side_x")),
      52          48 :     _assembly_side_y(getParam<Real>("assembly_side_y")),
      53          48 :     _n_cells(getParam<unsigned int>("n_cells")),
      54          48 :     _nx(getParam<unsigned int>("nx") + 1),
      55          48 :     _ny(getParam<unsigned int>("ny") + 1),
      56          24 :     _n_channels((_nx + 1) * (_ny + 1)),
      57          48 :     _side_bypass_length(getParam<Real>("side_bypass")),
      58          72 :     _block_id(getParam<unsigned int>("block_id"))
      59             : {
      60          24 :   Real L = _unheated_length_entry + _heated_length + _unheated_length_exit;
      61          24 :   Real dz = L / _n_cells;
      62         648 :   for (unsigned int i = 0; i < _n_cells + 1; i++)
      63         624 :     _z_grid.push_back(dz * i);
      64             : 
      65          24 :   _subch_type.resize(_n_channels);
      66         240 :   for (unsigned int iy = 0; iy < _ny; iy++)
      67             :   {
      68        2880 :     for (unsigned int ix = 0; ix < _nx; ix++)
      69             :     {
      70        2664 :       unsigned int i_ch = _nx * iy + ix;
      71        2640 :       bool is_corner = (ix == 0 && iy == 0) || (ix == _nx - 1 && iy == 0) ||
      72        5280 :                        (ix == 0 && iy == _ny - 1) || (ix == _nx - 1 && iy == _ny - 1);
      73        2664 :       bool is_edge = (ix == 0 || iy == 0 || ix == _nx - 1 || iy == _ny - 1);
      74             : 
      75        2664 :       if (is_corner)
      76          96 :         _subch_type[i_ch] = EChannelType::CORNER;
      77        2568 :       else if (is_edge)
      78         672 :         _subch_type[i_ch] = EChannelType::EDGE;
      79             :       else
      80        1896 :         _subch_type[i_ch] = EChannelType::CENTER;
      81             :     }
      82             :   }
      83          24 : }
      84             : 
      85             : std::unique_ptr<MeshBase>
      86          24 : SCMDetailedQuadInterWrapperMeshGenerator::generate()
      87             : {
      88          24 :   auto mesh_base = buildMeshBaseObject();
      89             :   BoundaryInfo & boundary_info = mesh_base->get_boundary_info();
      90          24 :   mesh_base->set_spatial_dimension(3);
      91             :   // Define the resolution (the number of points used to represent a circle).
      92             :   // This must be divisible by 4.
      93             :   const unsigned int theta_res = 16; // TODO: parameterize
      94             :   // Compute the number of points needed to represent one quarter of a circle.
      95             :   const unsigned int points_per_quad = theta_res / 4 + 1;
      96             : 
      97             :   // Compute the points needed to represent one axial cross-flow of a subchannel.
      98             :   // For the center subchannel (sc) there is one center point plus the points from 4 intersecting
      99             :   // circles.
     100             :   const unsigned int points_per_center = points_per_quad * 4 + 1;
     101             :   // For the corner sc there is one center point plus the points from 1 intersecting circle plus 3
     102             :   // corners
     103             :   const unsigned int points_per_corner = points_per_quad * 1 + 1 + 3;
     104             :   // For the side sc there is one center point plus the points from 2 intersecting circles plus 2
     105             :   // corners
     106             :   const unsigned int points_per_side = points_per_quad * 2 + 1 + 2;
     107             : 
     108             :   // Compute the number of elements (Prism6) which combined base creates the sub-channel
     109             :   // cross-section
     110             :   const unsigned int elems_per_center = theta_res + 4;
     111             :   const unsigned int elems_per_corner = theta_res / 4 + 4;
     112             :   const unsigned int elems_per_side = theta_res / 2 + 4;
     113             : 
     114             :   // specify number and type of sub-channel
     115             :   unsigned int n_center, n_side, n_corner;
     116             : 
     117             :   n_corner = 4;
     118          24 :   n_side = 2 * (_ny - 2) + 2 * (_nx - 2);
     119          24 :   n_center = _n_channels - n_side - n_corner;
     120             : 
     121             :   // Compute the total number of points and elements.
     122          24 :   const unsigned int points_per_level =
     123          24 :       n_corner * points_per_corner + n_side * points_per_side + n_center * points_per_center;
     124          24 :   const unsigned int elems_per_level =
     125          24 :       n_corner * elems_per_corner + n_side * elems_per_side + n_center * elems_per_center;
     126          24 :   const unsigned int n_points = points_per_level * (_n_cells + 1);
     127          24 :   const unsigned int n_elems = elems_per_level * _n_cells;
     128          24 :   mesh_base->reserve_nodes(n_points);
     129          24 :   mesh_base->reserve_elem(n_elems);
     130             :   // Build an array of points arranged in a square on the xy-plane. (last and first node overlap)
     131             :   // Mapping points in a circle to a square
     132             :   // See ttp://arxiv.org/abs/1509.06344 for proof
     133             :   const Real radius = 1.0;
     134             :   std::array<Point, theta_res + 1> circle_points;
     135             :   {
     136             :     Real theta = 0;
     137             :     Real u, v;
     138         432 :     for (unsigned int i = 0; i < theta_res + 1; i++)
     139             :     {
     140         408 :       u = radius * std::cos(theta);
     141         408 :       v = radius * std::sin(theta);
     142         408 :       Real val_check_u = std::abs(u) - std::sqrt(2.0) / 2.0;
     143         408 :       Real val_check_v = std::abs(v) - std::sqrt(2.0) / 2.0;
     144         408 :       if (val_check_u < 1e-5 && val_check_v < 1e-5)
     145             :       {
     146          96 :         circle_points[i](0) = u * 2.0 / std::sqrt(2);
     147          96 :         circle_points[i](1) = v * 2.0 / std::sqrt(2);
     148             :       }
     149             :       else
     150             :       {
     151         312 :         circle_points[i](0) =
     152         312 :             0.5 * std::sqrt(2. + std::pow(u, 2) - std::pow(v, 2) + 2. * u * std::sqrt(2)) -
     153         312 :             0.5 * std::sqrt(2. + std::pow(u, 2) - std::pow(v, 2) - 2. * u * std::sqrt(2));
     154         312 :         circle_points[i](1) =
     155         312 :             0.5 * std::sqrt(2. - std::pow(u, 2) + std::pow(v, 2) + 2. * v * std::sqrt(2)) -
     156         312 :             0.5 * std::sqrt(2. - std::pow(u, 2) + std::pow(v, 2) - 2. * v * std::sqrt(2));
     157             :       }
     158         408 :       circle_points[i](0) *= _assembly_side_x / 2.0;
     159         408 :       circle_points[i](1) *= _assembly_side_y / 2.0;
     160         408 :       theta += 2 * M_PI / theta_res;
     161             :     }
     162             :   }
     163             :   // Define "quadrant center" reference points.  These will be the centers of
     164             :   // the 4 circles that represent the fuel pins.  These centers are
     165             :   // offset a little bit so that in the final mesh, there is a tiny assembly_pitch between
     166             :   // neighboring subchannel cells.  That allows us to easily map a solution to
     167             :   // this detailed mesh with a nearest-neighbor search.
     168             :   const Real shrink_factor = 0.99999;
     169             :   std::array<Point, 4> quadrant_centers;
     170          24 :   quadrant_centers[0] =
     171          24 :       Point(_assembly_pitch * 0.5 * shrink_factor, _assembly_pitch * 0.5 * shrink_factor, 0);
     172          24 :   quadrant_centers[1] =
     173             :       Point(-_assembly_pitch * 0.5 * shrink_factor, _assembly_pitch * 0.5 * shrink_factor, 0);
     174          24 :   quadrant_centers[2] =
     175             :       Point(-_assembly_pitch * 0.5 * shrink_factor, -_assembly_pitch * 0.5 * shrink_factor, 0);
     176          24 :   quadrant_centers[3] =
     177             :       Point(_assembly_pitch * 0.5 * shrink_factor, -_assembly_pitch * 0.5 * shrink_factor, 0);
     178             : 
     179             :   const unsigned int m = theta_res / 4;
     180             :   // Build an array of points that represent a cross section of a center subchannel
     181             :   // cell.  The points are ordered in this fashion:
     182             :   //     4   3
     183             :   // 6 5       2 1
     184             :   //       0
     185             :   // 7 8       * *
     186             :   //     9   *
     187             :   std::array<Point, points_per_center> center_points;
     188             :   {
     189             :     unsigned int start;
     190         120 :     for (unsigned int i = 0; i < 4; i++)
     191             :     {
     192          96 :       if (i == 0)
     193             :         start = 3 * m;
     194          72 :       if (i == 1)
     195             :         start = 4 * m;
     196          72 :       if (i == 2)
     197             :         start = 1 * m;
     198          72 :       if (i == 3)
     199             :         start = 2 * m;
     200         576 :       for (unsigned int ii = 0; ii < points_per_quad; ii++)
     201             :       {
     202         480 :         auto c_pt = circle_points[start - ii];
     203         480 :         center_points[i * points_per_quad + ii + 1] = quadrant_centers[i] + c_pt;
     204             :       }
     205             :     }
     206             :   }
     207             : 
     208             :   // Build an array of points that represent a cross section of a top left corner subchannel
     209             :   // cell. The points are ordered in this fashion:
     210             :   // 5            4
     211             :   //
     212             :   //       0
     213             :   //           2  3
     214             :   // 6       1
     215             :   std::array<Point, points_per_corner> tl_corner_points;
     216             :   {
     217         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     218             :     {
     219         120 :       auto c_pt = circle_points[2 * m - ii];
     220         120 :       tl_corner_points[ii + 1] = quadrant_centers[3] + c_pt;
     221             :     }
     222          24 :     tl_corner_points[points_per_quad + 1] =
     223          24 :         Point(_assembly_pitch * 0.5 * shrink_factor, _side_bypass_length, 0);
     224          24 :     tl_corner_points[points_per_quad + 2] = Point(-_side_bypass_length, +_side_bypass_length, 0);
     225          24 :     tl_corner_points[points_per_quad + 3] =
     226             :         Point(-_side_bypass_length, -_assembly_pitch * 0.5 * shrink_factor, 0);
     227             :   }
     228             : 
     229             :   // Build an array of points that represent a cross section of a top right corner subchannel
     230             :   // cell.  The points are ordered in this fashion:
     231             :   // 6            5
     232             :   //
     233             :   //       0
     234             :   // 1 2
     235             :   //    3         4
     236             :   std::array<Point, points_per_corner> tr_corner_points;
     237             :   {
     238         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     239             :     {
     240         120 :       auto c_pt = circle_points[m - ii];
     241         120 :       tr_corner_points[ii + 1] = quadrant_centers[2] + c_pt;
     242             :     }
     243          24 :     tr_corner_points[points_per_quad + 1] =
     244             :         Point(_side_bypass_length, -_assembly_pitch * 0.5 * shrink_factor, 0);
     245          24 :     tr_corner_points[points_per_quad + 2] = Point(_side_bypass_length, _side_bypass_length, 0);
     246          24 :     tr_corner_points[points_per_quad + 3] =
     247             :         Point(-_assembly_pitch * 0.5 * shrink_factor, _side_bypass_length, 0);
     248             :   }
     249             : 
     250             :   // Build an array of points that represent a cross section of a bottom left corner subchannel
     251             :   // cell.  The points are ordered in this fashion:
     252             :   // 4       3
     253             :   //           2  1
     254             :   //       0
     255             :   //
     256             :   // 5            6
     257             :   std::array<Point, points_per_corner> bl_corner_points;
     258             :   {
     259         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     260             :     {
     261         120 :       auto c_pt = circle_points[3 * m - ii];
     262         120 :       bl_corner_points[ii + 1] = quadrant_centers[0] + c_pt;
     263             :     }
     264          24 :     bl_corner_points[points_per_quad + 1] =
     265             :         Point(-_side_bypass_length, _assembly_pitch * 0.5 * shrink_factor, 0);
     266          24 :     bl_corner_points[points_per_quad + 2] = Point(-_side_bypass_length, -_side_bypass_length, 0);
     267          24 :     bl_corner_points[points_per_quad + 3] =
     268             :         Point(_assembly_pitch * 0.5 * shrink_factor, -_side_bypass_length, 0);
     269             :   }
     270             : 
     271             :   // Build an array of points that represent a cross section of a bottom right corner subchannel
     272             :   // cell.  The points are ordered in this fashion:
     273             :   //    1        6
     274             :   // 3 2
     275             :   //       0
     276             :   //
     277             :   // 4           5
     278             :   std::array<Point, points_per_corner> br_corner_points;
     279             :   {
     280         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     281             :     {
     282         120 :       auto c_pt = circle_points[4 * m - ii];
     283         120 :       br_corner_points[ii + 1] = quadrant_centers[1] + c_pt;
     284             :     }
     285          24 :     br_corner_points[points_per_quad + 1] =
     286             :         Point(-_assembly_pitch * 0.5 * shrink_factor, -_side_bypass_length, 0);
     287          24 :     br_corner_points[points_per_quad + 2] = Point(_side_bypass_length, -_side_bypass_length, 0);
     288          24 :     br_corner_points[points_per_quad + 3] =
     289             :         Point(_side_bypass_length, _assembly_pitch * 0.5 * shrink_factor, 0);
     290             :   }
     291             : 
     292             :   // Build an array of points that represent a cross section of a top side subchannel
     293             :   // cell.  The points are ordered in this fashion:
     294             :   // 8            7
     295             :   //
     296             :   //       0
     297             :   // 1 2        5 6
     298             :   //    3     4
     299             :   std::array<Point, points_per_side> top_points;
     300             :   {
     301         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     302             :     {
     303         120 :       auto c_pt = circle_points[m - ii];
     304         120 :       top_points[ii + 1] = quadrant_centers[2] + c_pt;
     305             :     }
     306         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     307             :     {
     308         120 :       auto c_pt = circle_points[2 * m - ii];
     309         120 :       top_points[points_per_quad + ii + 1] = quadrant_centers[3] + c_pt;
     310             :     }
     311          24 :     top_points[2 * points_per_quad + 1] =
     312             :         Point(_assembly_pitch * 0.5 * shrink_factor, _side_bypass_length, 0);
     313          24 :     top_points[2 * points_per_quad + 2] =
     314             :         Point(-_assembly_pitch * 0.5 * shrink_factor, _side_bypass_length, 0);
     315             :   }
     316             : 
     317             :   // Build an array of points that represent a cross section of a left side subchannel
     318             :   // cell.  The points are ordered in this fashion:
     319             :   // 7        6
     320             :   //            5 4
     321             :   //      0
     322             :   //            2 3
     323             :   // 8        1
     324             :   std::array<Point, points_per_side> left_points;
     325             :   {
     326         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     327             :     {
     328         120 :       auto c_pt = circle_points[2 * m - ii];
     329         120 :       left_points[ii + 1] = quadrant_centers[3] + c_pt;
     330             :     }
     331         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     332             :     {
     333         120 :       auto c_pt = circle_points[3 * m - ii];
     334         120 :       left_points[points_per_quad + ii + 1] = quadrant_centers[0] + c_pt;
     335             :     }
     336          24 :     left_points[2 * points_per_quad + 1] =
     337             :         Point(-_side_bypass_length, _assembly_pitch * 0.5 * shrink_factor, 0);
     338          24 :     left_points[2 * points_per_quad + 2] =
     339             :         Point(-_side_bypass_length, -_assembly_pitch * 0.5 * shrink_factor, 0);
     340             :   }
     341             : 
     342             :   // Build an array of points that represent a cross section of a bottom side subchannel
     343             :   // cell.  The points are ordered in this fashion:
     344             :   //    4    3
     345             :   // 6 5       2 1
     346             :   //       0
     347             :   //
     348             :   // 7           8
     349             :   std::array<Point, points_per_side> bottom_points;
     350             :   {
     351         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     352             :     {
     353         120 :       auto c_pt = circle_points[3 * m - ii];
     354         120 :       bottom_points[ii + 1] = quadrant_centers[0] + c_pt;
     355             :     }
     356         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     357             :     {
     358         120 :       auto c_pt = circle_points[4 * m - ii];
     359         120 :       bottom_points[points_per_quad + ii + 1] = quadrant_centers[1] + c_pt;
     360             :     }
     361          24 :     bottom_points[2 * points_per_quad + 1] =
     362             :         Point(-_assembly_pitch * 0.5 * shrink_factor, -_side_bypass_length, 0);
     363          24 :     bottom_points[2 * points_per_quad + 2] =
     364             :         Point(_assembly_pitch * 0.5 * shrink_factor, -_side_bypass_length, 0);
     365             :   }
     366             : 
     367             :   // Build an array of points that represent a cross section of a right side subchannel
     368             :   // cell.  The points are ordered in this fashion:
     369             :   //    1        8
     370             :   // 3 2
     371             :   //       0
     372             :   // 4 5
     373             :   //   6         7
     374             :   std::array<Point, points_per_side> right_points;
     375             :   {
     376         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     377             :     {
     378         120 :       auto c_pt = circle_points[4 * m - ii];
     379         120 :       right_points[ii + 1] = quadrant_centers[1] + c_pt;
     380             :     }
     381         144 :     for (unsigned int ii = 0; ii < points_per_quad; ii++)
     382             :     {
     383         120 :       auto c_pt = circle_points[m - ii];
     384         120 :       right_points[points_per_quad + ii + 1] = quadrant_centers[2] + c_pt;
     385             :     }
     386          24 :     right_points[2 * points_per_quad + 1] =
     387             :         Point(_side_bypass_length, -_assembly_pitch * 0.5 * shrink_factor, 0);
     388          24 :     right_points[2 * points_per_quad + 2] =
     389             :         Point(_side_bypass_length, _assembly_pitch * 0.5 * shrink_factor, 0);
     390             :   }
     391             : 
     392             :   // Add the points to the mesh.
     393             : 
     394             :   unsigned int node_id = 0;
     395          24 :   Real offset_x = (_nx - 1) * _assembly_pitch / 2.0;
     396          24 :   Real offset_y = (_ny - 1) * _assembly_pitch / 2.0;
     397         240 :   for (unsigned int iy = 0; iy < _ny; iy++)
     398             :   {
     399         216 :     Point y0 = {0, _assembly_pitch * iy - offset_y, 0};
     400        2880 :     for (unsigned int ix = 0; ix < _nx; ix++)
     401             :     {
     402        2664 :       Point x0 = {_assembly_pitch * ix - offset_x, 0, 0};
     403        2664 :       if (ix == 0 && iy == 0) // Bottom Left corner
     404             :       {
     405         648 :         for (auto z : _z_grid)
     406             :         {
     407             :           Point z0{0, 0, z};
     408        6240 :           for (unsigned int i = 0; i < points_per_corner; i++)
     409        5616 :             mesh_base->add_point(bl_corner_points[i] + x0 + y0 + z0, node_id++);
     410             :         }
     411             :       }
     412        2640 :       else if (ix == _nx - 1 && iy == 0) // Bottom right corner
     413             :       {
     414         648 :         for (auto z : _z_grid)
     415             :         {
     416             :           Point z0{0, 0, z};
     417        6240 :           for (unsigned int i = 0; i < points_per_corner; i++)
     418        5616 :             mesh_base->add_point(br_corner_points[i] + x0 + y0 + z0, node_id++);
     419             :         }
     420             :       }
     421        2616 :       else if (ix == 0 && iy == _ny - 1) // top Left corner
     422             :       {
     423         648 :         for (auto z : _z_grid)
     424             :         {
     425             :           Point z0{0, 0, z};
     426        6240 :           for (unsigned int i = 0; i < points_per_corner; i++)
     427        5616 :             mesh_base->add_point(tl_corner_points[i] + x0 + y0 + z0, node_id++);
     428             :         }
     429             :       }
     430        2592 :       else if (ix == _nx - 1 && iy == _ny - 1) // top right corner
     431             :       {
     432         648 :         for (auto z : _z_grid)
     433             :         {
     434             :           Point z0{0, 0, z};
     435        6240 :           for (unsigned int i = 0; i < points_per_corner; i++)
     436        5616 :             mesh_base->add_point(tr_corner_points[i] + x0 + y0 + z0, node_id++);
     437             :         }
     438             :       }
     439        2568 :       else if (ix == 0 && (iy != _ny - 1 || iy != 0)) // left side
     440             :       {
     441        7056 :         for (auto z : _z_grid)
     442             :         {
     443             :           Point z0{0, 0, z};
     444       96432 :           for (unsigned int i = 0; i < points_per_side; i++)
     445       89544 :             mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
     446             :         }
     447             :       }
     448        2400 :       else if (ix == _nx - 1 && (iy != _ny - 1 || iy != 0)) // right side
     449             :       {
     450        7056 :         for (auto z : _z_grid)
     451             :         {
     452             :           Point z0{0, 0, z};
     453       96432 :           for (unsigned int i = 0; i < points_per_side; i++)
     454       89544 :             mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
     455             :         }
     456             :       }
     457        2232 :       else if (iy == 0 && (ix != _nx - 1 || ix != 0)) // bottom side
     458             :       {
     459        7056 :         for (auto z : _z_grid)
     460             :         {
     461             :           Point z0{0, 0, z};
     462       96432 :           for (unsigned int i = 0; i < points_per_side; i++)
     463       89544 :             mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
     464             :         }
     465             :       }
     466        2064 :       else if (iy == _ny - 1 && (ix != _nx - 1 || ix != 0)) // top side
     467             :       {
     468        7056 :         for (auto z : _z_grid)
     469             :         {
     470             :           Point z0{0, 0, z};
     471       96432 :           for (unsigned int i = 0; i < points_per_side; i++)
     472       89544 :             mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
     473             :         }
     474             :       }
     475             :       else // center
     476             :       {
     477       93312 :         for (auto z : _z_grid)
     478             :         {
     479             :           Point z0{0, 0, z};
     480     2011152 :           for (unsigned int i = 0; i < points_per_center; i++)
     481     1919736 :             mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
     482             :         }
     483             :       }
     484             :     }
     485             :   }
     486             : 
     487             :   // Add elements to the mesh.  The elements are 6-node prisms.  The
     488             :   // bases of these prisms form a triangulated representation of an cross-section
     489             :   // of a center subchannel.
     490             :   unsigned int elem_id = 0;
     491             :   unsigned int number_of_corner = 0;
     492             :   unsigned int number_of_side = 0;
     493             :   unsigned int number_of_center = 0;
     494             :   unsigned int elems_per_channel = 0;
     495             :   unsigned int points_per_channel = 0;
     496         240 :   for (unsigned int iy = 0; iy < _ny; iy++)
     497             :   {
     498        2880 :     for (unsigned int ix = 0; ix < _nx; ix++)
     499             :     {
     500        2664 :       unsigned int i_ch = _nx * iy + ix;
     501             :       auto subch_type = getSubchannelType(i_ch);
     502        2664 :       if (subch_type == EChannelType::CORNER)
     503             :       {
     504          96 :         number_of_corner++;
     505             :         elems_per_channel = elems_per_corner;
     506             :         points_per_channel = points_per_corner;
     507             :       }
     508        2568 :       else if (subch_type == EChannelType::EDGE)
     509             :       {
     510         672 :         number_of_side++;
     511             :         elems_per_channel = elems_per_side;
     512             :         points_per_channel = points_per_side;
     513             :       }
     514             :       else
     515             :       {
     516        1896 :         number_of_center++;
     517             :         elems_per_channel = elems_per_center;
     518             :         points_per_channel = points_per_center;
     519             :       }
     520      121464 :       for (unsigned int iz = 0; iz < _n_cells; iz++)
     521             :       {
     522      118800 :         unsigned int elapsed_points = number_of_corner * points_per_corner * (_n_cells + 1) +
     523      118800 :                                       number_of_side * points_per_side * (_n_cells + 1) +
     524             :                                       number_of_center * points_per_center * (_n_cells + 1) -
     525      118800 :                                       points_per_channel * (_n_cells + 1);
     526             :         // index of the central node at base of cell
     527      118800 :         unsigned int indx1 = iz * points_per_channel + elapsed_points;
     528             :         // index of the central node at top of cell
     529      118800 :         unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
     530             : 
     531     2250960 :         for (unsigned int i = 0; i < elems_per_channel; i++)
     532             :         {
     533     2132160 :           Elem * elem = new Prism6;
     534     2132160 :           elem->subdomain_id() = _block_id;
     535     2132160 :           elem->set_id(elem_id++);
     536     2132160 :           elem = mesh_base->add_elem(elem);
     537             : 
     538     2132160 :           elem->set_node(0, mesh_base->node_ptr(indx1));
     539     2132160 :           elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
     540     2132160 :           if (i != elems_per_channel - 1)
     541     2013360 :             elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
     542             :           else
     543      118800 :             elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
     544             : 
     545     2132160 :           elem->set_node(3, mesh_base->node_ptr(indx2));
     546     2132160 :           elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
     547     2132160 :           if (i != elems_per_channel - 1)
     548     2013360 :             elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
     549             :           else
     550      118800 :             elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
     551             : 
     552     2132160 :           if (iz == 0)
     553       46752 :             boundary_info.add_side(elem, 0, 0);
     554     2132160 :           if (iz == _n_cells - 1)
     555       46752 :             boundary_info.add_side(elem, 4, 1);
     556             :         }
     557             :       }
     558             :     }
     559             :   }
     560          24 :   boundary_info.sideset_name(0) = "inlet";
     561          24 :   boundary_info.sideset_name(1) = "outlet";
     562          24 :   mesh_base->subdomain_name(_block_id) = name();
     563          24 :   mesh_base->prepare_for_use();
     564             : 
     565          24 :   return mesh_base;
     566           0 : }

Generated by: LCOV version 1.14