LCOV - code coverage report
Current view: top level - src/meshgenerators - MeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31405 (292dce) with base fef103 Lines: 194 201 96.5 %
Date: 2025-09-04 07:52:05 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     1526944 : MeshGenerator::validParams()
      24             : {
      25     1526944 :   InputParameters params = MooseObject::validParams();
      26             : 
      27     4580832 :   params.addParam<bool>("show_info",
      28     3053888 :                         false,
      29             :                         "Whether or not to show mesh info after generating the mesh "
      30             :                         "(bounding box, element types, sidesets, nodesets, subdomains, etc)");
      31     4580832 :   params.addParam<std::string>(
      32             :       "save_with_name",
      33     3053888 :       std::string(),
      34             :       "Keep the mesh from this mesh generator in memory with the name specified");
      35             : 
      36     4580832 :   params.addParam<bool>(
      37     3053888 :       "output", false, "Whether or not to output the mesh file after generating the mesh");
      38     4580832 :   params.addParam<bool>("nemesis",
      39     3053888 :                         false,
      40             :                         "Whether or not to output the mesh file in the nemesis"
      41             :                         "format (only if output = true)");
      42             : 
      43     6107776 :   params.addParamNamesToGroup("show_info output nemesis", "Debugging");
      44     6107776 :   params.addParamNamesToGroup("save_with_name", "Advanced");
      45     1526944 :   params.registerBase("MeshGenerator");
      46             : 
      47     3053888 :   params.addPrivateParam<bool>("_has_generate_data", false);
      48     3053888 :   params.addPrivateParam<MooseMesh *>("_moose_mesh", nullptr);
      49     1526944 :   params.addPrivateParam<bool>(data_only_param, false);
      50             :   // Controls are not created early enough
      51     1526944 :   params.suppressParameter<std::vector<std::string>>("control_tags");
      52             : 
      53     1526944 :   return params;
      54           0 : }
      55             : 
      56       57193 : MeshGenerator::MeshGenerator(const InputParameters & parameters)
      57             :   : MooseObject(parameters),
      58             :     MeshMetaDataInterface(this),
      59      114386 :     _mesh(getParam<MooseMesh *>("_moose_mesh") ? getParam<MooseMesh *>("_moose_mesh")
      60       57193 :                                                : _app.actionWarehouse().mesh().get()),
      61      114386 :     _save_with_name(getParam<std::string>("save_with_name")),
      62      171579 :     _data_only(getParam<bool>(data_only_param))
      63             : {
      64       57193 :   const auto & system = _app.getMeshGeneratorSystem();
      65       57193 :   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       57185 :   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      171575 :   if (getParam<bool>("nemesis") && !getParam<bool>("output"))
      76           0 :     paramError("nemesis", "Should only be set to true if 'output=true'");
      77       57181 : }
      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       53798 : MeshGenerator::hasGenerateData(const InputParameters & params)
      87             : {
      88       53798 :   return params.get<bool>("_has_generate_data");
      89             : }
      90             : 
      91             : const MeshGeneratorName *
      92       26527 : MeshGenerator::getMeshGeneratorNameFromParam(const std::string & param_name,
      93             :                                              const bool allow_invalid) const
      94             : {
      95       26527 :   const auto valid_param = isParamValid(param_name);
      96       26527 :   if (!allow_invalid)
      97             :   {
      98       25822 :     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       25818 :     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       25829 :   const auto & name = getParam<MeshGeneratorName>(param_name);
     115       25829 :   checkGetMesh(name, param_name);
     116             : 
     117       25821 :   return &name;
     118             : }
     119             : 
     120             : const std::vector<MeshGeneratorName> &
     121        1919 : MeshGenerator::getMeshGeneratorNamesFromParam(const std::string & param_name) const
     122             : {
     123        1919 :   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        1915 :   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        1911 :   const auto & names = getParam<std::vector<MeshGeneratorName>>(param_name);
     137        6651 :   for (const auto & name : names)
     138        4744 :     checkGetMesh(name, param_name);
     139             : 
     140        1907 :   return names;
     141             : }
     142             : 
     143             : void
     144       61948 : MeshGenerator::checkGetMesh(const MeshGeneratorName & mesh_generator_name,
     145             :                             const std::string & param_name) const
     146             : {
     147             :   mooseAssert(!mesh_generator_name.empty(), "Empty name");
     148       61948 :   const auto & mg_sys = _app.getMeshGeneratorSystem();
     149       61948 :   if (!_app.constructingMeshGenerators())
     150           4 :     mooseError("Cannot get a mesh outside of construction");
     151       61944 :   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          80 :             << 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       61924 : }
     170             : 
     171             : std::unique_ptr<MeshBase> &
     172       26487 : MeshGenerator::getMesh(const std::string & param_name, const bool allow_invalid /* = false */)
     173             : {
     174       26487 :   const MeshGeneratorName * name = getMeshGeneratorNameFromParam(param_name, allow_invalid);
     175       26471 :   if (!name)
     176         690 :     return _null_mesh;
     177       25781 :   return getMeshByName(*name);
     178             : }
     179             : 
     180             : std::vector<std::unique_ptr<MeshBase> *>
     181        1919 : MeshGenerator::getMeshes(const std::string & param_name)
     182             : {
     183        1919 :   return getMeshesByName(getMeshGeneratorNamesFromParam(param_name));
     184             : }
     185             : 
     186             : std::unique_ptr<MeshBase> &
     187       31309 : MeshGenerator::getMeshByName(const MeshGeneratorName & mesh_generator_name)
     188             : {
     189       31309 :   checkGetMesh(mesh_generator_name, "");
     190       31297 :   if (isNullMeshName(mesh_generator_name))
     191          39 :     return _null_mesh;
     192             : 
     193       31258 :   _requested_mesh_generators.insert(mesh_generator_name);
     194       31258 :   auto & mesh = _app.getMeshGeneratorSystem().getMeshGeneratorOutput(mesh_generator_name);
     195       31258 :   _requested_meshes.emplace_back(mesh_generator_name, &mesh);
     196       31258 :   return mesh;
     197             : }
     198             : 
     199             : std::vector<std::unique_ptr<MeshBase> *>
     200        1911 : MeshGenerator::getMeshesByName(const std::vector<MeshGeneratorName> & mesh_generator_names)
     201             : {
     202        1911 :   std::vector<std::unique_ptr<MeshBase> *> meshes;
     203        6651 :   for (const auto & name : mesh_generator_names)
     204        4744 :     meshes.push_back(&getMeshByName(name));
     205        1907 :   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       27271 : MeshGenerator::buildMeshBaseObject(unsigned int dim)
     240             : {
     241             :   mooseAssert(_mesh, "Need a MooseMesh object");
     242       27271 :   return _mesh->buildMeshBaseObject(dim);
     243             : }
     244             : 
     245             : std::unique_ptr<ReplicatedMesh>
     246         768 : MeshGenerator::buildReplicatedMesh(unsigned int dim)
     247             : {
     248             :   mooseAssert(_mesh, "Need a MooseMesh object");
     249         768 :   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       53749 : MeshGenerator::generateInternal()
     261             : {
     262             :   libmesh_parallel_only(comm());
     263             :   mooseAssert(comm().verify(type() + name()), "Inconsistent execution ordering");
     264             : 
     265       53749 :   if (hasGenerateData())
     266          94 :     generateData();
     267             : 
     268       53749 :   if (isDataOnly())
     269          33 :     return nullptr;
     270             : 
     271       53716 :   auto mesh = generate();
     272       53228 :   if (!mesh)
     273           4 :     mooseError("A mesh was not generated by this generator (it was nullptr).");
     274             : 
     275       81908 :   for (const auto & [requested_name, requested_mesh] : _requested_meshes)
     276       28688 :     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      159660 :   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         150 :     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       53220 :   if (hasOutput())
     303             :   {
     304         347 :     if (!mesh->is_prepared())
     305         347 :       mesh->prepare_for_use();
     306             : 
     307        1041 :     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       53220 :   return mesh;
     331       53220 : }
     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 *>(MooseBase::app_param) = &_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       31010 : MeshGenerator::addParentMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     359             : {
     360             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     361       31010 :   _parent_mesh_generators.insert(&mg);
     362       31010 : }
     363             : 
     364             : void
     365       31010 : MeshGenerator::addChildMeshGenerator(const MeshGenerator & mg, const AddParentChildKey)
     366             : {
     367             :   mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
     368       31010 :   _child_mesh_generators.insert(&mg);
     369       31010 : }
     370             : 
     371             : bool
     372       31023 : MeshGenerator::isParentMeshGenerator(const MeshGeneratorName & name,
     373             :                                      const bool direct /* = true */) const
     374             : {
     375       31023 :   return std::find_if(getParentMeshGenerators().begin(),
     376       31023 :                       getParentMeshGenerators().end(),
     377       45675 :                       [&name, &direct](const auto & mg)
     378             :                       {
     379       60432 :                         return mg->name() == name ||
     380       60432 :                                (!direct && mg->isParentMeshGenerator(name, /* direct = */ false));
     381       62046 :                       }) != getParentMeshGenerators().end();
     382             : }
     383             : 
     384             : bool
     385        5541 : MeshGenerator::isChildMeshGenerator(const MeshGeneratorName & name,
     386             :                                     const bool direct /* = true */) const
     387             : {
     388        5541 :   return std::find_if(getChildMeshGenerators().begin(),
     389        5541 :                       getChildMeshGenerators().end(),
     390        4315 :                       [&name, &direct](const auto & mg)
     391             :                       {
     392        7127 :                         return mg->name() == name ||
     393        7127 :                                (!direct && mg->isChildMeshGenerator(name, /* direct = */ false));
     394       11082 :                       }) != 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      167520 : MeshGenerator::hasSaveMesh() const
     407             : {
     408      167520 :   return _save_with_name.size();
     409             : }
     410             : 
     411             : bool
     412      109987 : MeshGenerator::hasOutput() const
     413             : {
     414      329961 :   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