16 #include "libmesh/mesh_tools.h" 22 "allow_data_driven_mesh_generation";
36 const std::string & name,
41 std::piecewise_construct, std::forward_as_tuple(
name), std::forward_as_tuple(type, params));
48 if (type ==
"BreakMeshByBlockGenerator")
54 const std::string & name,
58 mooseError(
"Can only call appendMeshGenerator() during the append_mesh_generator task");
63 if ((param_name_mg_name_pairs.size() == 0) ||
64 (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first !=
"input" &&
65 param_name_mg_name_pairs[0].first !=
"inputs") ||
66 (param_name_mg_name_pairs.size() > 1 && param_name_mg_name_pairs[0].first !=
"inputs"))
71 "' via appendMeshGenerator():\nCan only append a mesh generator that takes a " 72 "single input mesh generator via the parameter named 'input' or 'inputs'.");
83 mooseError(
"Cannot use appendMeshGenerator() because there is not a generator to append to!");
101 std::piecewise_construct, std::forward_as_tuple(
name), std::forward_as_tuple(type, params));
106 std::vector<std::pair<std::string, MeshGeneratorName>>
108 const bool allow_empty )
const 110 std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
112 auto add_dependency =
113 [&dependencies, &allow_empty](
const auto & param_name,
const auto & dependency)
115 if (dependency.size() || allow_empty)
116 dependencies.emplace_back(param_name, dependency);
119 for (
const auto & [
name, param] : params)
120 if (
const auto dependency =
121 dynamic_cast<const Parameters::Parameter<MeshGeneratorName> *
>(param.get()))
122 add_dependency(
name, dependency->get());
123 else if (
const auto dependencies =
124 dynamic_cast<const Parameters::Parameter<std::vector<MeshGeneratorName>
> *>(
127 if (allow_empty && dependencies->get().empty())
128 add_dependency(
name, std::string());
129 for (
const auto & dependency : dependencies->get())
130 add_dependency(
name, dependency);
140 "Should not run now");
152 for (
const auto & param_dependency_pair :
154 resolver.
addEdge(param_dependency_pair.second,
name);
157 std::vector<std::vector<std::string>> ordered_generators;
164 mooseError(
"Cyclic dependencies detected in mesh generation: ",
171 if (!moose_mesh.get())
172 mooseError(
"No mesh created. Either add a Mesh, an ActionComponents or a Components block");
176 if (moose_mesh->parameters().get<
bool>(
"_mesh_generator_mesh") &&
180 moose_mesh->paramError(
182 "This application does not support data-driven mesh generation.\n\nThis generation is an " 183 "advanced feature and must be enabled on the application via the '",
187 mooseAssert(moose_mesh->type() ==
"MeshGeneratorMesh",
188 "Assumption for mesh type is now invalid");
193 "The data driven generator '",
202 "This parameter should not be set in conjunction with --csg-only");
205 for (
const auto & generator_names : ordered_generators)
206 for (
const auto & generator_name : generator_names)
209 auto & params = it->second.second;
212 const bool data_only =
223 " cannot be used in csg-only mode since it does not have a generateCSG " 227 "Inconsistent data only");
235 if (moose_mesh->parameters().get<
bool>(
"_mesh_generator_mesh") &&
236 moose_mesh->isParamValid(
"final_generator"))
238 mooseAssert(moose_mesh->type() ==
"MeshGeneratorMesh",
239 "Assumption for mesh type is now invalid");
243 moose_mesh->paramError(
"final_generator",
244 "The forced final MeshGenerator '",
255 "Incorrect call time");
259 TIME_SECTION(
"createMeshGeneratorOrder", 1,
"Ordering Mesh Generators");
268 std::vector<std::string> required_generators;
270 if (it.second->hasSaveMesh() || it.second->hasOutput())
271 required_generators.push_back(it.second->name());
291 std::find_if(required_generators.begin(),
292 required_generators.end(),
294 required_generators.end())
318 std::vector<std::string> names(cycle.size());
320 names[i] = cycle[i]->
name();
322 mooseError(
"Cyclic dependencies detected in mesh generation: ",
333 mooseAssert(final_generators.size(),
"Empty vector");
336 const auto ancestor_list = resolver.
getAncestors(final_generators.back());
341 std::set<MeshGenerator *, MeshGenerator::Comparator> ancestors(ancestor_list.begin(),
342 ancestor_list.end());
346 decltype(ancestors) all(allValues.begin(), allValues.end());
348 decltype(ancestors) ind_tree;
349 std::set_difference(all.begin(),
353 std::inserter(ind_tree, ind_tree.end()));
355 std::ostringstream oss;
356 oss <<
"Your MeshGenerator tree contains multiple possible generator outputs :\n\"" 357 << final_generators.back()->name()
358 <<
"\" and one or more of the following from an independent set: \"";
360 for (
const auto & gen : ind_tree)
369 oss <<
"\"\n\nThis may be due to a missing dependency or may be intentional. Please either\n" 370 "- check that all the mesh generators are connected as a tree and culminate in a " 371 "single final mesh. Having one wrong 'input=mg' parameter is the most common error\n" 372 "- add additional dependencies to remove the ambiguity if you are using a user-built " 374 "- if you intend to execute a subset of the defined generators (uncommon), select the" 375 " final MeshGenerator in the [Mesh] block with the \"final_generator\" parameter.";
388 libmesh_parallel_only(
comm());
398 std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
400 for (
const auto & generator : generator_set)
401 if (generator->hasSaveMesh())
404 generator->paramError(
"save_with_name",
405 "Cannot use the save in capability with the final mesh generator");
407 generator->paramError(
"save_with_name",
"Cannot use in conjunction with --csg-only");
408 to_save_in_meshes.emplace(generator->getSavedMeshName(),
418 for (
const auto & generator : generator_set)
420 const auto &
name = generator->name();
422 _app.
_console <<
" [DBG] Executing mesh generator (" << COLOR_GREEN << std::setw(20) <<
name 423 << COLOR_DEFAULT <<
") in type (" << COLOR_GREEN << generator->type()
424 << COLOR_DEFAULT <<
")" << std::endl;
425 auto current_mesh = generator->generateInternal();
428 if (generator->isDataOnly())
430 mooseAssert(!current_mesh,
"Should not have a mesh");
437 if (!
_has_bmbb && !MeshTools::valid_is_prepared(*current_mesh))
438 generator->mooseError(
"The generated mesh is marked as prepared but is not actually " 439 "prepared. Please edit the '",
441 "' class to call 'set_isnt_prepared()'");
449 auto & first_output = *outputs.begin();
451 first_output = std::move(current_mesh);
453 const auto & copy_from = *first_output;
455 auto output_it = ++outputs.begin();
458 for (; output_it != outputs.end(); ++output_it)
459 (*output_it) = copy_from.clone();
470 for (
auto & [
name, mesh_ptr] : to_save_in_meshes)
472 mooseAssert(mesh_ptr,
"Invalid pointer");
473 mooseAssert(*mesh_ptr,
"Invalid pointer");
480 std::shared_ptr<MeshGenerator>
483 libmesh_parallel_only(
comm());
488 const auto & [type, params] = find_params->second;
489 mooseAssert(
comm().verify(type + generator_name),
"Inconsistent construction order");
491 std::shared_ptr<MeshGenerator> mg =
494 if (mg->hasSaveMesh())
498 "The save with name '",
499 mg->getSavedMeshName(),
500 "' has already been used");
505 for (
const auto & dependency : mg->getRequestedMeshGenerators())
522 const auto & param_name = param_dependency_pair.first;
523 const auto & dependency_name = param_dependency_pair.second;
525 if (mg->isNullMeshName(dependency_name))
529 if (mg->isParentMeshGenerator(dependency_name))
531 mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name),
"Wasn't requested");
536 auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
537 mg->getSubMeshGenerators().end(),
538 [&dependency_name](
const auto & mg)
539 {
return mg->isParentMeshGenerator(dependency_name); });
540 const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
543 if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
545 if (!is_sub_dependency)
546 mg->mooseError(
"The sub generator dependency declared from MeshGenerator '",
548 "' from the parameter '",
550 "' was not used.\n\nDependencies that are declared by declareMeshForSub() " 551 "must be used as an input to a sub generator created by this object.");
554 else if (is_sub_dependency)
556 "The MeshGenerator '",
558 "' was referenced in the parameter '",
560 "' and used in the sub generator ",
561 (*find_sub_dependency)->type(),
563 (*find_sub_dependency)->name(),
564 "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
566 " to include a call to declareMesh(es)ForSub(\"",
568 "\") in the constructor.");
572 "You failed to request the generated mesh(es) for the parameter '",
574 "'.\n\nIn specific, the mesh from MeshGenerator '",
576 "' was not requested.\n\nTo correct this, you should remove the parameter if the " 577 "mesh(es)\nare not needed, or request the mesh(es) with getMesh()/getMeshes().");
589 std::unique_ptr<MeshBase> &
594 "Incorrect call time");
598 it->second.push_back(
nullptr);
599 return it->second.back();
619 mooseError(
"Failed to find a MeshGenerator with the name '",
name,
"'");
620 mooseAssert(it->second,
"Invalid shared pointer");
624 std::vector<std::string>
627 std::vector<std::string> names;
629 names.push_back(pair.first);
633 std::vector<std::string>
636 std::vector<std::string> names;
638 names.push_back(pair.first);
642 std::unique_ptr<MeshBase>
647 mooseError(
"Failed to find a saved mesh with the name '",
name,
"'");
649 auto & mesh_unique_ptr = find_mesh->second;
650 if (!mesh_unique_ptr)
651 mooseError(
"While getting the saved mesh generator '",
653 "', said mesh has already been retrieved");
655 return std::move(mesh_unique_ptr);
679 const std::string & message)
const 685 "' cannot be used in data-driven mode because the parent ",
699 std::unique_ptr<CSG::CSGBase> & csg_base)
702 "CSG mesh already exists");
706 std::unique_ptr<CSG::CSGBase> &
710 "Incorrect call time");
std::string name(const ElemQuality q)
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
std::unique_ptr< CSG::CSGBase > & getCSGBaseGeneratorOutput(const MeshGeneratorName &name)
Returns the output CSGBase object associated with a particular mesh generator name.
std::string _final_generator_name
The final mesh generator name to use.
MeshGeneratorSystem(MooseApp &app)
std::string join(Iterator begin, Iterator end, const std::string &delimiter)
Python-like join function for strings over an iterator range.
static const std::string data_only_param
The name of the private parameter for setting data only.
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...
bool isChildMeshGenerator(const MeshGeneratorName &name, const bool direct=true) const
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.
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 ...
bool hasSaveMesh() const
Return whether or not to save the current mesh.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
void setCSGOnly()
Set whether mesh generator system is running in CSG-only mode to true.
std::map< std::string, std::unique_ptr< libMesh::MeshBase > > _save_in_meshes
Holds the map of save in mesh -> name.
std::size_t size() const
Returns the number of unique items stored in the dependency resolver.
bool hasDataDrivenAllowed() const
const std::vector< T > & getSortedValues()
This function also returns dependency resolved values but with a simpler single vector interface...
const InputParameters & parameters() const
Get the parameters of the object.
const std::shared_ptr< MooseMesh > & getMesh() const
std::unique_ptr< libMesh::MeshBase > getSavedMesh(const std::string &name)
Get the saved mesh by name.
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 dependsOn(const T &key, const T &value)
Return true if key depends on value.
Base class for MOOSE-based applications.
void executeMeshGenerators()
Execute and clear the Mesh Generators data structure.
std::optional< std::string > _data_driven_generator_name
The name of the data driven generator, if any.
const Parallel::Communicator & comm() const
std::list< T > getAncestors(const T &key)
Returns a list of all values that a given key depends on.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const std::vector< std::vector< T > > & getSortedValuesSets()
Returns a vector of sets that represent dependency resolved values.
void addEdge(const T &a, const T &b)
Add an edge between nodes 'a' and 'b'.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
bool _verbose
Whether to print the names of the mesh generators being executed or not.
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.
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.
void addItem(const T &value)
Add an independent item to the set.
MooseApp & _app
The MooseApp that owns this system.
const std::string & name() const
Get the name of the class.
virtual std::unique_ptr< Base > create()=0
void createAddedMeshGenerators()
Creates (constructs) all of the MeshGenerators that have been declared using addMeshGenerator().
bool getCSGOnly() const
Get whether mesh generator system is running in CSG-only mode.
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
std::string typeAndName() const
Get the class's combined type and name; useful in error handling.
bool _csg_only
Whether mesh generator system is running in CSG-only mode.
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...
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.
Interface for objects interacting with the PerfGraph.
std::vector< std::string > getSavedMeshNames() const
Get all user-defined saved meshes except main and main_displaced.
static std::string mainMeshGeneratorName()
The name reserved for the "main" mesh generator which is the one used for the numerical solver downst...
std::map< std::string, std::shared_ptr< MeshGenerator > > _mesh_generators
Owning storage for mesh generators, map of name -> MeshGenerator.
const std::string & getCurrentTaskName() const
std::map< std::string, std::unique_ptr< CSG::CSGBase > > _csg_base_output
Holds the output CSGBase object for each mesh generator.
void createMeshGeneratorOrder()
Order all of the _mesh_generators into _ordered_mesh_generators for later execution in executeMeshGen...
const std::vector< T > & getCyclicDependencies() const
Class that is used as a parameter to add[Parent/Child]() that allows only MeshGeneratorSystem methods...
static const std::string data_driven_generator_param
The name of the string parameter that sets the data driven generator.
const std::set< const MeshGenerator *, Comparator > & getParentMeshGenerators() const
Gets the MeshGenerators that are parents to this MeshGenerator.
bool hasMeshGenerator(const MeshGeneratorName &name) const
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...
const MeshGenerator & getMeshGenerator(const std::string &name) const
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
bool appendingMeshGenerators() const
Whether or not mesh generators are currently being appended (append_mesh_generator task) ...
static const std::string allow_data_driven_param
The name of the boolean parameter on the MooseApp that will enable data driven generation.
const std::string & getDataDrivenGeneratorName() const
MeshGenerator & getMeshGeneratorInternal(const std::string &name)
Get a MeshGenerator with the name name.
bool _has_bmbb
Whether any of the mesh generators are a BreakMeshByBlockGenerator.
MeshGenerators are objects that can modify or add to an existing mesh.
auto index_range(const T &sizable)
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 hasMeshGeneratorParams(const MeshGeneratorName &name) const
Whether or not we know about the parameters for a MeshGenerator with the given name.
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.
std::vector< std::vector< MeshGenerator * > > _ordered_mesh_generators
Holds the ordered mesh generators from createMeshGeneratorOrder() until they are executed in executeM...