LCOV - code coverage report
Current view: top level - src/meshgenerators - MeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fa5e60 Lines: 228 241 94.6 %
Date: 2026-06-24 08:03:36 Functions: 38 40 95.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 "MeshGenerator.h"
      11             : #include "MooseMesh.h"
      12             : #include "MooseApp.h"
      13             : 
      14             : #include "Exodus.h"
      15             : #include "Nemesis.h"
      16             : 
      17             : #include "libmesh/exodusII_io.h"
      18             : #include "libmesh/nemesis_io.h"
      19             : 
      20             : const std::string MeshGenerator::data_only_param = "_data_only";
      21             : 
      22             : InputParameters
      23      478601 : MeshGenerator::validParams()
      24             : {
      25      478601 :   InputParameters params = MooseObject::validParams();
      26             : 
      27     1435803 :   params.addParam<bool>("show_info",
      28      957202 :                         false,
      29             :                         "Whether or not to show mesh info after generating the mesh "
      30             :                         "(bounding box, element types, sidesets, nodesets, subdomains, etc)");
      31     1435803 :   params.addParam<std::string>(
      32             :       "save_with_name",
      33      957202 :       std::string(),
      34             :       "Keep the mesh from this mesh generator in memory with the name specified");
      35             : 
      36     1435803 :   params.addParam<bool>(
      37      957202 :       "output", false, "Whether or not to output the mesh file after generating the mesh");
      38     1435803 :   params.addParam<bool>("nemesis",
      39      957202 :                         false,
      40             :                         "Whether or not to output the mesh file in the nemesis"
      41             :                         "format (only if output = true)");
      42             : 
      43     1914404 :   params.addParamNamesToGroup("show_info output nemesis", "Debugging");
      44     1914404 :   params.addParamNamesToGroup("save_with_name", "Advanced");
      45      478601 :   params.registerBase("MeshGenerator");
      46             : 
      47      957202 :   params.addPrivateParam<bool>("_has_generate_data", false);
      48      957202 :   params.addPrivateParam<bool>("_has_generate_csg", false);
      49      957202 :   params.addPrivateParam<MooseMesh *>("_moose_mesh", nullptr);
      50      478601 :   params.addPrivateParam<bool>(data_only_param, false);
      51             :   // Controls are not created early enough
      52      478601 :   params.suppressParameter<std::vector<std::string>>("control_tags");
      53             : 
      54      478601 :   return params;
      55           0 : }
      56             : 
      57       57081 : MeshGenerator::MeshGenerator(const InputParameters & parameters)
      58             :   : MooseObject(parameters),
      59             :     MeshMetaDataInterface(this),
      60      114162 :     _mesh(getParam<MooseMesh *>("_moose_mesh") ? getParam<MooseMesh *>("_moose_mesh")
      61       57081 :                                                : _app.actionWarehouse().mesh().get()),
      62      114162 :     _save_with_name(getParam<std::string>("save_with_name")),
      63      171243 :     _data_only(getParam<bool>(data_only_param))
      64             : {
      65       57081 :   const auto & system = _app.getMeshGeneratorSystem();
      66       57081 :   if (isDataOnly())
      67             :   {
      68             :     // Skip the requirement for generateData() if we are generating CSG object
      69         248 :     if (!hasGenerateCSG() && !hasGenerateData())
      70           3 :       system.dataDrivenError(*this, "does not support data-driven generation");
      71         245 :     if (hasSaveMesh())
      72           3 :       system.dataDrivenError(*this, "has 'save_with_name' set");
      73             :   }
      74       57075 :   if (_save_with_name == system.mainMeshGeneratorName())
      75           3 :     paramError(
      76           3 :         "save_with_name", "The user-defined mesh name: '", _save_with_name, "' is a reserved name");
      77      171244 :   if (getParam<bool>("nemesis") && !getParam<bool>("output"))
      78           0 :     paramError("nemesis", "Should only be set to true if 'output=true'");
      79       57072 : }
      80             : 
      81             : void
      82        6409 : MeshGenerator::setHasGenerateData(InputParameters & params)
      83             : {
      84        6409 :   params.set<bool>("_has_generate_data") = true;
      85        6409 : }
      86             : 
      87             : bool
      88       53563 : MeshGenerator::hasGenerateData(const InputParameters & params)
      89             : {
      90       53563 :   return params.get<bool>("_has_generate_data");
      91             : }
      92             : 
      93             : void
      94       24880 : MeshGenerator::setHasGenerateCSG(InputParameters & params)
      95             : {
      96       24880 :   params.set<bool>("_has_generate_csg") = true;
      97       24880 : }
      98             : 
      99             : bool
     100       63489 : MeshGenerator::hasGenerateCSG(const InputParameters & params)
     101             : {
     102       63489 :   return params.get<bool>("_has_generate_csg");
     103             : }
     104             : 
     105             : const MeshGeneratorName *
     106       27784 : MeshGenerator::getMeshGeneratorNameFromParam(const std::string & param_name,
     107             :                                              const bool allow_invalid) const
     108             : {
     109       27784 :   const auto valid_param = isParamValid(param_name);
     110       27784 :   if (!allow_invalid)
     111             :   {
     112       26004 :     if (!valid_param)
     113           3 :       mooseError("Failed to get a parameter with the name \"",
     114             :                  param_name,
     115             :                  "\" when getting a MeshGenerator.",
     116             :                  "\n\nKnown parameters:\n",
     117             :                  _pars);
     118       26001 :     if (!_pars.isType<MeshGeneratorName>(param_name))
     119           3 :       paramError(param_name,
     120             :                  "Parameter of type \"",
     121           3 :                  _pars.type(param_name),
     122             :                  "\" is not an expected type for getting a MeshGenerator (should be of type "
     123             :                  "\"MeshGeneratorName\")");
     124             :   }
     125        1780 :   else if (!valid_param)
     126        1406 :     return nullptr;
     127             : 
     128       26372 :   const auto & name = getParam<MeshGeneratorName>(param_name);
     129       26372 :   checkGetMesh(name, param_name);
     130             : 
     131       26366 :   return &name;
     132             : }
     133             : 
     134             : const std::vector<MeshGeneratorName> &
     135        1981 : MeshGenerator::getMeshGeneratorNamesFromParam(const std::string & param_name) const
     136             : {
     137        1981 :   if (!isParamValid(param_name))
     138           3 :     mooseError("Failed to get a parameter with the name \"",
     139             :                param_name,
     140             :                "\" when getting MeshGenerators.",
     141             :                "\n\nKnown parameters:\n",
     142             :                _pars);
     143        1978 :   if (!_pars.isType<std::vector<MeshGeneratorName>>(param_name))
     144           3 :     paramError(param_name,
     145             :                "Parameter of type \"",
     146           3 :                _pars.type(param_name),
     147             :                "\" is not an expected type for getting MeshGenerators (should be of type "
     148             :                "\"std::vector<MeshGeneratorName>\")");
     149             : 
     150        1975 :   const auto & names = getParam<std::vector<MeshGeneratorName>>(param_name);
     151        6729 :   for (const auto & name : names)
     152        4757 :     checkGetMesh(name, param_name);
     153             : 
     154        1972 :   return names;
     155             : }
     156             : 
     157             : void
     158       63035 : MeshGenerator::checkGetMesh(const MeshGeneratorName & mesh_generator_name,
     159             :                             const std::string & param_name) const
     160             : {
     161             :   mooseAssert(!mesh_generator_name.empty(), "Empty name");
     162       63035 :   const auto & mg_sys = _app.getMeshGeneratorSystem();
     163       63035 :   if (!hasGenerateCSG() && !_app.constructingMeshGenerators())
     164           3 :     mooseError("Cannot get a mesh outside of construction");
     165       63032 :   if (!mg_sys.hasMeshGenerator(mesh_generator_name) && !isNullMeshName(mesh_generator_name))
     166             :   {
     167          15 :     std::stringstream error;
     168          15 :     error << "The requested MeshGenerator with name '" << mesh_generator_name << "' ";
     169          15 :     if (mg_sys.hasMeshGeneratorParams(mesh_generator_name))
     170             :       error << "was found, but has not been constructed yet.\n\nThis can occur when your "
     171             :                "dependencies are not properly defined and we cannot infer the proper construction "
     172             :                "order of your MeshGenerators.\n\nThe most likely case is a sub generator whose "
     173           3 :                "input(s) are not declared as a sub dependency in the generator creating them.";
     174             :     else
     175             :       error << "was not found.\nMesh generators that can be found: "
     176          60 :             << Moose::stringify(mg_sys.getMeshGeneratorNames());
     177             : 
     178          15 :     if (param_name.size())
     179           9 :       paramError(param_name, error.str());
     180             :     else
     181           6 :       mooseError(error.str());
     182           0 :   }
     183       63017 : }
     184             : 
     185             : std::unique_ptr<MeshBase> &
     186       27666 : MeshGenerator::getMesh(const std::string & param_name, const bool allow_invalid /* = false */)
     187             : {
     188       27666 :   const MeshGeneratorName * name = getMeshGeneratorNameFromParam(param_name, allow_invalid);
     189       27654 :   if (!name)
     190        1406 :     return _null_mesh;
     191       26248 :   return getMeshByName(*name);
     192             : }
     193             : 
     194             : std::vector<std::unique_ptr<MeshBase> *>
     195        1973 : MeshGenerator::getMeshes(const std::string & param_name)
     196             : {
     197        1973 :   return getMeshesByName(getMeshGeneratorNamesFromParam(param_name));
     198             : }
     199             : 
     200             : std::unique_ptr<MeshBase> &
     201       31700 : MeshGenerator::getMeshByName(const MeshGeneratorName & mesh_generator_name)
     202             : {
     203       31700 :   checkGetMesh(mesh_generator_name, "");
     204       31691 :   if (isNullMeshName(mesh_generator_name))
     205          36 :     return _null_mesh;
     206             : 
     207       31655 :   _requested_mesh_generators.insert(mesh_generator_name);
     208       31655 :   auto & mesh = _app.getMeshGeneratorSystem().getMeshGeneratorOutput(mesh_generator_name);
     209       31655 :   _requested_meshes.emplace_back(mesh_generator_name, &mesh);
     210       31655 :   return mesh;
     211             : }
     212             : 
     213             : std::vector<std::unique_ptr<MeshBase> *>
     214        1967 : MeshGenerator::getMeshesByName(const std::vector<MeshGeneratorName> & mesh_generator_names)
     215             : {
     216        1967 :   std::vector<std::unique_ptr<MeshBase> *> meshes;
     217        6705 :   for (const auto & name : mesh_generator_names)
     218        4741 :     meshes.push_back(&getMeshByName(name));
     219        1964 :   return meshes;
     220           0 : }
     221             : 
     222             : std::unique_ptr<CSG::CSGBase> &
     223          83 : MeshGenerator::getCSGBase(const std::string & param_name)
     224             : {
     225          83 :   const MeshGeneratorName * name = getMeshGeneratorNameFromParam(param_name, false);
     226          83 :   if (!name)
     227           0 :     return _null_csg_base;
     228          83 :   return getCSGBaseByName(*name);
     229             : }
     230             : 
     231             : std::unique_ptr<CSG::CSGBase> &
     232         147 : MeshGenerator::getCSGBaseByName(const MeshGeneratorName & mesh_generator_name)
     233             : {
     234         147 :   checkGetMesh(mesh_generator_name, "");
     235         147 :   if (isNullMeshName(mesh_generator_name))
     236           0 :     return _null_csg_base;
     237             : 
     238         147 :   auto & csg_base = _app.getMeshGeneratorSystem().getCSGBaseGeneratorOutput(mesh_generator_name);
     239         147 :   _requested_csg_bases.emplace_back(mesh_generator_name, &csg_base);
     240         147 :   return csg_base;
     241             : }
     242             : 
     243             : std::vector<std::unique_ptr<CSG::CSGBase> *>
     244           8 : MeshGenerator::getCSGBases(const std::string & param_name)
     245             : {
     246           8 :   return getCSGBasesByName(getMeshGeneratorNamesFromParam(param_name));
     247             : }
     248             : 
     249             : std::vector<std::unique_ptr<CSG::CSGBase> *>
     250           8 : MeshGenerator::getCSGBasesByName(const std::vector<MeshGeneratorName> & mesh_generator_names)
     251             : {
     252           8 :   std::vector<std::unique_ptr<CSG::CSGBase> *> csg_bases;
     253          24 :   for (const auto & name : mesh_generator_names)
     254          16 :     csg_bases.push_back(&getCSGBaseByName(name));
     255           8 :   return csg_bases;
     256           0 : }
     257             : 
     258             : void
     259          35 : MeshGenerator::declareMeshForSub(const std::string & param_name)
     260             : {
     261          35 :   declareMeshForSubByName(*getMeshGeneratorNameFromParam(param_name, false));
     262          35 : }
     263             : 
     264             : void
     265           0 : MeshGenerator::declareMeshesForSub(const std::string & param_name)
     266             : {
     267           0 :   declareMeshesForSubByName(getMeshGeneratorNamesFromParam(param_name));
     268           0 : }
     269             : 
     270             : void
     271          59 : MeshGenerator::declareMeshForSubByName(const MeshGeneratorName & mesh_generator_name)
     272             : {
     273          59 :   checkGetMesh(mesh_generator_name, "");
     274          59 :   if (isNullMeshName(mesh_generator_name))
     275          24 :     return;
     276             : 
     277          35 :   _requested_mesh_generators_for_sub.insert(mesh_generator_name);
     278             : }
     279             : 
     280             : void
     281          12 : MeshGenerator::declareMeshesForSubByName(
     282             :     const std::vector<MeshGeneratorName> & mesh_generator_names)
     283             : {
     284          24 :   for (const auto & name : mesh_generator_names)
     285          12 :     declareMeshForSubByName(name);
     286          12 : }
     287             : 
     288             : std::unique_ptr<MeshBase>
     289       26898 : MeshGenerator::buildMeshBaseObject(unsigned int dim)
     290             : {
     291             :   mooseAssert(_mesh, "Need a MooseMesh object");
     292       26898 :   return _mesh->buildMeshBaseObject(dim);
     293             : }
     294             : 
     295             : std::unique_ptr<ReplicatedMesh>
     296        1505 : MeshGenerator::buildReplicatedMesh(unsigned int dim)
     297             : {
     298             :   mooseAssert(_mesh, "Need a MooseMesh object");
     299        1505 :   return _mesh->buildTypedMesh<ReplicatedMesh>(dim);
     300             : }
     301             : 
     302             : std::unique_ptr<DistributedMesh>
     303         781 : MeshGenerator::buildDistributedMesh(unsigned int dim)
     304             : {
     305             :   mooseAssert(_mesh, "Need a MooseMesh object");
     306         781 :   return _mesh->buildTypedMesh<DistributedMesh>(dim);
     307             : }
     308             : 
     309             : std::unique_ptr<MeshBase>
     310       53521 : MeshGenerator::generateInternal()
     311             : {
     312             :   libmesh_parallel_only(comm());
     313             :   mooseAssert(comm().verify(type() + name()), "Inconsistent execution ordering");
     314             : 
     315       53521 :   if (hasGenerateData())
     316          85 :     generateData();
     317             : 
     318       53521 :   if (isDataOnly())
     319         228 :     return nullptr;
     320             : 
     321       53293 :   auto mesh = generate();
     322       52906 :   if (!mesh)
     323           3 :     mooseError("A mesh was not generated by this generator (it was nullptr).");
     324             : 
     325       81929 :   for (const auto & [requested_name, requested_mesh] : _requested_meshes)
     326       29029 :     if (*requested_mesh)
     327           3 :       mooseError(
     328             :           "The mesh from input ",
     329           3 :           _app.getMeshGenerator(requested_name).type(),
     330             :           " '",
     331           3 :           _app.getMeshGenerator(requested_name).name(),
     332             :           "' was not moved.\n\nThe MeshGenerator system requires that the memory from all input "
     333             :           "meshes\nare managed by the requesting MeshGenerator during the generate phase.\n\nThis "
     334             :           "is achieved with a std::move() operation within the generate() method.");
     335             : 
     336      158700 :   if (getParam<bool>("show_info"))
     337             :   {
     338          83 :     if (!mesh->is_prepared())
     339          83 :       mesh->prepare_for_use();
     340             : 
     341          83 :     const auto mesh_info = mesh->get_info(/* verbosity = */ 2);
     342             : 
     343             :     // We will prefix all information with "type() 'name()':" because this could potentially
     344             :     // output a ton of information and looks a bit better with a prefix
     345          83 :     std::stringstream oss;
     346         166 :     const auto split = MooseUtils::split(mesh_info, "\n");
     347          83 :     if (split.size())
     348        5949 :       for (std::size_t i = 0; i < split.size() - 1; ++i) // ignore the last line break
     349        5866 :         oss << COLOR_CYAN << "" << type() << " '" << name() << "': " << COLOR_DEFAULT << split[i]
     350        5866 :             << std::endl;
     351          83 :     _console << oss.str() << std::flush;
     352          83 :   }
     353             : 
     354             :   // output the current mesh block to file
     355       52900 :   if (hasOutput())
     356             :   {
     357         477 :     if (!mesh->is_prepared())
     358         477 :       mesh->prepare_for_use();
     359             : 
     360        1431 :     if (!getParam<bool>("nemesis"))
     361             :     {
     362         463 :       libMesh::ExodusII_IO exio(*mesh);
     363             : 
     364         463 :       if (mesh->mesh_dimension() == 1)
     365          82 :         exio.write_as_dimension(3);
     366             : 
     367             :       // Avoid truncating names
     368         463 :       exio.set_max_name_length(80);
     369             : 
     370             :       // Default to non-HDF5 output for wider compatibility
     371         463 :       exio.set_hdf5_writing(false);
     372             : 
     373         463 :       exio.write(name() + "_in.e");
     374         463 :     }
     375             :     else
     376             :     {
     377          14 :       libMesh::Nemesis_IO nemesis_io(*mesh);
     378             : 
     379             :       // Default to non-HDF5 output for wider compatibility
     380          14 :       nemesis_io.set_hdf5_writing(false);
     381             : 
     382          14 :       nemesis_io.write(name() + "_in.e");
     383          14 :     }
     384             :   }
     385             : 
     386       52900 :   return mesh;
     387       52900 : }
     388             : 
     389             : std::unique_ptr<CSG::CSGBase>
     390         198 : MeshGenerator::generateInternalCSG()
     391             : {
     392             :   mooseAssert(isDataOnly(), "Trying to use csg-only mode while not in data-driven mode");
     393         198 :   auto csg_obj = generateCSG();
     394             :   mooseAssert(csg_obj, "Null CSG object");
     395         334 :   for (const auto & [requested_name, requested_csg] : _requested_csg_bases)
     396         139 :     if (*requested_csg)
     397           3 :       mooseError(
     398             :           "The CSGBase object from input ",
     399           3 :           _app.getMeshGenerator(requested_name).type(),
     400             :           " '",
     401           3 :           _app.getMeshGenerator(requested_name).name(),
     402             :           "' was not moved.\n\nThe MeshGenerator system requires that the memory from all input "
     403             :           "meshes\nare managed by the requesting MeshGenerator during the generate phase.\n\nThis "
     404             :           "is achieved with a std::move() operation within the generateCSG() method.");
     405             : 
     406         195 :   return csg_obj;
     407           0 : }
     408             : 
     409             : void
     410         196 : MeshGenerator::addMeshSubgenerator(const std::string & type,
     411             :                                    const std::string & name,
     412             :                                    InputParameters params)
     413             : {
     414         196 :   if (!_app.constructingMeshGenerators())
     415           3 :     mooseError("Can only call addMeshSubgenerator() during MeshGenerator construction");
     416             : 
     417             :   // In case the user forgot it
     418         193 :   params.set<MooseApp *>(MooseBase::app_param) = &_app;
     419             : 
     420             :   // Set this to be data-only if this generator is data only
     421         193 :   params.set<bool>(data_only_param) = isDataOnly();
     422             : 
     423         193 :   _app.addMeshGenerator(type, name, params);
     424         190 :   _sub_mesh_generators.insert(&std::as_const(_app).getMeshGenerator(name));
     425         190 : }
     426             : 
     427             : RestartableDataValue &
     428          23 : MeshGenerator::setMeshPropertyHelper(const std::string & data_name)
     429             : {
     430          23 :   return _app.getRestartableMetaData(meshPropertyName(data_name), MooseApp::MESH_META_DATA, 0);
     431             : }
     432             : 
     433             : void
     434       31436 : MeshGenerator::addParentMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     435             : {
     436             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     437       31436 :   _parent_mesh_generators.insert(&mg);
     438       31436 : }
     439             : 
     440             : void
     441       31436 : MeshGenerator::addChildMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     442             : {
     443             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     444       31436 :   _child_mesh_generators.insert(&mg);
     445       31436 : }
     446             : 
     447             : bool
     448       31448 : MeshGenerator::isParentMeshGenerator(const MeshGeneratorName & name,
     449             :                                      const bool direct /* = true */) const
     450             : {
     451       31448 :   return std::find_if(getParentMeshGenerators().begin(),
     452       31448 :                       getParentMeshGenerators().end(),
     453       45236 :                       [&name, &direct](const auto & mg)
     454             :                       {
     455       59114 :                         return mg->name() == name ||
     456       59114 :                                (!direct && mg->isParentMeshGenerator(name, /* direct = */ false));
     457       62896 :                       }) != getParentMeshGenerators().end();
     458             : }
     459             : 
     460             : bool
     461        5746 : MeshGenerator::isChildMeshGenerator(const MeshGeneratorName & name,
     462             :                                     const bool direct /* = true */) const
     463             : {
     464        5746 :   return std::find_if(getChildMeshGenerators().begin(),
     465        5746 :                       getChildMeshGenerators().end(),
     466        4546 :                       [&name, &direct](const auto & mg)
     467             :                       {
     468        7483 :                         return mg->name() == name ||
     469        7483 :                                (!direct && mg->isChildMeshGenerator(name, /* direct = */ false));
     470       11492 :                       }) != getChildMeshGenerators().end();
     471             : }
     472             : 
     473             : void
     474          12 : MeshGenerator::declareNullMeshName(const MeshGeneratorName & name)
     475             : {
     476             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     477             :   mooseAssert(!_null_mesh_names.count(name), "Already declared");
     478          12 :   _null_mesh_names.insert(name);
     479          12 : }
     480             : 
     481             : bool
     482      167339 : MeshGenerator::hasSaveMesh() const
     483             : {
     484      167339 :   return _save_with_name.size();
     485             : }
     486             : 
     487             : bool
     488      109586 : MeshGenerator::hasOutput() const
     489             : {
     490      328758 :   return getParam<bool>("output");
     491             : }
     492             : 
     493             : const std::string &
     494         130 : MeshGenerator::getSavedMeshName() const
     495             : {
     496         130 :   return _save_with_name;
     497             : }
     498             : 
     499             : void
     500           3 : MeshGenerator::generateData()
     501             : {
     502             :   mooseAssert(!hasGenerateData(), "Inconsistent flag");
     503           3 :   mooseError("This MeshGenerator does not have a generateData() implementation.");
     504             : }
     505             : 
     506             : [[nodiscard]] std::unique_ptr<CSG::CSGBase>
     507           0 : MeshGenerator::generateCSG()
     508             : {
     509             :   mooseAssert(!hasGenerateCSG(), "Inconsistent flag");
     510           0 :   mooseError("This MeshGenerator does not have a generateCSG() implementation.");
     511             : }

Generated by: LCOV version 1.14