LCOV - code coverage report
Current view: top level - src/base - MeshGeneratorSystem.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 249 268 92.9 %
Date: 2025-07-17 01:28:37 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       62755 : MeshGeneratorSystem::MeshGeneratorSystem(MooseApp & app)
      25             :   : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
      26             :     ParallelObject(app),
      27       62755 :     _app(app),
      28       62755 :     _has_bmbb(false),
      29       62755 :     _verbose(false)
      30             : {
      31       62755 : }
      32             : 
      33             : void
      34       51231 : 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       51231 :   _mesh_generator_params.emplace(
      40       51231 :       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       51231 :   if (_app.constructingMeshGenerators())
      45         224 :     createMeshGenerator(name);
      46             : 
      47       51227 :   if (type == "BreakMeshByBlockGenerator")
      48         236 :     _has_bmbb = true;
      49       51227 : }
      50             : 
      51             : const MeshGenerator &
      52         104 : MeshGeneratorSystem::appendMeshGenerator(const std::string & type,
      53             :                                          const std::string & name,
      54             :                                          InputParameters params)
      55             : {
      56         104 :   if (!appendingMeshGenerators())
      57           4 :     mooseError("Can only call appendMeshGenerator() during the append_mesh_generator task");
      58         100 :   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         196 :   if ((param_name_mg_name_pairs.size() == 0) ||
      63         136 :       (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first != "input" &&
      64         276 :        param_name_mg_name_pairs[0].first != "inputs") ||
      65         164 :       (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          96 :   if (_final_generator_name.empty())
      80             :   {
      81          16 :     if (_mesh_generators.empty())
      82           4 :       mooseError("Cannot use appendMeshGenerator() because there is not a generator to append to!");
      83             : 
      84          12 :     createMeshGeneratorOrder();
      85          12 :     _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          92 :   if (params.have_parameter<MeshGeneratorName>("input"))
      91          12 :     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          92 :   _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          92 :   _mesh_generator_params.emplace(
     100          92 :       std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
     101             : 
     102         184 :   return *createMeshGenerator(name);
     103          92 : }
     104             : 
     105             : std::vector<std::pair<std::string, MeshGeneratorName>>
     106      101762 : MeshGeneratorSystem::getMeshGeneratorParamDependencies(const InputParameters & params,
     107             :                                                        const bool allow_empty /* = false */) const
     108             : {
     109      101762 :   std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
     110             : 
     111             :   auto add_dependency =
     112      113424 :       [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
     113             :   {
     114       56704 :     if (dependency.size() || allow_empty)
     115       54912 :       dependencies.emplace_back(param_name, dependency);
     116      158466 :   };
     117             : 
     118     3781244 :   for (const auto & [name, param] : params)
     119     3679482 :     if (const auto dependency =
     120     3679482 :             dynamic_cast<const Parameters::Parameter<MeshGeneratorName> *>(param.get()))
     121       48404 :       add_dependency(name, dependency->get());
     122     3631078 :     else if (const auto dependencies =
     123     3631078 :                  dynamic_cast<const Parameters::Parameter<std::vector<MeshGeneratorName>> *>(
     124     7262156 :                      param.get()))
     125             :     {
     126        3468 :       if (allow_empty && dependencies->get().empty())
     127           0 :         add_dependency(name, std::string());
     128       11768 :       for (const auto & dependency : dependencies->get())
     129        8300 :         add_dependency(name, dependency);
     130             :     }
     131             : 
     132      203524 :   return dependencies;
     133           0 : }
     134             : 
     135             : void
     136       61831 : 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       61831 :   if (_mesh_generator_params.empty())
     143       38281 :     return;
     144             : 
     145       23550 :   DependencyResolver<std::string> resolver;
     146             : 
     147             :   // Define the dependencies known so far
     148       74553 :   for (const auto & [name, type_params_pair] : _mesh_generator_params)
     149             :   {
     150       51003 :     resolver.addItem(name);
     151       51003 :     for (const auto & param_dependency_pair :
     152      129447 :          getMeshGeneratorParamDependencies(type_params_pair.second))
     153       78444 :       resolver.addEdge(param_dependency_pair.second, name);
     154             :   }
     155             : 
     156       23550 :   std::vector<std::vector<std::string>> ordered_generators;
     157             :   try
     158             :   {
     159       23550 :     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       23546 :   const auto & moose_mesh = _app.actionWarehouse().getMesh();
     168             : 
     169             :   // If there is no mesh
     170       23546 :   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       47041 :   if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
     176       23495 :       moose_mesh->isParamValid(data_driven_generator_param))
     177             :   {
     178          36 :     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          32 :     _data_driven_generator_name = moose_mesh->getParam<std::string>(data_driven_generator_param);
     190          32 :     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       70467 :   for (const auto & generator_names : ordered_generators)
     199       97656 :     for (const auto & generator_name : generator_names)
     200       50727 :       if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
     201             :       {
     202       50695 :         auto & params = it->second.second;
     203             : 
     204             :         // Determine now if we need to run this in data only mode
     205          76 :         const bool data_only = _data_driven_generator_name &&
     206       50771 :                                getDataDrivenGeneratorName() != generator_name &&
     207          56 :                                resolver.dependsOn(getDataDrivenGeneratorName(), generator_name);
     208       50695 :         params.set<bool>(MeshGenerator::data_only_param) = data_only;
     209             : 
     210       50695 :         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       46305 :   if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
     222       46305 :       moose_mesh->isParamValid("final_generator"))
     223             :   {
     224             :     mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
     225             :                 "Assumption for mesh type is now invalid");
     226             : 
     227         402 :     _final_generator_name = moose_mesh->getParam<std::string>("final_generator");
     228         402 :     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       23174 : }
     235             : 
     236             : void
     237       22236 : 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       22236 :   TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
     246             : 
     247             :   // We dare not sort these based on address!
     248       22236 :   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       22236 :   std::vector<std::string> required_generators;
     255       70645 :   for (const auto & it : _mesh_generators)
     256       48409 :     if (it.second->hasSaveMesh() || it.second->hasOutput())
     257         361 :       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       70645 :   for (const auto & it : _mesh_generators)
     264             :   {
     265       48409 :     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        2325 :     if (_final_generator_name.empty() ||
     270             :         // This mesh generator is the final generator
     271        2325 :         mg->name() == _final_generator_name ||
     272             :         // This needs to be saved or output
     273        3680 :         mg->hasSaveMesh() || mg->hasOutput() ||
     274             :         // Final mesh generator set and is a child of this generator
     275      101547 :         (_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         650 :         std::find_if(required_generators.begin(),
     278             :                      required_generators.end(),
     279        1154 :                      [&mg](const auto & name) { return mg->isChildMeshGenerator(name, false); }) !=
     280       49059 :             required_generators.end())
     281             :     {
     282       47963 :       resolver.addItem(mg);
     283       73886 :       for (const auto & dep_mg : mg->getParentMeshGenerators())
     284       25923 :         resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
     285             :     }
     286             :   }
     287             : 
     288             :   // ...and sort them
     289             :   try
     290             :   {
     291       22236 :     _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       22236 :   const auto & final_generators = _ordered_mesh_generators.back();
     315             : 
     316             :   // We haven't forced a final generator yet
     317       22236 :   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       21837 :     const auto ancestor_list = resolver.getAncestors(final_generators.back());
     323       21837 :     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          29 :       for (const auto & gen : ind_tree)
     347             :       {
     348          21 :         if (!first)
     349          13 :           oss << ", ";
     350             :         else
     351           8 :           first = false;
     352             : 
     353          21 :         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       21829 :     _final_generator_name = final_generators.back()->name();
     366       21829 :   }
     367             :   else
     368             :     mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
     369       22228 : }
     370             : 
     371             : void
     372       57480 : MeshGeneratorSystem::executeMeshGenerators()
     373             : {
     374             :   libmesh_parallel_only(comm());
     375             : 
     376             :   // we do not need to do this when there are no mesh generators
     377       57480 :   if (_mesh_generators.empty())
     378       35256 :     return;
     379             : 
     380             :   // Order the generators
     381       22224 :   createMeshGeneratorOrder();
     382             : 
     383             :   // Save all meshes marked to to_save_in_meshes and save in error checking
     384       22216 :   std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
     385       66926 :   for (const auto & generator_set : _ordered_mesh_generators)
     386       92633 :     for (const auto & generator : generator_set)
     387       47923 :       if (generator->hasSaveMesh())
     388             :       {
     389          42 :         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          38 :         to_save_in_meshes.emplace(generator->getSavedMeshName(),
     393          76 :                                   &getMeshGeneratorOutput(generator->name()));
     394             :       }
     395             :   // Grab the outputs from the final generator so MeshGeneratorMesh can pick it up
     396       22212 :   to_save_in_meshes.emplace(mainMeshGeneratorName(),
     397       44424 :                             &getMeshGeneratorOutput(_final_generator_name));
     398             : 
     399             :   // Run the MeshGenerators in the proper order
     400       66450 :   for (const auto & generator_set : _ordered_mesh_generators)
     401             :   {
     402       92129 :     for (const auto & generator : generator_set)
     403             :     {
     404       47891 :       const auto & name = generator->name();
     405       47891 :       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       47891 :       auto current_mesh = generator->generateInternal();
     410             : 
     411             :       // Only generating data for this generator
     412       47439 :       if (generator->isDataOnly())
     413             :       {
     414             :         mooseAssert(!current_mesh, "Should not have a mesh");
     415          30 :         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       47409 :       auto & outputs = _mesh_generator_outputs[name];
     430             : 
     431       47409 :       if (outputs.size())
     432             :       {
     433       47279 :         auto & first_output = *outputs.begin();
     434             : 
     435       47279 :         first_output = std::move(current_mesh);
     436             : 
     437       47279 :         const auto & copy_from = *first_output;
     438             : 
     439       47279 :         auto output_it = ++outputs.begin();
     440             : 
     441             :         // For all of the rest we need to make a copy
     442       47743 :         for (; output_it != outputs.end(); ++output_it)
     443         464 :           (*output_it) = copy_from.clone();
     444             :       }
     445       47439 :     }
     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       43558 :   for (auto & [name, mesh_ptr] : to_save_in_meshes)
     451             :   {
     452             :     mooseAssert(mesh_ptr, "Invalid pointer");
     453             :     mooseAssert(*mesh_ptr, "Invalid pointer");
     454       21798 :     if (name != mainMeshGeneratorName())
     455             :       mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
     456       21798 :     _save_in_meshes[name] = std::move(*mesh_ptr);
     457             :   }
     458       21772 : }
     459             : 
     460             : std::shared_ptr<MeshGenerator>
     461       51011 : MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
     462             : {
     463             :   libmesh_parallel_only(comm());
     464             :   mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
     465             : 
     466       51011 :   const auto find_params = _mesh_generator_params.find(generator_name);
     467             :   mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
     468       51011 :   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       51011 :       _app.getFactory().create<MeshGenerator>(type, generator_name, params);
     473             : 
     474       50663 :   if (mg->hasSaveMesh())
     475             :   {
     476          52 :     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          48 :     _save_in_meshes.emplace(mg->getSavedMeshName(), nullptr);
     482             :   }
     483             : 
     484             :   // Setup the children and parents
     485       77964 :   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       27305 :     auto & dependency_mg = getMeshGeneratorInternal(dependency);
     492       27305 :     mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
     493       27305 :     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       77898 :   for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
     501             :   {
     502       27251 :     const auto & param_name = param_dependency_pair.first;
     503       27251 :     const auto & dependency_name = param_dependency_pair.second;
     504             : 
     505       27251 :     if (mg->isNullMeshName(dependency_name))
     506       27215 :       continue;
     507             : 
     508             :     // True if this dependency was requested and is a parent
     509       27227 :     if (mg->isParentMeshGenerator(dependency_name))
     510             :     {
     511             :       mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
     512       27191 :       continue;
     513             :     }
     514             : 
     515             :     // Whether or not this is a dependency of at least one SubGenerator
     516          36 :     auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
     517          36 :                                             mg->getSubMeshGenerators().end(),
     518          88 :                                             [&dependency_name](const auto & mg)
     519          88 :                                             { return mg->isParentMeshGenerator(dependency_name); });
     520          36 :     const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
     521             : 
     522             :     // This should be used by a sub generator
     523          36 :     if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
     524             :     {
     525          28 :       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       50647 :   }
     559             : 
     560             :   mooseAssert(!_mesh_generators.count(generator_name), "Already created");
     561       50647 :   _mesh_generators.emplace(generator_name, mg);
     562             :   mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
     563       50647 :   _mesh_generator_outputs[generator_name];
     564       50647 :   _mesh_generator_params.erase(find_params);
     565             : 
     566      101294 :   return mg;
     567           0 : }
     568             : 
     569             : std::unique_ptr<MeshBase> &
     570       49803 : MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
     571             : {
     572             :   mooseAssert(_app.constructingMeshGenerators() ||
     573             :                   _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
     574             :               "Incorrect call time");
     575             : 
     576       49803 :   auto it = _mesh_generator_outputs.find(name);
     577             :   mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
     578       49803 :   it->second.push_back(nullptr);
     579       99606 :   return it->second.back();
     580             : }
     581             : 
     582             : bool
     583       55006 : MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
     584             : {
     585       55006 :   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       53440 : MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
     596             : {
     597       53440 :   const auto it = _mesh_generators.find(name);
     598       53440 :   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      106872 :   return *it->second;
     602             : }
     603             : 
     604             : std::vector<std::string>
     605       98854 : MeshGeneratorSystem::getMeshGeneratorNames() const
     606             : {
     607       98854 :   std::vector<std::string> names;
     608      150559 :   for (auto & pair : _mesh_generators)
     609       51705 :     names.push_back(pair.first);
     610       98854 :   return names;
     611           0 : }
     612             : 
     613             : std::vector<std::string>
     614          16 : MeshGeneratorSystem::getSavedMeshNames() const
     615             : {
     616          16 :   std::vector<std::string> names;
     617          48 :   for (auto & pair : _save_in_meshes)
     618          32 :     names.push_back(pair.first);
     619          16 :   return names;
     620           0 : }
     621             : 
     622             : std::unique_ptr<MeshBase>
     623       21784 : MeshGeneratorSystem::getSavedMesh(const std::string & name)
     624             : {
     625       21784 :   auto find_mesh = _save_in_meshes.find(name);
     626       21784 :   if (find_mesh == _save_in_meshes.end())
     627           4 :     mooseError("Failed to find a saved mesh with the name '", name, "'");
     628             : 
     629       21780 :   auto & mesh_unique_ptr = find_mesh->second;
     630       21780 :   if (!mesh_unique_ptr)
     631           4 :     mooseError("While getting the saved mesh generator '",
     632             :                name,
     633             :                "', said mesh has already been retrieved");
     634             : 
     635       43552 :   return std::move(mesh_unique_ptr);
     636             : }
     637             : 
     638             : bool
     639       51639 : MeshGeneratorSystem::appendingMeshGenerators() const
     640             : {
     641       51639 :   return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
     642             : }
     643             : 
     644             : bool
     645          36 : MeshGeneratorSystem::hasDataDrivenAllowed() const
     646             : {
     647          36 :   return _app.parameters().get<bool>(allow_data_driven_param);
     648             : }
     649             : 
     650             : const std::string &
     651         140 : MeshGeneratorSystem::getDataDrivenGeneratorName() const
     652             : {
     653             :   mooseAssert(_data_driven_generator_name, "Not set");
     654         140 :   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