LCOV - code coverage report
Current view: top level - src/meshgenerators - CartesianMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 257 300 85.7 %
Date: 2026-05-29 20:35:17 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 "CartesianMeshGenerator.h"
      11             : #include "CastUniquePointer.h"
      12             : 
      13             : // libMesh includes
      14             : #include "libmesh/mesh_generation.h"
      15             : #include "libmesh/unstructured_mesh.h"
      16             : #include "libmesh/replicated_mesh.h"
      17             : #include "libmesh/point.h"
      18             : #include "libmesh/elem.h"
      19             : #include "libmesh/node.h"
      20             : 
      21             : registerMooseObject("MooseApp", CartesianMeshGenerator);
      22             : 
      23             : InputParameters
      24        9195 : CartesianMeshGenerator::validParams()
      25             : {
      26        9195 :   InputParameters params = MeshGenerator::validParams();
      27       36780 :   MooseEnum dims("1=1 2 3");
      28       36780 :   params.addRequiredParam<MooseEnum>("dim", dims, "The dimension of the mesh to be generated");
      29             : 
      30       36780 :   params.addRequiredParam<std::vector<Real>>("dx", "Intervals in the X direction");
      31       36780 :   params.addParam<std::vector<unsigned int>>(
      32             :       "ix", "Number of grids in all intervals in the X direction (default to all one)");
      33       36780 :   params.addParam<std::vector<Real>>(
      34             :       "max_sizes_in_x",
      35             :       "Maximum element size in the X direction. This can be specified once for all 'dx' intervals "
      36             :       "or specified for each interval. 'ix' is then determined using the ceiling of dx/size");
      37       36780 :   params.addParam<std::vector<Real>>(
      38             :       "dy", "Intervals in the Y direction (required when dim>1 otherwise ignored)");
      39       36780 :   params.addParam<std::vector<unsigned int>>(
      40             :       "iy", "Number of grids in all intervals in the Y direction (default to all one)");
      41       36780 :   params.addParam<std::vector<Real>>(
      42             :       "max_sizes_in_y",
      43             :       "Maximum element size in the Y direction. This can be specified once for all 'dy' intervals "
      44             :       "or specified for each interval. 'iy' is then determined using the ceiling of dy/size");
      45       36780 :   params.addParam<std::vector<Real>>(
      46             :       "dz", "Intervals in the Z direction (required when dim>2 otherwise ignored)");
      47       36780 :   params.addParam<std::vector<unsigned int>>(
      48             :       "iz", "Number of grids in all intervals in the Z direction (default to all one)");
      49       36780 :   params.addParam<std::vector<Real>>(
      50             :       "max_sizes_in_z",
      51             :       "Maximum element size in the Z direction. This can be specified once for all 'dz' intervals "
      52             :       "or specified for each interval. 'iz' is then determined using the ceiling of dz/size");
      53       36780 :   params.addParam<std::vector<unsigned int>>("subdomain_id", "Block IDs (default to all zero)");
      54        9195 :   params.addClassDescription("This CartesianMeshGenerator creates a non-uniform Cartesian mesh.");
      55       18390 :   return params;
      56        9195 : }
      57             : 
      58        3061 : CartesianMeshGenerator::CartesianMeshGenerator(const InputParameters & parameters)
      59             :   : MeshGenerator(parameters),
      60        3061 :     _dim(getParam<MooseEnum>("dim")),
      61       12244 :     _dx(getParam<std::vector<Real>>("dx"))
      62             : {
      63             :   // get all other parameters if provided and check their sizes
      64        9183 :   if (isParamValid("ix"))
      65             :   {
      66        4382 :     _ix = getParam<std::vector<unsigned int>>("ix");
      67        2191 :     if (_ix.size() != _dx.size())
      68           0 :       mooseError("ix must be the same size as dx");
      69        7392 :     for (unsigned int i = 0; i < _ix.size(); ++i)
      70        5201 :       if (_ix[i] == 0)
      71           0 :         mooseError("ix cannot be zero");
      72        6573 :     if (isParamValid("max_sizes_in_x"))
      73           0 :       paramError("max_sizes_in_x", "Cannot be provided if 'ix' is specified");
      74             :   }
      75        2610 :   else if (isParamValid("max_sizes_in_x"))
      76             :   {
      77           8 :     _ix.resize(_dx.size());
      78          16 :     auto max_sizes = getParam<std::vector<Real>>("max_sizes_in_x");
      79           8 :     if (max_sizes.size() == 1)
      80           0 :       max_sizes.resize(_dx.size(), max_sizes[0]);
      81           8 :     if (max_sizes.size() != _dx.size())
      82           0 :       paramError("max_sizes_in_x", "max_sizes_in_x must be size 1 or the same size as dx");
      83          32 :     for (const auto i : index_range(_dx))
      84          24 :       if (max_sizes[i] <= 0)
      85           0 :         paramError("max_sizes_in_x", "max_sizes_in_x must be strictly positive.");
      86          32 :     for (const auto i : index_range(_dx))
      87          24 :       _ix[i] = std::ceil(_dx[i] / max_sizes[i]);
      88           8 :   }
      89             :   else
      90         862 :     _ix = std::vector<unsigned int>(_dx.size(), 1);
      91             : 
      92        9604 :   for (unsigned int i = 0; i < _dx.size(); ++i)
      93        6543 :     if (_dx[i] <= 0)
      94           0 :       mooseError("dx must be greater than zero. dx: ", Moose::stringify(_dx));
      95             : 
      96        9183 :   if (isParamValid("dy"))
      97             :   {
      98        4050 :     _dy = getParam<std::vector<Real>>("dy");
      99        6204 :     for (unsigned int i = 0; i < _dy.size(); ++i)
     100        4179 :       if (_dy[i] <= 0)
     101           0 :         mooseError("dy must be greater than zero. dy: ", Moose::stringify(_dy));
     102             :   }
     103             : 
     104        9183 :   if (isParamValid("iy"))
     105             :   {
     106        3746 :     _iy = getParam<std::vector<unsigned int>>("iy");
     107        1873 :     if (_iy.size() != _dy.size())
     108           0 :       mooseError("iy must be the same size as dy");
     109        5576 :     for (unsigned int i = 0; i < _iy.size(); ++i)
     110        3703 :       if (_iy[i] == 0)
     111           0 :         mooseError("iy cannot be zero");
     112        5619 :     if (isParamValid("max_sizes_in_y"))
     113           0 :       paramError("max_sizes_in_y", "Cannot be provided if 'iy' is specified");
     114             :   }
     115        3564 :   else if (isParamValid("max_sizes_in_y"))
     116             :   {
     117           8 :     _iy.resize(_dy.size());
     118          16 :     auto max_sizes = getParam<std::vector<Real>>("max_sizes_in_y");
     119           8 :     if (max_sizes.size() == 1)
     120           0 :       max_sizes.resize(_dy.size(), max_sizes[0]);
     121           8 :     if (max_sizes.size() != _dy.size())
     122           0 :       paramError("max_sizes_in_y", "max_sizes_in_y must be size 1 or the same size as dy");
     123          24 :     for (const auto i : index_range(_dy))
     124          16 :       if (max_sizes[i] <= 0)
     125           0 :         paramError("max_sizes_in_y", "max_sizes_in_y must be strictly positive.");
     126          24 :     for (const auto i : index_range(_dy))
     127          16 :       _iy[i] = std::ceil(_dy[i] / max_sizes[i]);
     128           8 :   }
     129             :   else
     130        1180 :     _iy = std::vector<unsigned int>(_dy.size(), 1);
     131             : 
     132        9183 :   if (isParamValid("dz"))
     133             :   {
     134         936 :     _dz = getParam<std::vector<Real>>("dz");
     135        1902 :     for (unsigned int i = 0; i < _dz.size(); ++i)
     136        1434 :       if (_dz[i] <= 0)
     137           0 :         mooseError("dz must be greater than zero dz: ", Moose::stringify(_dz));
     138             :   }
     139             : 
     140        9183 :   if (isParamValid("iz"))
     141             :   {
     142         814 :     _iz = getParam<std::vector<unsigned int>>("iz");
     143         407 :     if (_iz.size() != _dz.size())
     144           0 :       mooseError("iz must be the same size as dz");
     145        1597 :     for (unsigned int i = 0; i < _iz.size(); ++i)
     146        1190 :       if (_iz[i] == 0)
     147           0 :         mooseError("iz cannot be zero");
     148        1221 :     if (isParamValid("max_sizes_in_z"))
     149           0 :       paramError("max_sizes_in_z", "Cannot be provided if 'iz' is specified");
     150             :   }
     151        7962 :   else if (isParamValid("max_sizes_in_z"))
     152             :   {
     153           8 :     _iz.resize(_dz.size());
     154          16 :     auto max_sizes = getParam<std::vector<Real>>("max_sizes_in_z");
     155           8 :     if (max_sizes.size() == 1)
     156           0 :       max_sizes.resize(_dz.size(), max_sizes[0]);
     157           8 :     if (max_sizes.size() != _dz.size())
     158           0 :       paramError("max_sizes_in_z", "max_sizes_in_z must be size 1 or the same size as dz");
     159          40 :     for (const auto i : index_range(_dz))
     160          32 :       if (max_sizes[i] <= 0)
     161           0 :         paramError("max_sizes_in_z", "max_sizes_in_z must be strictly positive.");
     162          40 :     for (const auto i : index_range(_dz))
     163          32 :       _iz[i] = std::ceil(_dz[i] / max_sizes[i]);
     164           8 :   }
     165             :   else
     166        2646 :     _iz = std::vector<unsigned int>(_dz.size(), 1);
     167             : 
     168        9183 :   if (isParamValid("subdomain_id"))
     169             :   {
     170        3476 :     _subdomain_id = getParam<std::vector<unsigned int>>("subdomain_id");
     171        5780 :     if (isParamValid("dz") && isParamValid("dy"))
     172             :     {
     173         283 :       if (_subdomain_id.size() != _dx.size() * _dy.size() * _dz.size())
     174           0 :         mooseError(
     175           0 :             "subdomain_id must be the size of the product of sizes of dx, dy and dz. Sizes are '" +
     176           0 :             std::to_string(_subdomain_id.size()) + "' and '" +
     177           0 :             std::to_string(_dx.size() * _dy.size() * _dz.size()) + "' respectively");
     178             :     }
     179        4365 :     else if (isParamValid("dy"))
     180             :     {
     181        1359 :       if (_subdomain_id.size() != _dx.size() * _dy.size())
     182           0 :         mooseError(
     183           0 :             "subdomain_id must be the size of the product of sizes of dx and dy. Sizes are '" +
     184           0 :             std::to_string(_subdomain_id.size()) + "' and '" +
     185           0 :             std::to_string(_dx.size() * _dy.size()) + "' respectively");
     186             :     }
     187             :     else
     188             :     {
     189          96 :       if (_subdomain_id.size() != _dx.size())
     190           0 :         mooseError("subdomain_id must be the size of the product of sizes of dx. Sizes are '" +
     191           0 :                    std::to_string(_subdomain_id.size()) + "' and '" + std::to_string(_dx.size()) +
     192             :                    "' respectively");
     193             :     }
     194             :   }
     195             :   else
     196             :   {
     197        3969 :     if (isParamValid("dz"))
     198         185 :       _subdomain_id = std::vector<unsigned int>(_dx.size() * _dy.size() * _dz.size(), 0);
     199        3414 :     else if (isParamValid("dy"))
     200         198 :       _subdomain_id = std::vector<unsigned int>(_dx.size() * _dy.size(), 0);
     201             :     else
     202         940 :       _subdomain_id = std::vector<unsigned int>(_dx.size(), 0);
     203             :   }
     204             : 
     205             :   // do dimension checks and expand block IDs for all sub-grids
     206        3061 :   switch (_dim)
     207             :   {
     208        1036 :     case 1:
     209             :     {
     210        1036 :       _nx = 0;
     211        2380 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     212        1344 :         _nx += _ix[i];
     213        1036 :       _ny = 1;
     214        1036 :       _nz = 1;
     215             : 
     216        1036 :       std::vector<unsigned int> new_id;
     217        2380 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     218        5803 :         for (unsigned int ii = 0; ii < _ix[i]; ++ii)
     219        4459 :           new_id.push_back(_subdomain_id[i]);
     220             : 
     221        1036 :       _subdomain_id = new_id;
     222             : 
     223        3108 :       if (isParamValid("dy"))
     224           0 :         mooseWarning("dy provided for 1D");
     225        3108 :       if (isParamValid("iy"))
     226           0 :         mooseWarning("iy provided for 1D");
     227        3108 :       if (isParamValid("dz"))
     228           0 :         mooseWarning("dz provided for 1D");
     229        3108 :       if (isParamValid("iz"))
     230           0 :         mooseWarning("iz provided for 1D");
     231        3108 :       if (isParamValid("max_sizes_in_y"))
     232           0 :         paramWarning("max_sizes_in_y", "Should not be provided for 1D");
     233        3108 :       if (isParamValid("max_sizes_in_z"))
     234           0 :         paramWarning("max_sizes_in_z", "Should not be provided for 1D");
     235        1036 :       break;
     236        1036 :     }
     237        1557 :     case 2:
     238             :     {
     239        1557 :       _nx = 0;
     240        5471 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     241        3914 :         _nx += _ix[i];
     242        1557 :       _ny = 0;
     243        4780 :       for (unsigned int i = 0; i < _dy.size(); ++i)
     244        3223 :         _ny += _iy[i];
     245        1557 :       _nz = 1;
     246             : 
     247        1557 :       std::vector<unsigned int> new_id;
     248        4780 :       for (unsigned int j = 0; j < _dy.size(); ++j)
     249       11773 :         for (unsigned int jj = 0; jj < _iy[j]; ++jj)
     250       32710 :           for (unsigned int i = 0; i < _dx.size(); ++i)
     251       92607 :             for (unsigned int ii = 0; ii < _ix[i]; ++ii)
     252       68447 :               new_id.push_back(_subdomain_id[j * _dx.size() + i]);
     253             : 
     254        1557 :       _subdomain_id = new_id;
     255             : 
     256        4671 :       if (!isParamValid("dy"))
     257           0 :         mooseError("dy is not provided for 2D");
     258        4671 :       if (isParamValid("dz"))
     259           0 :         mooseWarning("dz provided for 2D");
     260        4671 :       if (isParamValid("iz"))
     261           0 :         mooseWarning("iz provided for 2D");
     262        4671 :       if (isParamValid("max_sizes_in_z"))
     263           0 :         paramWarning("max_sizes_in_z", "Should not be provided for 2D");
     264        1557 :       break;
     265        1557 :     }
     266         468 :     case 3:
     267             :     {
     268         468 :       _nx = 0;
     269        1753 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     270        1285 :         _nx += _ix[i];
     271         468 :       _ny = 0;
     272        1424 :       for (unsigned int i = 0; i < _dy.size(); ++i)
     273         956 :         _ny += _iy[i];
     274         468 :       _nz = 0;
     275        1902 :       for (unsigned int i = 0; i < _dz.size(); ++i)
     276        1434 :         _nz += _iz[i];
     277             : 
     278         468 :       std::vector<unsigned int> new_id;
     279        1902 :       for (unsigned int k = 0; k < _dz.size(); ++k)
     280        3392 :         for (unsigned int kk = 0; kk < _iz[k]; ++kk)
     281        5958 :           for (unsigned int j = 0; j < _dy.size(); ++j)
     282       12870 :             for (unsigned int jj = 0; jj < _iy[j]; ++jj)
     283       34344 :               for (unsigned int i = 0; i < _dx.size(); ++i)
     284       59606 :                 for (unsigned int ii = 0; ii < _ix[i]; ++ii)
     285       34132 :                   new_id.push_back(_subdomain_id[k * _dx.size() * _dy.size() + j * _dx.size() + i]);
     286             : 
     287         468 :       _subdomain_id = new_id;
     288             : 
     289        1404 :       if (!isParamValid("dy"))
     290           0 :         mooseError("dy is not provided for 3D");
     291        1404 :       if (!isParamValid("dz"))
     292           0 :         mooseError("dz is not provided for 3D");
     293         468 :       break;
     294         468 :     }
     295             :   }
     296        3061 : }
     297             : 
     298             : std::unique_ptr<MeshBase>
     299        2884 : CartesianMeshGenerator::generate()
     300             : {
     301        2884 :   auto mesh = buildMeshBaseObject();
     302             : 
     303             :   // switching on MooseEnum to generate the reference mesh
     304             :   // Note: element type is fixed
     305        2884 :   switch (_dim)
     306             :   {
     307        1003 :     case 1:
     308        1003 :       MeshTools::Generation::build_line(static_cast<UnstructuredMesh &>(*mesh), _nx, 0, _nx, EDGE2);
     309        1003 :       break;
     310        1439 :     case 2:
     311        1439 :       MeshTools::Generation::build_square(
     312        1439 :           static_cast<UnstructuredMesh &>(*mesh), _nx, _ny, 0, _nx, 0, _ny, QUAD4);
     313        1439 :       break;
     314         442 :     case 3:
     315         442 :       MeshTools::Generation::build_cube(
     316         442 :           static_cast<UnstructuredMesh &>(*mesh), _nx, _ny, _nz, 0, _nx, 0, _ny, 0, _nz, HEX8);
     317         442 :       break;
     318             :   }
     319             : 
     320             :   // assign block IDs
     321        5768 :   MeshBase::element_iterator el = mesh->active_elements_begin();
     322        5768 :   MeshBase::element_iterator el_end = mesh->active_elements_end();
     323       99975 :   for (; el != el_end; ++el)
     324             :   {
     325       97091 :     const Point p = (*el)->vertex_average();
     326       97091 :     unsigned int ix = std::floor(p(0));
     327       97091 :     unsigned int iy = std::floor(p(1));
     328       97091 :     unsigned int iz = std::floor(p(2));
     329       97091 :     unsigned int i = iz * _nx * _ny + iy * _nx + ix;
     330       97091 :     (*el)->subdomain_id() = _subdomain_id[i];
     331             :   }
     332             : 
     333             :   // adjust node coordinates
     334        2884 :   switch (_dim)
     335             :   {
     336        1003 :     case 1:
     337             :     {
     338             :       Real base;
     339             : 
     340        1003 :       std::vector<Real> mapx;
     341             :       // Note: the starting coordinate is zero
     342        1003 :       base = 0;
     343        1003 :       mapx.push_back(base);
     344        2303 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     345             :       {
     346        5561 :         for (unsigned int j = 1; j <= _ix[i]; ++j)
     347        4261 :           mapx.push_back(base + _dx[i] / _ix[i] * j);
     348        1300 :         base += _dx[i];
     349             :       }
     350             : 
     351        1003 :       MeshBase::node_iterator node = mesh->active_nodes_begin();
     352        1003 :       MeshBase::node_iterator node_end = mesh->active_nodes_end();
     353        6063 :       for (; node != node_end; ++node)
     354             :       {
     355        5060 :         unsigned int i = (*(*node))(0) + 0.5;
     356        5060 :         (*(*node))(0) = mapx.at(i);
     357             :       }
     358        1003 :       break;
     359        1003 :     }
     360        1439 :     case 2:
     361             :     {
     362             :       Real base;
     363             : 
     364        1439 :       std::vector<Real> mapx;
     365        1439 :       base = 0;
     366        1439 :       mapx.push_back(base);
     367        5078 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     368             :       {
     369       11861 :         for (unsigned int j = 1; j <= _ix[i]; ++j)
     370        8222 :           mapx.push_back(base + _dx[i] / _ix[i] * j);
     371        3639 :         base += _dx[i];
     372             :       }
     373             : 
     374        1439 :       std::vector<Real> mapy;
     375        1439 :       base = 0;
     376        1439 :       mapy.push_back(base);
     377        4418 :       for (unsigned int i = 0; i < _dy.size(); ++i)
     378             :       {
     379       10864 :         for (unsigned int j = 1; j <= _iy[i]; ++j)
     380        7885 :           mapy.push_back(base + _dy[i] / _iy[i] * j);
     381        2979 :         base += _dy[i];
     382             :       }
     383             : 
     384        1439 :       MeshBase::node_iterator node = mesh->active_nodes_begin();
     385        1439 :       MeshBase::node_iterator node_end = mesh->active_nodes_end();
     386       80090 :       for (; node != node_end; ++node)
     387             :       {
     388       78651 :         unsigned int i = (*(*node))(0) + 0.5;
     389       78651 :         (*(*node))(0) = mapx.at(i);
     390       78651 :         unsigned int j = (*(*node))(1) + 0.5;
     391       78651 :         (*(*node))(1) = mapy.at(j);
     392             :       }
     393        1439 :       break;
     394        1439 :     }
     395         442 :     case 3:
     396             :     {
     397             :       Real base;
     398             : 
     399         442 :       std::vector<Real> mapx;
     400         442 :       base = 0;
     401         442 :       mapx.push_back(base);
     402        1667 :       for (unsigned int i = 0; i < _dx.size(); ++i)
     403             :       {
     404        2889 :         for (unsigned int j = 1; j <= _ix[i]; ++j)
     405        1664 :           mapx.push_back(base + _dx[i] / _ix[i] * j);
     406        1225 :         base += _dx[i];
     407             :       }
     408             : 
     409         442 :       std::vector<Real> mapy;
     410         442 :       base = 0;
     411         442 :       mapy.push_back(base);
     412        1355 :       for (unsigned int i = 0; i < _dy.size(); ++i)
     413             :       {
     414        2889 :         for (unsigned int j = 1; j <= _iy[i]; ++j)
     415        1976 :           mapy.push_back(base + _dy[i] / _iy[i] * j);
     416         913 :         base += _dy[i];
     417             :       }
     418             : 
     419         442 :       std::vector<Real> mapz;
     420         442 :       base = 0;
     421         442 :       mapz.push_back(base);
     422        1799 :       for (unsigned int i = 0; i < _dz.size(); ++i)
     423             :       {
     424        3210 :         for (unsigned int j = 1; j <= _iz[i]; ++j)
     425        1853 :           mapz.push_back(base + _dz[i] / _iz[i] * j);
     426        1357 :         base += _dz[i];
     427             :       }
     428             : 
     429         442 :       MeshBase::node_iterator node = mesh->active_nodes_begin();
     430         442 :       MeshBase::node_iterator node_end = mesh->active_nodes_end();
     431       60702 :       for (; node != node_end; ++node)
     432             :       {
     433       60260 :         unsigned int i = (*(*node))(0) + 0.5;
     434       60260 :         (*(*node))(0) = mapx.at(i);
     435       60260 :         unsigned int j = (*(*node))(1) + 0.5;
     436       60260 :         (*(*node))(1) = mapy.at(j);
     437       60260 :         unsigned int k = (*(*node))(2) + 0.5;
     438       60260 :         (*(*node))(2) = mapz.at(k);
     439             :       }
     440         442 :       break;
     441         442 :     }
     442             :   }
     443             : 
     444        2884 :   mesh->prepare_for_use();
     445        5768 :   return dynamic_pointer_cast<MeshBase>(mesh);
     446        2884 : }

Generated by: LCOV version 1.14