LCOV - code coverage report
Current view: top level - src/meshgenerators - MeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 194 201 96.5 %
Date: 2025-07-17 01:28:37 Functions: 31 32 96.9 %
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     1471763 : MeshGenerator::validParams()
      24             : {
      25     1471763 :   InputParameters params = MooseObject::validParams();
      26             : 
      27     4415289 :   params.addParam<bool>("show_info",
      28     2943526 :                         false,
      29             :                         "Whether or not to show mesh info after generating the mesh "
      30             :                         "(bounding box, element types, sidesets, nodesets, subdomains, etc)");
      31     4415289 :   params.addParam<std::string>(
      32             :       "save_with_name",
      33     2943526 :       std::string(),
      34             :       "Keep the mesh from this mesh generator in memory with the name specified");
      35             : 
      36     4415289 :   params.addParam<bool>(
      37     2943526 :       "output", false, "Whether or not to output the mesh file after generating the mesh");
      38     4415289 :   params.addParam<bool>("nemesis",
      39     2943526 :                         false,
      40             :                         "Whether or not to output the mesh file in the nemesis"
      41             :                         "format (only if output = true)");
      42             : 
      43     1471763 :   params.addParamNamesToGroup("show_info output nemesis", "Debugging");
      44     1471763 :   params.addParamNamesToGroup("save_with_name", "Advanced");
      45     1471763 :   params.registerBase("MeshGenerator");
      46             : 
      47     1471763 :   params.addPrivateParam<bool>("_has_generate_data", false);
      48     1471763 :   params.addPrivateParam<MooseMesh *>("_moose_mesh", nullptr);
      49     1471763 :   params.addPrivateParam<bool>(data_only_param, false);
      50             :   // Controls are not created early enough
      51     1471763 :   params.suppressParameter<std::vector<std::string>>("control_tags");
      52             : 
      53     1471763 :   return params;
      54           0 : }
      55             : 
      56       51015 : MeshGenerator::MeshGenerator(const InputParameters & parameters)
      57             :   : MooseObject(parameters),
      58             :     MeshMetaDataInterface(this),
      59      102030 :     _mesh(getParam<MooseMesh *>("_moose_mesh") ? getParam<MooseMesh *>("_moose_mesh")
      60       51015 :                                                : _app.actionWarehouse().mesh().get()),
      61       51015 :     _save_with_name(getParam<std::string>("save_with_name")),
      62      153045 :     _data_only(getParam<bool>(data_only_param))
      63             : {
      64       51015 :   const auto & system = _app.getMeshGeneratorSystem();
      65       51015 :   if (isDataOnly())
      66             :   {
      67          46 :     if (!hasGenerateData())
      68           4 :       system.dataDrivenError(*this, "does not support data-driven generation");
      69          42 :     if (hasSaveMesh())
      70           4 :       system.dataDrivenError(*this, "has 'save_with_name' set");
      71             :   }
      72       51007 :   if (_save_with_name == system.mainMeshGeneratorName())
      73           4 :     paramError(
      74           4 :         "save_with_name", "The user-defined mesh name: '", _save_with_name, "' is a reserved name");
      75       51003 :   if (getParam<bool>("nemesis") && !getParam<bool>("output"))
      76           0 :     paramError("nemesis", "Should only be set to true if 'output=true'");
      77       51003 : }
      78             : 
      79             : void
      80       28860 : MeshGenerator::setHasGenerateData(InputParameters & params)
      81             : {
      82       28860 :   params.set<bool>("_has_generate_data") = true;
      83       28860 : }
      84             : 
      85             : bool
      86       47937 : MeshGenerator::hasGenerateData(const InputParameters & params)
      87             : {
      88       47937 :   return params.get<bool>("_has_generate_data");
      89             : }
      90             : 
      91             : const MeshGeneratorName *
      92       23427 : MeshGenerator::getMeshGeneratorNameFromParam(const std::string & param_name,
      93             :                                              const bool allow_invalid) const
      94             : {
      95       23427 :   const auto valid_param = isParamValid(param_name);
      96       23427 :   if (!allow_invalid)
      97             :   {
      98       22775 :     if (!valid_param)
      99           4 :       mooseError("Failed to get a parameter with the name \"",
     100             :                  param_name,
     101             :                  "\" when getting a MeshGenerator.",
     102             :                  "\n\nKnown parameters:\n",
     103             :                  _pars);
     104       22771 :     if (!_pars.isType<MeshGeneratorName>(param_name))
     105           4 :       paramError(param_name,
     106             :                  "Parameter of type \"",
     107           4 :                  _pars.type(param_name),
     108             :                  "\" is not an expected type for getting a MeshGenerator (should be of type "
     109             :                  "\"MeshGeneratorName\")");
     110             :   }
     111         652 :   else if (!valid_param)
     112         638 :     return nullptr;
     113             : 
     114       22781 :   const auto & name = getParam<MeshGeneratorName>(param_name);
     115       22781 :   checkGetMesh(name, param_name);
     116             : 
     117       22773 :   return &name;
     118             : }
     119             : 
     120             : const std::vector<MeshGeneratorName> &
     121        1704 : MeshGenerator::getMeshGeneratorNamesFromParam(const std::string & param_name) const
     122             : {
     123        1704 :   if (!isParamValid(param_name))
     124           4 :     mooseError("Failed to get a parameter with the name \"",
     125             :                param_name,
     126             :                "\" when getting MeshGenerators.",
     127             :                "\n\nKnown parameters:\n",
     128             :                _pars);
     129        1700 :   if (!_pars.isType<std::vector<MeshGeneratorName>>(param_name))
     130           4 :     paramError(param_name,
     131             :                "Parameter of type \"",
     132           4 :                _pars.type(param_name),
     133             :                "\" is not an expected type for getting MeshGenerators (should be of type "
     134             :                "\"std::vector<MeshGeneratorName>\")");
     135             : 
     136        1696 :   const auto & names = getParam<std::vector<MeshGeneratorName>>(param_name);
     137        5858 :   for (const auto & name : names)
     138        4166 :     checkGetMesh(name, param_name);
     139             : 
     140        1692 :   return names;
     141             : }
     142             : 
     143             : void
     144       54608 : MeshGenerator::checkGetMesh(const MeshGeneratorName & mesh_generator_name,
     145             :                             const std::string & param_name) const
     146             : {
     147             :   mooseAssert(!mesh_generator_name.empty(), "Empty name");
     148       54608 :   const auto & mg_sys = _app.getMeshGeneratorSystem();
     149       54608 :   if (!_app.constructingMeshGenerators())
     150           4 :     mooseError("Cannot get a mesh outside of construction");
     151       54604 :   if (!mg_sys.hasMeshGenerator(mesh_generator_name) && !isNullMeshName(mesh_generator_name))
     152             :   {
     153          20 :     std::stringstream error;
     154          20 :     error << "The requested MeshGenerator with name '" << mesh_generator_name << "' ";
     155          20 :     if (mg_sys.hasMeshGeneratorParams(mesh_generator_name))
     156             :       error << "was found, but has not been constructed yet.\n\nThis can occur when your "
     157             :                "dependencies are not properly defined and we cannot infer the proper construction "
     158             :                "order of your MeshGenerators.\n\nThe most likely case is a sub generator whose "
     159           4 :                "input(s) are not declared as a sub dependency in the generator creating them.";
     160             :     else
     161             :       error << "was not found.\nMesh generators that can be found: "
     162          16 :             << Moose::stringify(mg_sys.getMeshGeneratorNames());
     163             : 
     164          20 :     if (param_name.size())
     165          12 :       paramError(param_name, error.str());
     166             :     else
     167           8 :       mooseError(error.str());
     168           0 :   }
     169       54584 : }
     170             : 
     171             : std::unique_ptr<MeshBase> &
     172       23391 : MeshGenerator::getMesh(const std::string & param_name, const bool allow_invalid /* = false */)
     173             : {
     174       23391 :   const MeshGeneratorName * name = getMeshGeneratorNameFromParam(param_name, allow_invalid);
     175       23375 :   if (!name)
     176         638 :     return _null_mesh;
     177       22737 :   return getMeshByName(*name);
     178             : }
     179             : 
     180             : std::vector<std::unique_ptr<MeshBase> *>
     181        1704 : MeshGenerator::getMeshes(const std::string & param_name)
     182             : {
     183        1704 :   return getMeshesByName(getMeshGeneratorNamesFromParam(param_name));
     184             : }
     185             : 
     186             : std::unique_ptr<MeshBase> &
     187       27601 : MeshGenerator::getMeshByName(const MeshGeneratorName & mesh_generator_name)
     188             : {
     189       27601 :   checkGetMesh(mesh_generator_name, "");
     190       27589 :   if (isNullMeshName(mesh_generator_name))
     191          36 :     return _null_mesh;
     192             : 
     193       27553 :   _requested_mesh_generators.insert(mesh_generator_name);
     194       27553 :   auto & mesh = _app.getMeshGeneratorSystem().getMeshGeneratorOutput(mesh_generator_name);
     195       27553 :   _requested_meshes.emplace_back(mesh_generator_name, &mesh);
     196       27553 :   return mesh;
     197             : }
     198             : 
     199             : std::vector<std::unique_ptr<MeshBase> *>
     200        1696 : MeshGenerator::getMeshesByName(const std::vector<MeshGeneratorName> & mesh_generator_names)
     201             : {
     202        1696 :   std::vector<std::unique_ptr<MeshBase> *> meshes;
     203        5858 :   for (const auto & name : mesh_generator_names)
     204        4166 :     meshes.push_back(&getMeshByName(name));
     205        1692 :   return meshes;
     206           0 : }
     207             : 
     208             : void
     209          36 : MeshGenerator::declareMeshForSub(const std::string & param_name)
     210             : {
     211          36 :   declareMeshForSubByName(*getMeshGeneratorNameFromParam(param_name, false));
     212          36 : }
     213             : 
     214             : void
     215           0 : MeshGenerator::declareMeshesForSub(const std::string & param_name)
     216             : {
     217           0 :   declareMeshesForSubByName(getMeshGeneratorNamesFromParam(param_name));
     218           0 : }
     219             : 
     220             : void
     221          60 : MeshGenerator::declareMeshForSubByName(const MeshGeneratorName & mesh_generator_name)
     222             : {
     223          60 :   checkGetMesh(mesh_generator_name, "");
     224          60 :   if (isNullMeshName(mesh_generator_name))
     225          24 :     return;
     226             : 
     227          36 :   _requested_mesh_generators_for_sub.insert(mesh_generator_name);
     228             : }
     229             : 
     230             : void
     231          12 : MeshGenerator::declareMeshesForSubByName(
     232             :     const std::vector<MeshGeneratorName> & mesh_generator_names)
     233             : {
     234          24 :   for (const auto & name : mesh_generator_names)
     235          12 :     declareMeshForSubByName(name);
     236          12 : }
     237             : 
     238             : std::unique_ptr<MeshBase>
     239       24248 : MeshGenerator::buildMeshBaseObject(unsigned int dim)
     240             : {
     241             :   mooseAssert(_mesh, "Need a MooseMesh object");
     242       24248 :   return _mesh->buildMeshBaseObject(dim);
     243             : }
     244             : 
     245             : std::unique_ptr<ReplicatedMesh>
     246         682 : MeshGenerator::buildReplicatedMesh(unsigned int dim)
     247             : {
     248             :   mooseAssert(_mesh, "Need a MooseMesh object");
     249         682 :   return _mesh->buildTypedMesh<ReplicatedMesh>(dim);
     250             : }
     251             : 
     252             : std::unique_ptr<DistributedMesh>
     253         798 : MeshGenerator::buildDistributedMesh(unsigned int dim)
     254             : {
     255             :   mooseAssert(_mesh, "Need a MooseMesh object");
     256         798 :   return _mesh->buildTypedMesh<DistributedMesh>(dim);
     257             : }
     258             : 
     259             : std::unique_ptr<MeshBase>
     260       47891 : MeshGenerator::generateInternal()
     261             : {
     262             :   libmesh_parallel_only(comm());
     263             :   mooseAssert(comm().verify(type() + name()), "Inconsistent execution ordering");
     264             : 
     265       47891 :   if (hasGenerateData())
     266          86 :     generateData();
     267             : 
     268       47891 :   if (isDataOnly())
     269          30 :     return nullptr;
     270             : 
     271       47861 :   auto mesh = generate();
     272       47417 :   if (!mesh)
     273           4 :     mooseError("A mesh was not generated by this generator (it was nullptr).");
     274             : 
     275       72796 :   for (const auto & [requested_name, requested_mesh] : _requested_meshes)
     276       25387 :     if (*requested_mesh)
     277           4 :       mooseError(
     278             :           "The mesh from input ",
     279           4 :           _app.getMeshGenerator(requested_name).type(),
     280             :           " '",
     281           4 :           _app.getMeshGenerator(requested_name).name(),
     282             :           "' was not moved.\n\nThe MeshGenerator system requires that the memory from all input "
     283             :           "meshes\nare managed by the requesting MeshGenerator during the generate phase.\n\nThis "
     284             :           "is achieved with a std::move() operation within the generate() method.");
     285             : 
     286       47409 :   if (getParam<bool>("show_info"))
     287             :   {
     288          67 :     const auto mesh_info = mesh->get_info(/* verbosity = */ 2);
     289             : 
     290             :     // We will prefix all information with "type() 'name()':" because this could potentially
     291             :     // output a ton of information and looks a bit better with a prefix
     292          67 :     std::stringstream oss;
     293          67 :     const auto split = MooseUtils::split(mesh_info, "\n");
     294          67 :     if (split.size())
     295        4567 :       for (std::size_t i = 0; i < split.size() - 1; ++i) // ignore the last line break
     296        4500 :         oss << COLOR_CYAN << "" << type() << " '" << name() << "': " << COLOR_DEFAULT << split[i]
     297        4500 :             << std::endl;
     298          67 :     _console << oss.str() << std::flush;
     299          67 :   }
     300             : 
     301             :   // output the current mesh block to file
     302       47409 :   if (hasOutput())
     303             :   {
     304         315 :     if (!mesh->is_prepared())
     305         315 :       mesh->prepare_for_use();
     306             : 
     307         315 :     if (!getParam<bool>("nemesis"))
     308             :     {
     309         301 :       libMesh::ExodusII_IO exio(*mesh);
     310             : 
     311         301 :       if (mesh->mesh_dimension() == 1)
     312          10 :         exio.write_as_dimension(3);
     313             : 
     314             :       // Default to non-HDF5 output for wider compatibility
     315         301 :       exio.set_hdf5_writing(false);
     316             : 
     317         301 :       exio.write(name() + "_in.e");
     318         301 :     }
     319             :     else
     320             :     {
     321          14 :       libMesh::Nemesis_IO nemesis_io(*mesh);
     322             : 
     323             :       // Default to non-HDF5 output for wider compatibility
     324          14 :       nemesis_io.set_hdf5_writing(false);
     325             : 
     326          14 :       nemesis_io.write(name() + "_in.e");
     327          14 :     }
     328             :   }
     329             : 
     330       47409 :   return mesh;
     331       47409 : }
     332             : 
     333             : void
     334         208 : MeshGenerator::addMeshSubgenerator(const std::string & type,
     335             :                                    const std::string & name,
     336             :                                    InputParameters params)
     337             : {
     338         208 :   if (!_app.constructingMeshGenerators())
     339           4 :     mooseError("Can only call addMeshSubgenerator() during MeshGenerator construction");
     340             : 
     341             :   // In case the user forgot it
     342         204 :   params.set<MooseApp *>("_moose_app") = &_app;
     343             : 
     344             :   // Set this to be data-only if this generator is data only
     345         204 :   params.set<bool>(data_only_param) = isDataOnly();
     346             : 
     347         204 :   _app.addMeshGenerator(type, name, params);
     348         200 :   _sub_mesh_generators.insert(&std::as_const(_app).getMeshGenerator(name));
     349         200 : }
     350             : 
     351             : RestartableDataValue &
     352          24 : MeshGenerator::setMeshPropertyHelper(const std::string & data_name)
     353             : {
     354          24 :   return _app.getRestartableMetaData(meshPropertyName(data_name), MooseApp::MESH_META_DATA, 0);
     355             : }
     356             : 
     357             : void
     358       27305 : MeshGenerator::addParentMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     359             : {
     360             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     361       27305 :   _parent_mesh_generators.insert(&mg);
     362       27305 : }
     363             : 
     364             : void
     365       27305 : MeshGenerator::addChildMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     366             : {
     367             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     368       27305 :   _child_mesh_generators.insert(&mg);
     369       27305 : }
     370             : 
     371             : bool
     372       27315 : MeshGenerator::isParentMeshGenerator(const MeshGeneratorName & name,
     373             :                                      const bool direct /* = true */) const
     374             : {
     375       27315 :   return std::find_if(getParentMeshGenerators().begin(),
     376       27315 :                       getParentMeshGenerators().end(),
     377       53239 :                       [&name, &direct](const auto & mg)
     378             :                       {
     379       53239 :                         return mg->name() == name ||
     380       53239 :                                (!direct && mg->isParentMeshGenerator(name, /* direct = */ false));
     381       54630 :                       }) != getParentMeshGenerators().end();
     382             : }
     383             : 
     384             : bool
     385        4097 : MeshGenerator::isChildMeshGenerator(const MeshGeneratorName & name,
     386             :                                     const bool direct /* = true */) const
     387             : {
     388        4097 :   return std::find_if(getChildMeshGenerators().begin(),
     389        4097 :                       getChildMeshGenerators().end(),
     390        6825 :                       [&name, &direct](const auto & mg)
     391             :                       {
     392        4986 :                         return mg->name() == name ||
     393        4986 :                                (!direct && mg->isChildMeshGenerator(name, /* direct = */ false));
     394        8194 :                       }) != getChildMeshGenerators().end();
     395             : }
     396             : 
     397             : void
     398          12 : MeshGenerator::declareNullMeshName(const MeshGeneratorName & name)
     399             : {
     400             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     401             :   mooseAssert(!_null_mesh_names.count(name), "Already declared");
     402          12 :   _null_mesh_names.insert(name);
     403          12 : }
     404             : 
     405             : bool
     406      148963 : MeshGenerator::hasSaveMesh() const
     407             : {
     408      148963 :   return _save_with_name.size();
     409             : }
     410             : 
     411             : bool
     412       97664 : MeshGenerator::hasOutput() const
     413             : {
     414       97664 :   return getParam<bool>("output");
     415             : }
     416             : 
     417             : const std::string &
     418         142 : MeshGenerator::getSavedMeshName() const
     419             : {
     420         142 :   return _save_with_name;
     421             : }
     422             : 
     423             : void
     424           4 : MeshGenerator::generateData()
     425             : {
     426             :   mooseAssert(!hasGenerateData(), "Inconsistent flag");
     427           4 :   mooseError("This MeshGenerator does not have a generateData() implementation.");
     428             : }

Generated by: LCOV version 1.14