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

Generated by: LCOV version 1.14