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

Generated by: LCOV version 1.14