LCOV - code coverage report
Current view: top level - src/base - MeshGeneratorSystem.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 249 268 92.9 %
Date: 2025-08-08 20:01:16 Functions: 22 23 95.7 %
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 "MeshGeneratorSystem.h"
      11             : 
      12             : #include "MooseApp.h"
      13             : #include "MeshGenerator.h"
      14             : #include "DependencyResolver.h"
      15             : 
      16             : #include "libmesh/mesh_tools.h"
      17             : 
      18             : using namespace libMesh;
      19             : 
      20             : const std::string MeshGeneratorSystem::data_driven_generator_param = "data_driven_generator";
      21             : const std::string MeshGeneratorSystem::allow_data_driven_param =
      22             :     "allow_data_driven_mesh_generation";
      23             : 
      24       67610 : MeshGeneratorSystem::MeshGeneratorSystem(MooseApp & app)
      25             :   : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
      26             :     ParallelObject(app),
      27       67610 :     _app(app),
      28       67610 :     _has_bmbb(false),
      29       67610 :     _verbose(false)
      30             : {
      31       67610 : }
      32             : 
      33             : void
      34       55395 : MeshGeneratorSystem::addMeshGenerator(const std::string & type,
      35             :                                       const std::string & name,
      36             :                                       const InputParameters & params)
      37             : {
      38             :   mooseAssert(!_mesh_generator_params.count(name), "Already exists");
      39       55395 :   _mesh_generator_params.emplace(
      40       55395 :       std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
      41             : 
      42             :   // This should be a sub mesh generator. We can assume this because if we're in the middle of
      43             :   // constructing mesh generators (not "adding" them, where we simply store their parameters)
      44       55395 :   if (_app.constructingMeshGenerators())
      45         244 :     createMeshGenerator(name);
      46             : 
      47       55391 :   if (type == "BreakMeshByBlockGenerator")
      48         268 :     _has_bmbb = true;
      49       55391 : }
      50             : 
      51             : const MeshGenerator &
      52         111 : MeshGeneratorSystem::appendMeshGenerator(const std::string & type,
      53             :                                          const std::string & name,
      54             :                                          InputParameters params)
      55             : {
      56         111 :   if (!appendingMeshGenerators())
      57           4 :     mooseError("Can only call appendMeshGenerator() during the append_mesh_generator task");
      58         107 :   const auto param_name_mg_name_pairs = getMeshGeneratorParamDependencies(params, true);
      59             : 
      60             :   // Make sure this mesh generator has one and _only_ one input, in the "input" parameter,
      61             :   // Or several, listed in the "inputs" parameter
      62         210 :   if ((param_name_mg_name_pairs.size() == 0) ||
      63         137 :       (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first != "input" &&
      64         296 :        param_name_mg_name_pairs[0].first != "inputs") ||
      65         176 :       (param_name_mg_name_pairs.size() > 1 && param_name_mg_name_pairs[0].first != "inputs"))
      66           4 :     mooseError("While adding ",
      67             :                type,
      68             :                " '",
      69             :                name,
      70             :                "' via appendMeshGenerator():\nCan only append a mesh generator that takes a "
      71             :                "single input mesh generator via the parameter named 'input' or 'inputs'.");
      72             : 
      73             :   // If no final generator is set, we need to make sure that we have one; we will hit
      74             :   // this the first time we add an appended MeshGenerator and only need to do it once.
      75             :   // We'll then generate the final ordering within the execution phase. We'll also
      76             :   // clear the ordering because it could be invalid if we append any more generators,
      77             :   // and we'll be re-ordering within executeMeshgenerators() anyway (where we don't
      78             :   // keep track of any state for the sake of simpler logic)
      79         103 :   if (_final_generator_name.empty())
      80             :   {
      81          17 :     if (_mesh_generators.empty())
      82           4 :       mooseError("Cannot use appendMeshGenerator() because there is not a generator to append to!");
      83             : 
      84          13 :     createMeshGeneratorOrder();
      85          13 :     _ordered_mesh_generators.clear();
      86             :   }
      87             : 
      88             :   // Set the final generator as the input if a single generator
      89             :   mooseAssert(hasMeshGenerator(_final_generator_name), "Missing final generator");
      90          99 :   if (params.have_parameter<MeshGeneratorName>("input"))
      91          13 :     params.set<MeshGeneratorName>("input") = _final_generator_name;
      92             :   // We'll trust the final combiner generator with its list of inputs
      93             : 
      94             :   // Keep track of the new final generator
      95          99 :   _final_generator_name = name;
      96             : 
      97             :   // Need to add this to the param map so that createMeshGenerator can use it
      98             :   mooseAssert(!_mesh_generator_params.count(name), "Already exists");
      99          99 :   _mesh_generator_params.emplace(
     100          99 :       std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
     101             : 
     102         198 :   return *createMeshGenerator(name);
     103          99 : }
     104             : 
     105             : std::vector<std::pair<std::string, MeshGeneratorName>>
     106      110084 : MeshGeneratorSystem::getMeshGeneratorParamDependencies(const InputParameters & params,
     107             :                                                        const bool allow_empty /* = false */) const
     108             : {
     109      110084 :   std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
     110             : 
     111             :   auto add_dependency =
     112      122485 :       [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
     113             :   {
     114       61234 :     if (dependency.size() || allow_empty)
     115       59318 :       dependencies.emplace_back(param_name, dependency);
     116      171318 :   };
     117             : 
     118     4094721 :   for (const auto & [name, param] : params)
     119     3984637 :     if (const auto dependency =
     120     3984637 :             dynamic_cast<const Parameters::Parameter<MeshGeneratorName> *>(param.get()))
     121       52110 :       add_dependency(name, dependency->get());
     122     3932527 :     else if (const auto dependencies =
     123     3932527 :                  dynamic_cast<const Parameters::Parameter<std::vector<MeshGeneratorName>> *>(
     124     7865054 :                      param.get()))
     125             :     {
     126        3786 :       if (allow_empty && dependencies->get().empty())
     127           0 :         add_dependency(name, std::string());
     128       12910 :       for (const auto & dependency : dependencies->get())
     129        9124 :         add_dependency(name, dependency);
     130             :     }
     131             : 
     132      220168 :   return dependencies;
     133           0 : }
     134             : 
     135             : void
     136       66684 : MeshGeneratorSystem::createAddedMeshGenerators()
     137             : {
     138             :   mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "create_added_mesh_generators",
     139             :               "Should not run now");
     140             : 
     141             :   // No generators were added via addMeshGenerator()
     142       66684 :   if (_mesh_generator_params.empty())
     143       41173 :     return;
     144             : 
     145       25511 :   DependencyResolver<std::string> resolver;
     146             : 
     147             :   // Define the dependencies known so far
     148       80658 :   for (const auto & [name, type_params_pair] : _mesh_generator_params)
     149             :   {
     150       55147 :     resolver.addItem(name);
     151       55147 :     for (const auto & param_dependency_pair :
     152      139913 :          getMeshGeneratorParamDependencies(type_params_pair.second))
     153       84766 :       resolver.addEdge(param_dependency_pair.second, name);
     154             :   }
     155             : 
     156       25511 :   std::vector<std::vector<std::string>> ordered_generators;
     157             :   try
     158             :   {
     159       25511 :     ordered_generators = resolver.getSortedValuesSets();
     160             :   }
     161           4 :   catch (CyclicDependencyException<std::string> & e)
     162             :   {
     163           4 :     mooseError("Cyclic dependencies detected in mesh generation: ",
     164           4 :                MooseUtils::join(e.getCyclicDependencies(), " <- "));
     165           0 :   }
     166             : 
     167       25507 :   const auto & moose_mesh = _app.actionWarehouse().getMesh();
     168             : 
     169             :   // If there is no mesh
     170       25507 :   if (!moose_mesh.get())
     171           0 :     mooseError("No mesh created. Either add a Mesh, an ActionComponents or a Components block");
     172             : 
     173             :   // If we're using data-driven generation, find that requirement now
     174             :   mooseAssert(!_data_driven_generator_name, "Should not be set");
     175       50958 :   if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
     176       25451 :       moose_mesh->isParamValid(data_driven_generator_param))
     177             :   {
     178          38 :     if (!hasDataDrivenAllowed())
     179           4 :       moose_mesh->paramError(
     180             :           data_driven_generator_param,
     181             :           "This application does not support data-driven mesh generation.\n\nThis generation is an "
     182             :           "advanced feature and must be enabled on the application via the '",
     183             :           allow_data_driven_param,
     184             :           "' parameter.");
     185             : 
     186             :     mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
     187             :                 "Assumption for mesh type is now invalid");
     188             : 
     189          34 :     _data_driven_generator_name = moose_mesh->getParam<std::string>(data_driven_generator_param);
     190          34 :     if (!_mesh_generator_params.count(*_data_driven_generator_name))
     191           8 :       moose_mesh->paramError(data_driven_generator_param,
     192             :                              "The data driven generator '",
     193           4 :                              *_data_driven_generator_name,
     194             :                              "' does not exist");
     195             :   }
     196             : 
     197             :   // Construct all of the mesh generators that we know exist
     198       76239 :   for (const auto & generator_names : ordered_generators)
     199      105612 :     for (const auto & generator_name : generator_names)
     200       54872 :       if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
     201             :       {
     202       54839 :         auto & params = it->second.second;
     203             : 
     204             :         // Determine now if we need to run this in data only mode
     205          82 :         const bool data_only = _data_driven_generator_name &&
     206       54921 :                                getDataDrivenGeneratorName() != generator_name &&
     207          60 :                                resolver.dependsOn(getDataDrivenGeneratorName(), generator_name);
     208       54839 :         params.set<bool>(MeshGenerator::data_only_param) = data_only;
     209             : 
     210       54839 :         createMeshGenerator(generator_name);
     211             : 
     212             :         mooseAssert(data_only == getMeshGenerator(generator_name).isDataOnly(),
     213             :                     "Inconsistent data only");
     214             :       }
     215             : 
     216             :   mooseAssert(_mesh_generator_params.empty(), "Should be empty");
     217             :   mooseAssert(_final_generator_name.empty(), "Should be unset at this point");
     218             : 
     219             :   // Set the final generator if we have one set by the user
     220             :   // and if so make sure it also exists
     221       50222 :   if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
     222       50222 :       moose_mesh->isParamValid("final_generator"))
     223             :   {
     224             :     mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
     225             :                 "Assumption for mesh type is now invalid");
     226             : 
     227         439 :     _final_generator_name = moose_mesh->getParam<std::string>("final_generator");
     228         439 :     if (!hasMeshGenerator(_final_generator_name))
     229           8 :       moose_mesh->paramError("final_generator",
     230             :                              "The forced final MeshGenerator '",
     231           4 :                              _final_generator_name,
     232             :                              "' does not exist");
     233             :   }
     234       25135 : }
     235             : 
     236             : void
     237       24188 : MeshGeneratorSystem::createMeshGeneratorOrder()
     238             : {
     239             :   mooseAssert(_app.constructingMeshGenerators() ||
     240             :                   _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
     241             :               "Incorrect call time");
     242             :   mooseAssert(_ordered_mesh_generators.empty(), "Already ordered");
     243             :   mooseAssert(_mesh_generators.size(), "No mesh generators to order");
     244             : 
     245       24188 :   TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
     246             : 
     247             :   // We dare not sort these based on address!
     248       24188 :   DependencyResolver<MeshGenerator *, MeshGenerator::Comparator> resolver;
     249             : 
     250             :   // The mesh generators that must be called
     251             :   // This is needed to mark the generators that could be cut due to a
     252             :   // final generator being set, but should still be called because they're
     253             :   // either being saved in memory or as output
     254       24188 :   std::vector<std::string> required_generators;
     255       76753 :   for (const auto & it : _mesh_generators)
     256       52565 :     if (it.second->hasSaveMesh() || it.second->hasOutput())
     257         396 :       required_generators.push_back(it.second->name());
     258             : 
     259             :   // The mesh generator tree should have all the mesh generators that
     260             :   // The final generator depends on and all the mesh generators
     261             :   // with 'save in' flag. Here we loop over all the mesh generators
     262             :   // and conditionally add all of the dependencies into the resolver
     263       76753 :   for (const auto & it : _mesh_generators)
     264             :   {
     265       52565 :     MeshGenerator * mg = it.second.get();
     266             : 
     267             :     // The mesh generator has to meet one of the following conditions:
     268             :     // Final mesh generator is not set, so we build the whole tree
     269        2547 :     if (_final_generator_name.empty() ||
     270             :         // This mesh generator is the final generator
     271        2547 :         mg->name() == _final_generator_name ||
     272             :         // This needs to be saved or output
     273        4030 :         mg->hasSaveMesh() || mg->hasOutput() ||
     274             :         // Final mesh generator set and is a child of this generator
     275      110313 :         (_final_generator_name.size() && mg->isChildMeshGenerator(_final_generator_name, false)) ||
     276             :         // This is a dependency of a generator that needs to be saved or output
     277         716 :         std::find_if(required_generators.begin(),
     278             :                      required_generators.end(),
     279        1273 :                      [&mg](const auto & name) { return mg->isChildMeshGenerator(name, false); }) !=
     280       53281 :             required_generators.end())
     281             :     {
     282       52076 :       resolver.addItem(mg);
     283       80176 :       for (const auto & dep_mg : mg->getParentMeshGenerators())
     284       28100 :         resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
     285             :     }
     286             :   }
     287             : 
     288             :   // ...and sort them
     289             :   try
     290             :   {
     291       24188 :     _ordered_mesh_generators = resolver.getSortedValuesSets();
     292             :   }
     293             :   // It is _quite_ hard to trigger this to test it. I've tried to no avail.
     294             :   // Now that we...
     295             :   // - check and sort up front
     296             :   // - know if dependencies exist at the time of requesting them
     297             :   // - require that sub generators depend only on other sub generators in an object's
     298             :   //   tree + input dependencies that we explicitly declare
     299             :   // I don't think it's possible. But we'll leave it here anyway and it
     300             :   // definitely will not be covered
     301           0 :   catch (CyclicDependencyException<MeshGenerator *, MeshGenerator::Comparator> & e)
     302             :   {
     303           0 :     const auto & cycle = e.getCyclicDependencies();
     304           0 :     std::vector<std::string> names(cycle.size());
     305           0 :     for (const auto i : index_range(cycle))
     306           0 :       names[i] = cycle[i]->name();
     307             : 
     308           0 :     mooseError("Cyclic dependencies detected in mesh generation: ",
     309           0 :                MooseUtils::join(names, " <- "));
     310           0 :   }
     311             : 
     312             :   mooseAssert(_ordered_mesh_generators.size(), "No mesh generators found");
     313             : 
     314       24188 :   const auto & final_generators = _ordered_mesh_generators.back();
     315             : 
     316             :   // We haven't forced a final generator yet
     317       24188 :   if (_final_generator_name.empty())
     318             :   {
     319             :     mooseAssert(final_generators.size(), "Empty vector");
     320             : 
     321             :     // See if we have multiple independent trees of generators
     322       23751 :     const auto ancestor_list = resolver.getAncestors(final_generators.back());
     323       23751 :     if (ancestor_list.size() != resolver.size() && _final_generator_name.empty())
     324             :     {
     325             :       // Need to remove duplicates and possibly perform a difference so we'll import our list
     326             :       // into a set for these operations.
     327             :       std::set<MeshGenerator *, MeshGenerator::Comparator> ancestors(ancestor_list.begin(),
     328           8 :                                                                      ancestor_list.end());
     329             :       // Get all of the items from the resolver so we can compare against the tree from the
     330             :       // final generator we just pulled.
     331           8 :       const auto & allValues = resolver.getSortedValues();
     332           8 :       decltype(ancestors) all(allValues.begin(), allValues.end());
     333             : 
     334           8 :       decltype(ancestors) ind_tree;
     335           8 :       std::set_difference(all.begin(),
     336             :                           all.end(),
     337             :                           ancestors.begin(),
     338             :                           ancestors.end(),
     339             :                           std::inserter(ind_tree, ind_tree.end()));
     340             : 
     341           8 :       std::ostringstream oss;
     342             :       oss << "Your MeshGenerator tree contains multiple possible generator outputs :\n\""
     343          24 :           << final_generators.back()->name()
     344           8 :           << "\" and one or more of the following from an independent set: \"";
     345           8 :       bool first = true;
     346          28 :       for (const auto & gen : ind_tree)
     347             :       {
     348          20 :         if (!first)
     349          12 :           oss << ", ";
     350             :         else
     351           8 :           first = false;
     352             : 
     353          20 :         oss << gen->name();
     354             :       }
     355             :       oss << "\"\n\nThis may be due to a missing dependency or may be intentional. Please either\n"
     356             :              "- check that all the mesh generators are connected as a tree and culminate in a "
     357             :              "single final mesh. Having one wrong 'input=mg' parameter is the most common error\n"
     358             :              "- add additional dependencies to remove the ambiguity if you are using a user-built "
     359             :              "MeshGenerator\n"
     360             :              "- if you intend to execute a subset of the defined generators (uncommon), select the"
     361           8 :              " final MeshGenerator in the [Mesh] block with the \"final_generator\" parameter.";
     362           8 :       mooseError(oss.str());
     363           0 :     }
     364             : 
     365       23743 :     _final_generator_name = final_generators.back()->name();
     366       23743 :   }
     367             :   else
     368             :     mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
     369       24180 : }
     370             : 
     371             : void
     372       62232 : MeshGeneratorSystem::executeMeshGenerators()
     373             : {
     374             :   libmesh_parallel_only(comm());
     375             : 
     376             :   // we do not need to do this when there are no mesh generators
     377       62232 :   if (_mesh_generators.empty())
     378       38057 :     return;
     379             : 
     380             :   // Order the generators
     381       24175 :   createMeshGeneratorOrder();
     382             : 
     383             :   // Save all meshes marked to to_save_in_meshes and save in error checking
     384       24167 :   std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
     385       72670 :   for (const auto & generator_set : _ordered_mesh_generators)
     386      100538 :     for (const auto & generator : generator_set)
     387       52035 :       if (generator->hasSaveMesh())
     388             :       {
     389          45 :         if (_final_generator_name == generator->name())
     390           4 :           generator->paramError("save_with_name",
     391             :                                 "Cannot use the save in capability with the final mesh generator");
     392          41 :         to_save_in_meshes.emplace(generator->getSavedMeshName(),
     393          82 :                                   &getMeshGeneratorOutput(generator->name()));
     394             :       }
     395             :   // Grab the outputs from the final generator so MeshGeneratorMesh can pick it up
     396       24163 :   to_save_in_meshes.emplace(mainMeshGeneratorName(),
     397       48326 :                             &getMeshGeneratorOutput(_final_generator_name));
     398             : 
     399             :   // Run the MeshGenerators in the proper order
     400       72194 :   for (const auto & generator_set : _ordered_mesh_generators)
     401             :   {
     402      100034 :     for (const auto & generator : generator_set)
     403             :     {
     404       52003 :       const auto & name = generator->name();
     405       52003 :       if (_verbose)
     406           0 :         _app._console << " [DBG] Executing mesh generator (" << COLOR_GREEN << std::setw(20) << name
     407           0 :                       << COLOR_DEFAULT << ") in type (" << COLOR_GREEN << generator->type()
     408           0 :                       << COLOR_DEFAULT << ")" << std::endl;
     409       52003 :       auto current_mesh = generator->generateInternal();
     410             : 
     411             :       // Only generating data for this generator
     412       51551 :       if (generator->isDataOnly())
     413             :       {
     414             :         mooseAssert(!current_mesh, "Should not have a mesh");
     415          33 :         continue;
     416             :       }
     417             : 
     418             : #ifdef DEBUG
     419             :       // Assert that the mesh is either marked as not prepared or if it is marked as prepared,
     420             :       // that it's *actually* prepared
     421             :       if (!_has_bmbb && !MeshTools::valid_is_prepared(*current_mesh))
     422             :         generator->mooseError("The generated mesh is marked as prepared but is not actually "
     423             :                               "prepared. Please edit the '",
     424             :                               generator->type(),
     425             :                               "' class to call 'set_isnt_prepared()'");
     426             : #endif
     427             : 
     428             :       // Now we need to possibly give this mesh to downstream generators
     429       51518 :       auto & outputs = _mesh_generator_outputs[name];
     430             : 
     431       51518 :       if (outputs.size())
     432             :       {
     433       51373 :         auto & first_output = *outputs.begin();
     434             : 
     435       51373 :         first_output = std::move(current_mesh);
     436             : 
     437       51373 :         const auto & copy_from = *first_output;
     438             : 
     439       51373 :         auto output_it = ++outputs.begin();
     440             : 
     441             :         // For all of the rest we need to make a copy
     442       51879 :         for (; output_it != outputs.end(); ++output_it)
     443         506 :           (*output_it) = copy_from.clone();
     444             :       }
     445       51551 :     }
     446             :   }
     447             : 
     448             :   // Grab all the valid save in meshes from the temporary map to_save_in_meshes
     449             :   // and store them in _save_in_meshes
     450       47463 :   for (auto & [name, mesh_ptr] : to_save_in_meshes)
     451             :   {
     452             :     mooseAssert(mesh_ptr, "Invalid pointer");
     453             :     mooseAssert(*mesh_ptr, "Invalid pointer");
     454       23752 :     if (name != mainMeshGeneratorName())
     455             :       mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
     456       23752 :     _save_in_meshes[name] = std::move(*mesh_ptr);
     457             :   }
     458       23723 : }
     459             : 
     460             : std::shared_ptr<MeshGenerator>
     461       55182 : MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
     462             : {
     463             :   libmesh_parallel_only(comm());
     464             :   mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
     465             : 
     466       55182 :   const auto find_params = _mesh_generator_params.find(generator_name);
     467             :   mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
     468       55182 :   const auto & [type, params] = find_params->second;
     469             :   mooseAssert(comm().verify(type + generator_name), "Inconsistent construction order");
     470             : 
     471             :   std::shared_ptr<MeshGenerator> mg =
     472       55182 :       _app.getFactory().create<MeshGenerator>(type, generator_name, params);
     473             : 
     474       54834 :   if (mg->hasSaveMesh())
     475             :   {
     476          55 :     if (_save_in_meshes.count(mg->getSavedMeshName()))
     477           8 :       mg->paramError("save_with_name",
     478             :                      "The save with name '",
     479           4 :                      mg->getSavedMeshName(),
     480             :                      "' has already been used");
     481          51 :     _save_in_meshes.emplace(mg->getSavedMeshName(), nullptr);
     482             :   }
     483             : 
     484             :   // Setup the children and parents
     485       84351 :   for (const auto & dependency : mg->getRequestedMeshGenerators())
     486             :   {
     487             :     // We _shouldn't_ hit this; now that we enforce construction ordering we do
     488             :     // all of this error checking at construction time because the info is available
     489             :     mooseAssert(hasMeshGenerator(dependency), "Missing dependency");
     490             : 
     491       29521 :     auto & dependency_mg = getMeshGeneratorInternal(dependency);
     492       29521 :     mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
     493       29521 :     dependency_mg.addChildMeshGenerator(*mg, MeshGenerator::AddParentChildKey());
     494             :   }
     495             : 
     496             :   // Loop through all of the MeshGeneratorName and std::vector<MeshGeneratorName>
     497             :   // parameters (meshes that we should depend on), and make sure that either:
     498             :   // - We directly depend on them and requested a mesh from them
     499             :   // - We created a sub generator that depends on them and we declared it
     500       84281 :   for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
     501             :   {
     502       29463 :     const auto & param_name = param_dependency_pair.first;
     503       29463 :     const auto & dependency_name = param_dependency_pair.second;
     504             : 
     505       29463 :     if (mg->isNullMeshName(dependency_name))
     506       29424 :       continue;
     507             : 
     508             :     // True if this dependency was requested and is a parent
     509       29437 :     if (mg->isParentMeshGenerator(dependency_name))
     510             :     {
     511             :       mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
     512       29398 :       continue;
     513             :     }
     514             : 
     515             :     // Whether or not this is a dependency of at least one SubGenerator
     516          39 :     auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
     517          39 :                                             mg->getSubMeshGenerators().end(),
     518          97 :                                             [&dependency_name](const auto & mg)
     519          97 :                                             { return mg->isParentMeshGenerator(dependency_name); });
     520          39 :     const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
     521             : 
     522             :     // This should be used by a sub generator
     523          39 :     if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
     524             :     {
     525          31 :       if (!is_sub_dependency)
     526           4 :         mg->mooseError("The sub generator dependency declared from MeshGenerator '",
     527             :                        dependency_name,
     528             :                        "' from the parameter '",
     529             :                        param_name,
     530             :                        "' was not used.\n\nDependencies that are declared by declareMeshForSub() "
     531             :                        "must be used as an input to a sub generator created by this object.");
     532             :     }
     533             :     // This was used by a sub generator but wasn't declared
     534           8 :     else if (is_sub_dependency)
     535           8 :       mg->mooseError(
     536             :           "The MeshGenerator '",
     537             :           dependency_name,
     538             :           "' was referenced in the parameter '",
     539             :           param_name,
     540             :           "' and used in the sub generator ",
     541           4 :           (*find_sub_dependency)->type(),
     542             :           " '",
     543           4 :           (*find_sub_dependency)->name(),
     544             :           "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
     545           4 :           mg->type(),
     546             :           " to include a call to declareMesh(es)ForSub(\"",
     547             :           param_name,
     548             :           "\") in the constructor.");
     549             :     // Isn't used at all
     550             :     else
     551           4 :       mg->mooseError(
     552             :           "You failed to request the generated mesh(es) for the parameter '",
     553             :           param_name,
     554             :           "'.\n\nIn specific, the mesh from MeshGenerator '",
     555             :           dependency_name,
     556             :           "' was not requested.\n\nTo correct this, you should remove the parameter if the "
     557             :           "mesh(es)\nare not needed, or request the mesh(es) with getMesh()/getMeshes().");
     558       54818 :   }
     559             : 
     560             :   mooseAssert(!_mesh_generators.count(generator_name), "Already created");
     561       54818 :   _mesh_generators.emplace(generator_name, mg);
     562             :   mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
     563       54818 :   _mesh_generator_outputs[generator_name];
     564       54818 :   _mesh_generator_params.erase(find_params);
     565             : 
     566      109636 :   return mg;
     567           0 : }
     568             : 
     569             : std::unique_ptr<MeshBase> &
     570       53973 : MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
     571             : {
     572             :   mooseAssert(_app.constructingMeshGenerators() ||
     573             :                   _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
     574             :               "Incorrect call time");
     575             : 
     576       53973 :   auto it = _mesh_generator_outputs.find(name);
     577             :   mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
     578       53973 :   it->second.push_back(nullptr);
     579      107946 :   return it->second.back();
     580             : }
     581             : 
     582             : bool
     583       59440 : MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
     584             : {
     585       59440 :   return _mesh_generators.count(name);
     586             : }
     587             : 
     588             : bool
     589          20 : MeshGeneratorSystem::hasMeshGeneratorParams(const MeshGeneratorName & name) const
     590             : {
     591          20 :   return _mesh_generator_params.count(name);
     592             : }
     593             : 
     594             : const MeshGenerator &
     595       57852 : MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
     596             : {
     597       57852 :   const auto it = _mesh_generators.find(name);
     598       57852 :   if (it == _mesh_generators.end())
     599           4 :     mooseError("Failed to find a MeshGenerator with the name '", name, "'");
     600             :   mooseAssert(it->second, "Invalid shared pointer");
     601      115696 :   return *it->second;
     602             : }
     603             : 
     604             : std::vector<std::string>
     605      106493 : MeshGeneratorSystem::getMeshGeneratorNames() const
     606             : {
     607      106493 :   std::vector<std::string> names;
     608      162465 :   for (auto & pair : _mesh_generators)
     609       55972 :     names.push_back(pair.first);
     610      106493 :   return names;
     611           0 : }
     612             : 
     613             : std::vector<std::string>
     614          17 : MeshGeneratorSystem::getSavedMeshNames() const
     615             : {
     616          17 :   std::vector<std::string> names;
     617          51 :   for (auto & pair : _save_in_meshes)
     618          34 :     names.push_back(pair.first);
     619          17 :   return names;
     620           0 : }
     621             : 
     622             : std::unique_ptr<MeshBase>
     623       23736 : MeshGeneratorSystem::getSavedMesh(const std::string & name)
     624             : {
     625       23736 :   auto find_mesh = _save_in_meshes.find(name);
     626       23736 :   if (find_mesh == _save_in_meshes.end())
     627           4 :     mooseError("Failed to find a saved mesh with the name '", name, "'");
     628             : 
     629       23732 :   auto & mesh_unique_ptr = find_mesh->second;
     630       23732 :   if (!mesh_unique_ptr)
     631           4 :     mooseError("While getting the saved mesh generator '",
     632             :                name,
     633             :                "', said mesh has already been retrieved");
     634             : 
     635       47456 :   return std::move(mesh_unique_ptr);
     636             : }
     637             : 
     638             : bool
     639       55827 : MeshGeneratorSystem::appendingMeshGenerators() const
     640             : {
     641       55827 :   return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
     642             : }
     643             : 
     644             : bool
     645          38 : MeshGeneratorSystem::hasDataDrivenAllowed() const
     646             : {
     647          38 :   return _app.parameters().get<bool>(allow_data_driven_param);
     648             : }
     649             : 
     650             : const std::string &
     651         150 : MeshGeneratorSystem::getDataDrivenGeneratorName() const
     652             : {
     653             :   mooseAssert(_data_driven_generator_name, "Not set");
     654         150 :   return *_data_driven_generator_name;
     655             : }
     656             : 
     657             : void
     658           8 : MeshGeneratorSystem::dataDrivenError(const MeshGenerator & generator,
     659             :                                      const std::string & message) const
     660             : {
     661           8 :   const auto & moose_mesh = _app.actionWarehouse().getMesh();
     662          16 :   moose_mesh->paramError(data_driven_generator_param,
     663             :                          "The generator '",
     664           8 :                          getDataDrivenGeneratorName(),
     665             :                          "' cannot be used in data-driven mode because the parent ",
     666           8 :                          generator.typeAndName(),
     667             :                          " ",
     668             :                          message);
     669             : }

Generated by: LCOV version 1.14