16#include "libmesh/mesh_tools.h"
22 "allow_data_driven_mesh_generation";
35 const std::string & name,
40 std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
50 const std::string & name,
54 mooseError(
"Can only call appendMeshGenerator() during the append_mesh_generator task");
59 if ((param_name_mg_name_pairs.size() == 0) ||
60 (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first !=
"input" &&
61 param_name_mg_name_pairs[0].first !=
"inputs") ||
62 (param_name_mg_name_pairs.size() > 1 && param_name_mg_name_pairs[0].first !=
"inputs"))
67 "' via appendMeshGenerator():\nCan only append a mesh generator that takes a "
68 "single input mesh generator via the parameter named 'input' or 'inputs'.");
79 mooseError(
"Cannot use appendMeshGenerator() because there is not a generator to append to!");
97 std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
102std::vector<std::pair<std::string, MeshGeneratorName>>
104 const bool allow_empty )
const
106 std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
108 auto add_dependency =
109 [&dependencies, &allow_empty](
const auto & param_name,
const auto & dependency)
111 if (dependency.size() || allow_empty)
112 dependencies.emplace_back(param_name, dependency);
115 for (
const auto & [name, param] : params)
116 if (
const auto dependency =
118 add_dependency(name, dependency->get());
119 else if (
const auto dependencies =
123 if (allow_empty && dependencies->get().empty())
124 add_dependency(name, std::string());
125 for (
const auto & dependency : dependencies->get())
126 add_dependency(name, dependency);
136 "Should not run now");
148 for (
const auto & param_dependency_pair :
150 resolver.
addEdge(param_dependency_pair.second, name);
153 std::vector<std::vector<std::string>> ordered_generators;
160 mooseError(
"Cyclic dependencies detected in mesh generation: ",
167 if (!moose_mesh.get())
168 mooseError(
"No mesh created. Either add a Mesh, an ActionComponents or a Components block");
172 if (moose_mesh->parameters().get<
bool>(
"_mesh_generator_mesh") &&
176 moose_mesh->paramError(
178 "This application does not support data-driven mesh generation.\n\nThis generation is an "
179 "advanced feature and must be enabled on the application via the '",
183 mooseAssert(moose_mesh->type() ==
"MeshGeneratorMesh",
184 "Assumption for mesh type is now invalid");
189 "The data driven generator '",
198 "This parameter should not be set in conjunction with --csg-only");
201 for (
const auto & generator_names : ordered_generators)
202 for (
const auto & generator_name : generator_names)
205 auto & params = it->second.second;
208 const bool data_only =
219 " cannot be used in csg-only mode since it does not have a generateCSG "
223 "Inconsistent data only");
231 if (moose_mesh->parameters().get<
bool>(
"_mesh_generator_mesh") &&
232 moose_mesh->isParamValid(
"final_generator"))
234 mooseAssert(moose_mesh->type() ==
"MeshGeneratorMesh",
235 "Assumption for mesh type is now invalid");
239 moose_mesh->paramError(
"final_generator",
240 "The forced final MeshGenerator '",
251 "Incorrect call time");
255 TIME_SECTION(
"createMeshGeneratorOrder", 1,
"Ordering Mesh Generators");
264 std::vector<std::string> required_generators;
266 if (it.second->hasSaveMesh() || it.second->hasOutput())
267 required_generators.push_back(it.second->name());
287 std::find_if(required_generators.begin(),
288 required_generators.end(),
290 required_generators.end())
314 std::vector<std::string> names(cycle.size());
316 names[i] = cycle[i]->name();
318 mooseError(
"Cyclic dependencies detected in mesh generation: ",
319 MooseUtils::join(names,
" <- "));
329 mooseAssert(final_generators.size(),
"Empty vector");
332 const auto ancestor_list = resolver.
getAncestors(final_generators.back());
337 std::set<MeshGenerator *, MeshGenerator::Comparator> ancestors(ancestor_list.begin(),
338 ancestor_list.end());
342 decltype(ancestors) all(allValues.begin(), allValues.end());
344 decltype(ancestors) ind_tree;
345 std::set_difference(all.begin(),
349 std::inserter(ind_tree, ind_tree.end()));
351 std::ostringstream oss;
352 oss <<
"Your MeshGenerator tree contains multiple possible generator outputs :\n\""
353 << final_generators.back()->name()
354 <<
"\" and one or more of the following from an independent set: \"";
356 for (
const auto & gen : ind_tree)
365 oss <<
"\"\n\nThis may be due to a missing dependency or may be intentional. Please either\n"
366 "- check that all the mesh generators are connected as a tree and culminate in a "
367 "single final mesh. Having one wrong 'input=mg' parameter is the most common error\n"
368 "- add additional dependencies to remove the ambiguity if you are using a user-built "
370 "- if you intend to execute a subset of the defined generators (uncommon), select the"
371 " final MeshGenerator in the [Mesh] block with the \"final_generator\" parameter.";
384 libmesh_parallel_only(
comm());
394 std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
396 for (
const auto & generator : generator_set)
397 if (generator->hasSaveMesh())
400 generator->paramError(
"save_with_name",
401 "Cannot use the save in capability with the final mesh generator");
403 generator->paramError(
"save_with_name",
"Cannot use in conjunction with --csg-only");
404 to_save_in_meshes.emplace(generator->getSavedMeshName(),
414 for (
const auto & generator : generator_set)
416 mooseAssert(
comm().verify(generator->typeAndName().size()) &&
417 comm().verify(generator->typeAndName()),
418 "Mesh generator generation is parallel inconsistent; about to execute "
419 << generator->typeAndName());
421 const auto & name = generator->name();
423 _app.
_console <<
" [DBG] Executing mesh generator (" << COLOR_GREEN << std::setw(20) << name
424 << COLOR_DEFAULT <<
") in type (" << COLOR_GREEN << generator->type()
425 << COLOR_DEFAULT <<
")" << std::endl;
426 auto current_mesh = generator->generateInternal();
428 if (!generator->isDataOnly())
429 mooseAssert(
comm().verify(current_mesh->is_prepared()),
430 "Mesh prepared state after " << generator->typeAndName()
431 <<
" is parallel inconsistent");
433 mooseAssert(
comm().verify(generator->typeAndName().size()) &&
434 comm().verify(generator->typeAndName()),
435 "Mesh generator generation is parallel inconsistent; just executed "
436 << generator->typeAndName());
439 if (generator->isDataOnly())
441 mooseAssert(!current_mesh,
"Should not have a mesh");
453 generator->mooseError(
454 "The generated mesh is marked as (at least partially) prepared but is not "
455 "prepared in the marked sense(s). Please edit the '",
457 "' class to call 'unset_is_prepared()', or more fine-grained "
458 "alternatives as appropriate.");
466 auto & first_output = *outputs.begin();
468 first_output = std::move(current_mesh);
470 const auto & copy_from = *first_output;
472 auto output_it = ++outputs.begin();
475 for (; output_it != outputs.end(); ++output_it)
476 (*output_it) = copy_from.clone();
487 for (
auto & [name, mesh_ptr] : to_save_in_meshes)
489 mooseAssert(mesh_ptr,
"Invalid pointer");
490 mooseAssert(*mesh_ptr,
"Invalid pointer");
492 mooseAssert(
_save_in_meshes.count(name),
"Mesh has not been requested for save");
497std::shared_ptr<MeshGenerator>
500 libmesh_parallel_only(
comm());
505 const auto & [type, params] = find_params->second;
506 mooseAssert(
comm().verify(type + generator_name),
"Inconsistent construction order");
508 std::shared_ptr<MeshGenerator> mg =
511 if (mg->hasSaveMesh())
515 "The save with name '",
516 mg->getSavedMeshName(),
517 "' has already been used");
522 for (
const auto & dependency : mg->getRequestedMeshGenerators())
539 const auto & param_name = param_dependency_pair.first;
540 const auto & dependency_name = param_dependency_pair.second;
542 if (mg->isNullMeshName(dependency_name))
546 if (mg->isParentMeshGenerator(dependency_name))
548 mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name),
"Wasn't requested");
553 auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
554 mg->getSubMeshGenerators().end(),
555 [&dependency_name](
const auto & mg)
556 { return mg->isParentMeshGenerator(dependency_name); });
557 const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
560 if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
562 if (!is_sub_dependency)
563 mg->mooseError(
"The sub generator dependency declared from MeshGenerator '",
565 "' from the parameter '",
567 "' was not used.\n\nDependencies that are declared by declareMeshForSub() "
568 "must be used as an input to a sub generator created by this object.");
571 else if (is_sub_dependency)
573 "The MeshGenerator '",
575 "' was referenced in the parameter '",
577 "' and used in the sub generator ",
578 (*find_sub_dependency)->type(),
580 (*find_sub_dependency)->name(),
581 "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
583 " to include a call to declareMesh(es)ForSub(\"",
585 "\") in the constructor.");
589 "You failed to request the generated mesh(es) for the parameter '",
591 "'.\n\nIn specific, the mesh from MeshGenerator '",
593 "' was not requested.\n\nTo correct this, you should remove the parameter if the "
594 "mesh(es)\nare not needed, or request the mesh(es) with getMesh()/getMeshes().");
611std::unique_ptr<MeshBase> &
616 "Incorrect call time");
620 it->second.push_back(
nullptr);
621 return it->second.back();
641 mooseError(
"Failed to find a MeshGenerator with the name '", name,
"'");
642 mooseAssert(it->second,
"Invalid shared pointer");
646std::vector<std::string>
649 std::vector<std::string> names;
651 names.push_back(pair.first);
655std::vector<std::string>
658 std::vector<std::string> names;
660 names.push_back(pair.first);
664std::unique_ptr<MeshBase>
669 mooseError(
"Failed to find a saved mesh with the name '", name,
"'");
671 auto & mesh_unique_ptr = find_mesh->second;
672 if (!mesh_unique_ptr)
673 mooseError(
"While getting the saved mesh generator '",
675 "', said mesh has already been retrieved");
677 return std::move(mesh_unique_ptr);
701 const std::string & message)
const
707 "' cannot be used in data-driven mode because the parent ",
721 std::unique_ptr<CSG::CSGBase> & csg_base)
730 auto & first_output = *outputs.begin();
731 first_output = std::move(csg_base);
732 const auto & copy_from = *first_output;
733 auto output_it = ++outputs.begin();
735 for (; output_it != outputs.end(); ++output_it)
736 (*output_it) = copy_from.clone();
740std::unique_ptr<CSG::CSGBase> &
745 "Incorrect call time");
749 it->second.push_back(
nullptr);
750 return it->second.back();
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
const std::string & getCurrentTaskName() const
const std::shared_ptr< MooseMesh > & getMesh() const
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
const std::vector< T > & getCyclicDependencies() const
Class that represents the dependecy as a graph.
bool dependsOn(const T &key, const T &value)
Return true if key depends on value.
std::list< T > getAncestors(const T &key)
Returns a list of all values that a given key depends on.
void addItem(const T &value)
Add an independent item to the set.
std::size_t size() const
Returns the number of unique items stored in the dependency resolver.
const std::vector< T > & getSortedValues()
This function also returns dependency resolved values but with a simpler single vector interface.
void addEdge(const T &a, const T &b)
Add an edge between nodes 'a' and 'b'.
const std::vector< std::vector< T > > & getSortedValuesSets()
Returns a vector of sets that represent dependency resolved values.
void saveOutputCSGBase(const MeshGeneratorName generator_name, std::unique_ptr< CSG::CSGBase > &csg_base)
Saves the CSGBase object to the global map storage, _csg_base_output, for a particular mesh generator...
MooseApp & _app
The MooseApp that owns this system.
void addMeshGenerator(const std::string &type, const std::string &name, const InputParameters ¶ms)
Add a mesh generator that will act on the meshes in the system.
std::vector< std::string > getMeshGeneratorNames() const
Get names of all mesh generators Note: This function should be called after all mesh generators are a...
bool hasMeshGeneratorParams(const MeshGeneratorName &name) const
Whether or not we know about the parameters for a MeshGenerator with the given name.
std::vector< std::vector< MeshGenerator * > > _ordered_mesh_generators
Holds the ordered mesh generators from createMeshGeneratorOrder() until they are executed in executeM...
std::shared_ptr< MeshGenerator > createMeshGenerator(const std::string &name)
Internal method for actually constructing a mesh generator after it has been declared externally in a...
std::unique_ptr< libMesh::MeshBase > & getMeshGeneratorOutput(const MeshGeneratorName &name)
Get a reference to a pointer that will be the output of the MeshGenerator named name.
std::map< std::string, std::list< std::unique_ptr< libMesh::MeshBase > > > _mesh_generator_outputs
Holds the output for each mesh generator - including duplicates needed downstream.
std::map< std::string, std::shared_ptr< MeshGenerator > > _mesh_generators
Owning storage for mesh generators, map of name -> MeshGenerator.
std::unordered_map< std::string, std::pair< std::string, InputParameters > > _mesh_generator_params
The MeshGenerators declared using addMeshGenerator(), cleared after createMeshGenerators() Key is the...
bool hasMeshGenerator(const MeshGeneratorName &name) const
void createAddedMeshGenerators()
Creates (constructs) all of the MeshGenerators that have been declared using addMeshGenerator().
static const std::string allow_data_driven_param
The name of the boolean parameter on the MooseApp that will enable data driven generation.
std::unique_ptr< CSG::CSGBase > & getCSGBaseGeneratorOutput(const MeshGeneratorName &name)
Returns the output CSGBase object associated with a particular mesh generator name.
std::map< std::string, std::unique_ptr< libMesh::MeshBase > > _save_in_meshes
Holds the map of save in mesh -> name.
void setCSGOnly()
Set whether mesh generator system is running in CSG-only mode to true.
const std::string & getDataDrivenGeneratorName() const
std::optional< std::string > _data_driven_generator_name
The name of the data driven generator, if any.
static std::string mainMeshGeneratorName()
The name reserved for the "main" mesh generator which is the one used for the numerical solver downst...
std::vector< std::pair< std::string, MeshGeneratorName > > getMeshGeneratorParamDependencies(const InputParameters ¶ms, const bool allow_empty=false) const
Gets the MeshGeneratorNames that are referenced in an object's parameters.
static const std::string data_driven_generator_param
The name of the string parameter that sets the data driven generator.
void executeMeshGenerators()
Execute and clear the Mesh Generators data structure.
bool appendingMeshGenerators() const
Whether or not mesh generators are currently being appended (append_mesh_generator task)
bool getCSGOnly() const
Get whether mesh generator system is running in CSG-only mode.
const MeshGenerator & appendMeshGenerator(const std::string &type, const std::string &name, InputParameters params)
Append a mesh generator that will act on the current final mesh generator in the system.
std::vector< std::string > getSavedMeshNames() const
Get all user-defined saved meshes except main and main_displaced.
bool _csg_only
Whether mesh generator system is running in CSG-only mode.
std::unique_ptr< libMesh::MeshBase > getSavedMesh(const std::string &name)
Get the saved mesh by name.
bool hasDataDrivenAllowed() const
std::map< std::string, std::list< std::unique_ptr< CSG::CSGBase > > > _csg_base_outputs
Holds the output CSGBase object for each mesh generator - including duplicates when needed by multipl...
MeshGenerator & getMeshGeneratorInternal(const std::string &name)
Get a MeshGenerator with the name name.
const MeshGenerator & getMeshGenerator(const std::string &name) const
bool _verbose
Whether to print the names of the mesh generators being executed or not.
MeshGeneratorSystem(MooseApp &app)
std::string _final_generator_name
The final mesh generator name to use.
void dataDrivenError(const MeshGenerator &generator, const std::string &message) const
Reports an error with the context of the data driven parameter, coming from the generator generator w...
void createMeshGeneratorOrder()
Order all of the _mesh_generators into _ordered_mesh_generators for later execution in executeMeshGen...
Class that is used as a parameter to add[Parent/Child]() that allows only MeshGeneratorSystem methods...
MeshGenerators are objects that can modify or add to an existing mesh.
bool hasSaveMesh() const
Return whether or not to save the current mesh.
static const std::string data_only_param
The name of the private parameter for setting data only.
const std::set< const MeshGenerator *, Comparator > & getParentMeshGenerators() const
Gets the MeshGenerators that are parents to this MeshGenerator.
bool isChildMeshGenerator(const MeshGeneratorName &name, const bool direct=true) const
Base class for MOOSE-based applications.
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
const InputParameters & parameters() const
Get the parameters of the object.
std::string typeAndName() const
Get the class's combined type and name; useful in error handling.
const std::string & name() const
Get the name of the class.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Interface for objects interacting with the PerfGraph.
virtual std::unique_ptr< Base > create()=0
const Parallel::Communicator & comm() const
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
auto index_range(const T &sizable)