LCOV - code coverage report
Current view: top level - src/meshgenerators - MeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 194 201 96.5 %
Date: 2025-08-08 20:01:16 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     1494388 : MeshGenerator::validParams()
      24             : {
      25     1494388 :   InputParameters params = MooseObject::validParams();
      26             : 
      27     4483164 :   params.addParam<bool>("show_info",
      28     2988776 :                         false,
      29             :                         "Whether or not to show mesh info after generating the mesh "
      30             :                         "(bounding box, element types, sidesets, nodesets, subdomains, etc)");
      31     4483164 :   params.addParam<std::string>(
      32             :       "save_with_name",
      33     2988776 :       std::string(),
      34             :       "Keep the mesh from this mesh generator in memory with the name specified");
      35             : 
      36     4483164 :   params.addParam<bool>(
      37     2988776 :       "output", false, "Whether or not to output the mesh file after generating the mesh");
      38     4483164 :   params.addParam<bool>("nemesis",
      39     2988776 :                         false,
      40             :                         "Whether or not to output the mesh file in the nemesis"
      41             :                         "format (only if output = true)");
      42             : 
      43     1494388 :   params.addParamNamesToGroup("show_info output nemesis", "Debugging");
      44     1494388 :   params.addParamNamesToGroup("save_with_name", "Advanced");
      45     1494388 :   params.registerBase("MeshGenerator");
      46             : 
      47     1494388 :   params.addPrivateParam<bool>("_has_generate_data", false);
      48     1494388 :   params.addPrivateParam<MooseMesh *>("_moose_mesh", nullptr);
      49     1494388 :   params.addPrivateParam<bool>(data_only_param, false);
      50             :   // Controls are not created early enough
      51     1494388 :   params.suppressParameter<std::vector<std::string>>("control_tags");
      52             : 
      53     1494388 :   return params;
      54           0 : }
      55             : 
      56       55186 : MeshGenerator::MeshGenerator(const InputParameters & parameters)
      57             :   : MooseObject(parameters),
      58             :     MeshMetaDataInterface(this),
      59      110372 :     _mesh(getParam<MooseMesh *>("_moose_mesh") ? getParam<MooseMesh *>("_moose_mesh")
      60       55186 :                                                : _app.actionWarehouse().mesh().get()),
      61       55186 :     _save_with_name(getParam<std::string>("save_with_name")),
      62      165558 :     _data_only(getParam<bool>(data_only_param))
      63             : {
      64       55186 :   const auto & system = _app.getMeshGeneratorSystem();
      65       55186 :   if (isDataOnly())
      66             :   {
      67          49 :     if (!hasGenerateData())
      68           4 :       system.dataDrivenError(*this, "does not support data-driven generation");
      69          45 :     if (hasSaveMesh())
      70           4 :       system.dataDrivenError(*this, "has 'save_with_name' set");
      71             :   }
      72       55178 :   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       55174 :   if (getParam<bool>("nemesis") && !getParam<bool>("output"))
      76           0 :     paramError("nemesis", "Should only be set to true if 'output=true'");
      77       55174 : }
      78             : 
      79             : void
      80       28876 : MeshGenerator::setHasGenerateData(InputParameters & params)
      81             : {
      82       28876 :   params.set<bool>("_has_generate_data") = true;
      83       28876 : }
      84             : 
      85             : bool
      86       52052 : MeshGenerator::hasGenerateData(const InputParameters & params)
      87             : {
      88       52052 :   return params.get<bool>("_has_generate_data");
      89             : }
      90             : 
      91             : const MeshGeneratorName *
      92       25235 : MeshGenerator::getMeshGeneratorNameFromParam(const std::string & param_name,
      93             :                                              const bool allow_invalid) const
      94             : {
      95       25235 :   const auto valid_param = isParamValid(param_name);
      96       25235 :   if (!allow_invalid)
      97             :   {
      98       24530 :     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       24526 :     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         705 :   else if (!valid_param)
     112         690 :     return nullptr;
     113             : 
     114       24537 :   const auto & name = getParam<MeshGeneratorName>(param_name);
     115       24537 :   checkGetMesh(name, param_name);
     116             : 
     117       24529 :   return &name;
     118             : }
     119             : 
     120             : const std::vector<MeshGeneratorName> &
     121        1865 : MeshGenerator::getMeshGeneratorNamesFromParam(const std::string & param_name) const
     122             : {
     123        1865 :   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        1861 :   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        1857 :   const auto & names = getParam<std::vector<MeshGeneratorName>>(param_name);
     137        6435 :   for (const auto & name : names)
     138        4582 :     checkGetMesh(name, param_name);
     139             : 
     140        1853 :   return names;
     141             : }
     142             : 
     143             : void
     144       59005 : MeshGenerator::checkGetMesh(const MeshGeneratorName & mesh_generator_name,
     145             :                             const std::string & param_name) const
     146             : {
     147             :   mooseAssert(!mesh_generator_name.empty(), "Empty name");
     148       59005 :   const auto & mg_sys = _app.getMeshGeneratorSystem();
     149       59005 :   if (!_app.constructingMeshGenerators())
     150           4 :     mooseError("Cannot get a mesh outside of construction");
     151       59001 :   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       58981 : }
     170             : 
     171             : std::unique_ptr<MeshBase> &
     172       25195 : MeshGenerator::getMesh(const std::string & param_name, const bool allow_invalid /* = false */)
     173             : {
     174       25195 :   const MeshGeneratorName * name = getMeshGeneratorNameFromParam(param_name, allow_invalid);
     175       25179 :   if (!name)
     176         690 :     return _null_mesh;
     177       24489 :   return getMeshByName(*name);
     178             : }
     179             : 
     180             : std::vector<std::unique_ptr<MeshBase> *>
     181        1865 : MeshGenerator::getMeshes(const std::string & param_name)
     182             : {
     183        1865 :   return getMeshesByName(getMeshGeneratorNamesFromParam(param_name));
     184             : }
     185             : 
     186             : std::unique_ptr<MeshBase> &
     187       29820 : MeshGenerator::getMeshByName(const MeshGeneratorName & mesh_generator_name)
     188             : {
     189       29820 :   checkGetMesh(mesh_generator_name, "");
     190       29808 :   if (isNullMeshName(mesh_generator_name))
     191          39 :     return _null_mesh;
     192             : 
     193       29769 :   _requested_mesh_generators.insert(mesh_generator_name);
     194       29769 :   auto & mesh = _app.getMeshGeneratorSystem().getMeshGeneratorOutput(mesh_generator_name);
     195       29769 :   _requested_meshes.emplace_back(mesh_generator_name, &mesh);
     196       29769 :   return mesh;
     197             : }
     198             : 
     199             : std::vector<std::unique_ptr<MeshBase> *>
     200        1857 : MeshGenerator::getMeshesByName(const std::vector<MeshGeneratorName> & mesh_generator_names)
     201             : {
     202        1857 :   std::vector<std::unique_ptr<MeshBase> *> meshes;
     203        6435 :   for (const auto & name : mesh_generator_names)
     204        4582 :     meshes.push_back(&getMeshByName(name));
     205        1853 :   return meshes;
     206           0 : }
     207             : 
     208             : void
     209          40 : MeshGenerator::declareMeshForSub(const std::string & param_name)
     210             : {
     211          40 :   declareMeshForSubByName(*getMeshGeneratorNameFromParam(param_name, false));
     212          40 : }
     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          66 : MeshGenerator::declareMeshForSubByName(const MeshGeneratorName & mesh_generator_name)
     222             : {
     223          66 :   checkGetMesh(mesh_generator_name, "");
     224          66 :   if (isNullMeshName(mesh_generator_name))
     225          26 :     return;
     226             : 
     227          40 :   _requested_mesh_generators_for_sub.insert(mesh_generator_name);
     228             : }
     229             : 
     230             : void
     231          13 : MeshGenerator::declareMeshesForSubByName(
     232             :     const std::vector<MeshGeneratorName> & mesh_generator_names)
     233             : {
     234          26 :   for (const auto & name : mesh_generator_names)
     235          13 :     declareMeshForSubByName(name);
     236          13 : }
     237             : 
     238             : std::unique_ptr<MeshBase>
     239       26408 : MeshGenerator::buildMeshBaseObject(unsigned int dim)
     240             : {
     241             :   mooseAssert(_mesh, "Need a MooseMesh object");
     242       26408 :   return _mesh->buildMeshBaseObject(dim);
     243             : }
     244             : 
     245             : std::unique_ptr<ReplicatedMesh>
     246         741 : MeshGenerator::buildReplicatedMesh(unsigned int dim)
     247             : {
     248             :   mooseAssert(_mesh, "Need a MooseMesh object");
     249         741 :   return _mesh->buildTypedMesh<ReplicatedMesh>(dim);
     250             : }
     251             : 
     252             : std::unique_ptr<DistributedMesh>
     253         880 : MeshGenerator::buildDistributedMesh(unsigned int dim)
     254             : {
     255             :   mooseAssert(_mesh, "Need a MooseMesh object");
     256         880 :   return _mesh->buildTypedMesh<DistributedMesh>(dim);
     257             : }
     258             : 
     259             : std::unique_ptr<MeshBase>
     260       52003 : MeshGenerator::generateInternal()
     261             : {
     262             :   libmesh_parallel_only(comm());
     263             :   mooseAssert(comm().verify(type() + name()), "Inconsistent execution ordering");
     264             : 
     265       52003 :   if (hasGenerateData())
     266          94 :     generateData();
     267             : 
     268       52003 :   if (isDataOnly())
     269          33 :     return nullptr;
     270             : 
     271       51970 :   auto mesh = generate();
     272       51526 :   if (!mesh)
     273           4 :     mooseError("A mesh was not generated by this generator (it was nullptr).");
     274             : 
     275       79082 :   for (const auto & [requested_name, requested_mesh] : _requested_meshes)
     276       27564 :     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       51518 :   if (getParam<bool>("show_info"))
     287             :   {
     288          75 :     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          75 :     std::stringstream oss;
     293          75 :     const auto split = MooseUtils::split(mesh_info, "\n");
     294          75 :     if (split.size())
     295        5238 :       for (std::size_t i = 0; i < split.size() - 1; ++i) // ignore the last line break
     296        5163 :         oss << COLOR_CYAN << "" << type() << " '" << name() << "': " << COLOR_DEFAULT << split[i]
     297        5163 :             << std::endl;
     298          75 :     _console << oss.str() << std::flush;
     299          75 :   }
     300             : 
     301             :   // output the current mesh block to file
     302       51518 :   if (hasOutput())
     303             :   {
     304         347 :     if (!mesh->is_prepared())
     305         347 :       mesh->prepare_for_use();
     306             : 
     307         347 :     if (!getParam<bool>("nemesis"))
     308             :     {
     309         331 :       libMesh::ExodusII_IO exio(*mesh);
     310             : 
     311         331 :       if (mesh->mesh_dimension() == 1)
     312          11 :         exio.write_as_dimension(3);
     313             : 
     314             :       // Default to non-HDF5 output for wider compatibility
     315         331 :       exio.set_hdf5_writing(false);
     316             : 
     317         331 :       exio.write(name() + "_in.e");
     318         331 :     }
     319             :     else
     320             :     {
     321          16 :       libMesh::Nemesis_IO nemesis_io(*mesh);
     322             : 
     323             :       // Default to non-HDF5 output for wider compatibility
     324          16 :       nemesis_io.set_hdf5_writing(false);
     325             : 
     326          16 :       nemesis_io.write(name() + "_in.e");
     327          16 :     }
     328             :   }
     329             : 
     330       51518 :   return mesh;
     331       51518 : }
     332             : 
     333             : void
     334         227 : MeshGenerator::addMeshSubgenerator(const std::string & type,
     335             :                                    const std::string & name,
     336             :                                    InputParameters params)
     337             : {
     338         227 :   if (!_app.constructingMeshGenerators())
     339           4 :     mooseError("Can only call addMeshSubgenerator() during MeshGenerator construction");
     340             : 
     341             :   // In case the user forgot it
     342         223 :   params.set<MooseApp *>("_moose_app") = &_app;
     343             : 
     344             :   // Set this to be data-only if this generator is data only
     345         223 :   params.set<bool>(data_only_param) = isDataOnly();
     346             : 
     347         223 :   _app.addMeshGenerator(type, name, params);
     348         219 :   _sub_mesh_generators.insert(&std::as_const(_app).getMeshGenerator(name));
     349         219 : }
     350             : 
     351             : RestartableDataValue &
     352          26 : MeshGenerator::setMeshPropertyHelper(const std::string & data_name)
     353             : {
     354          26 :   return _app.getRestartableMetaData(meshPropertyName(data_name), MooseApp::MESH_META_DATA, 0);
     355             : }
     356             : 
     357             : void
     358       29521 : MeshGenerator::addParentMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     359             : {
     360             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     361       29521 :   _parent_mesh_generators.insert(&mg);
     362       29521 : }
     363             : 
     364             : void
     365       29521 : MeshGenerator::addChildMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     366             : {
     367             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     368       29521 :   _child_mesh_generators.insert(&mg);
     369       29521 : }
     370             : 
     371             : bool
     372       29534 : MeshGenerator::isParentMeshGenerator(const MeshGeneratorName & name,
     373             :                                      const bool direct /* = true */) const
     374             : {
     375       29534 :   return std::find_if(getParentMeshGenerators().begin(),
     376       29534 :                       getParentMeshGenerators().end(),
     377       58133 :                       [&name, &direct](const auto & mg)
     378             :                       {
     379       58133 :                         return mg->name() == name ||
     380       58133 :                                (!direct && mg->isParentMeshGenerator(name, /* direct = */ false));
     381       59068 :                       }) != getParentMeshGenerators().end();
     382             : }
     383             : 
     384             : bool
     385        4497 : MeshGenerator::isChildMeshGenerator(const MeshGeneratorName & name,
     386             :                                     const bool direct /* = true */) const
     387             : {
     388        4497 :   return std::find_if(getChildMeshGenerators().begin(),
     389        4497 :                       getChildMeshGenerators().end(),
     390        7491 :                       [&name, &direct](const auto & mg)
     391             :                       {
     392        5471 :                         return mg->name() == name ||
     393        5471 :                                (!direct && mg->isChildMeshGenerator(name, /* direct = */ false));
     394        8994 :                       }) != getChildMeshGenerators().end();
     395             : }
     396             : 
     397             : void
     398          13 : 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          13 :   _null_mesh_names.insert(name);
     403          13 : }
     404             : 
     405             : bool
     406      161589 : MeshGenerator::hasSaveMesh() const
     407             : {
     408      161589 :   return _save_with_name.size();
     409             : }
     410             : 
     411             : bool
     412      106107 : MeshGenerator::hasOutput() const
     413             : {
     414      106107 :   return getParam<bool>("output");
     415             : }
     416             : 
     417             : const std::string &
     418         151 : MeshGenerator::getSavedMeshName() const
     419             : {
     420         151 :   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