https://mooseframework.inl.gov
MeshGenerator.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "MeshGenerator.h"
11 #include "MooseMesh.h"
12 #include "MooseApp.h"
13 
14 #include "Exodus.h"
15 #include "Nemesis.h"
16 
17 #include "libmesh/exodusII_io.h"
18 #include "libmesh/nemesis_io.h"
19 
20 const std::string MeshGenerator::data_only_param = "_data_only";
21 
24 {
26 
27  params.addParam<bool>("show_info",
28  false,
29  "Whether or not to show mesh info after generating the mesh "
30  "(bounding box, element types, sidesets, nodesets, subdomains, etc)");
31  params.addParam<std::string>(
32  "save_with_name",
33  std::string(),
34  "Keep the mesh from this mesh generator in memory with the name specified");
35 
36  params.addParam<bool>(
37  "output", false, "Whether or not to output the mesh file after generating the mesh");
38  params.addParam<bool>("nemesis",
39  false,
40  "Whether or not to output the mesh file in the nemesis"
41  "format (only if output = true)");
42 
43  params.addParamNamesToGroup("show_info output nemesis", "Debugging");
44  params.addParamNamesToGroup("save_with_name", "Advanced");
45  params.registerBase("MeshGenerator");
46 
47  params.addPrivateParam<bool>("_has_generate_data", false);
48  params.addPrivateParam<MooseMesh *>("_moose_mesh", nullptr);
49  params.addPrivateParam<bool>(data_only_param, false);
50  // Controls are not created early enough
51  params.suppressParameter<std::vector<std::string>>("control_tags");
52 
53  return params;
54 }
55 
57  : MooseObject(parameters),
59  _mesh(getParam<MooseMesh *>("_moose_mesh") ? getParam<MooseMesh *>("_moose_mesh")
60  : _app.actionWarehouse().mesh().get()),
61  _save_with_name(getParam<std::string>("save_with_name")),
62  _data_only(getParam<bool>(data_only_param))
63 {
64  const auto & system = _app.getMeshGeneratorSystem();
65  if (isDataOnly())
66  {
67  if (!hasGenerateData())
68  system.dataDrivenError(*this, "does not support data-driven generation");
69  if (hasSaveMesh())
70  system.dataDrivenError(*this, "has 'save_with_name' set");
71  }
72  if (_save_with_name == system.mainMeshGeneratorName())
73  paramError(
74  "save_with_name", "The user-defined mesh name: '", _save_with_name, "' is a reserved name");
75  if (getParam<bool>("nemesis") && !getParam<bool>("output"))
76  paramError("nemesis", "Should only be set to true if 'output=true'");
77 }
78 
79 void
81 {
82  params.set<bool>("_has_generate_data") = true;
83 }
84 
85 bool
87 {
88  return params.get<bool>("_has_generate_data");
89 }
90 
91 const MeshGeneratorName *
92 MeshGenerator::getMeshGeneratorNameFromParam(const std::string & param_name,
93  const bool allow_invalid) const
94 {
95  const auto valid_param = isParamValid(param_name);
96  if (!allow_invalid)
97  {
98  if (!valid_param)
99  mooseError("Failed to get a parameter with the name \"",
100  param_name,
101  "\" when getting a MeshGenerator.",
102  "\n\nKnown parameters:\n",
103  _pars);
104  if (!_pars.isType<MeshGeneratorName>(param_name))
105  paramError(param_name,
106  "Parameter of type \"",
107  _pars.type(param_name),
108  "\" is not an expected type for getting a MeshGenerator (should be of type "
109  "\"MeshGeneratorName\")");
110  }
111  else if (!valid_param)
112  return nullptr;
113 
114  const auto & name = getParam<MeshGeneratorName>(param_name);
115  checkGetMesh(name, param_name);
116 
117  return &name;
118 }
119 
120 const std::vector<MeshGeneratorName> &
121 MeshGenerator::getMeshGeneratorNamesFromParam(const std::string & param_name) const
122 {
123  if (!isParamValid(param_name))
124  mooseError("Failed to get a parameter with the name \"",
125  param_name,
126  "\" when getting MeshGenerators.",
127  "\n\nKnown parameters:\n",
128  _pars);
129  if (!_pars.isType<std::vector<MeshGeneratorName>>(param_name))
130  paramError(param_name,
131  "Parameter of type \"",
132  _pars.type(param_name),
133  "\" is not an expected type for getting MeshGenerators (should be of type "
134  "\"std::vector<MeshGeneratorName>\")");
135 
136  const auto & names = getParam<std::vector<MeshGeneratorName>>(param_name);
137  for (const auto & name : names)
138  checkGetMesh(name, param_name);
139 
140  return names;
141 }
142 
143 void
144 MeshGenerator::checkGetMesh(const MeshGeneratorName & mesh_generator_name,
145  const std::string & param_name) const
146 {
147  mooseAssert(!mesh_generator_name.empty(), "Empty name");
148  const auto & mg_sys = _app.getMeshGeneratorSystem();
150  mooseError("Cannot get a mesh outside of construction");
151  if (!mg_sys.hasMeshGenerator(mesh_generator_name) && !isNullMeshName(mesh_generator_name))
152  {
153  std::stringstream error;
154  error << "The requested MeshGenerator with name '" << mesh_generator_name << "' ";
155  if (mg_sys.hasMeshGeneratorParams(mesh_generator_name))
156  error << "was found, but has not been constructed yet.\n\nThis can occur when your "
157  "dependencies are not properly defined and we cannot infer the proper construction "
158  "order of your MeshGenerators.\n\nThe most likely case is a sub generator whose "
159  "input(s) are not declared as a sub dependency in the generator creating them.";
160  else
161  error << "was not found.\nMesh generators that can be found: "
162  << Moose::stringify(mg_sys.getMeshGeneratorNames());
163 
164  if (param_name.size())
165  paramError(param_name, error.str());
166  else
167  mooseError(error.str());
168  }
169 }
170 
171 std::unique_ptr<MeshBase> &
172 MeshGenerator::getMesh(const std::string & param_name, const bool allow_invalid /* = false */)
173 {
174  const MeshGeneratorName * name = getMeshGeneratorNameFromParam(param_name, allow_invalid);
175  if (!name)
176  return _null_mesh;
177  return getMeshByName(*name);
178 }
179 
180 std::vector<std::unique_ptr<MeshBase> *>
181 MeshGenerator::getMeshes(const std::string & param_name)
182 {
184 }
185 
186 std::unique_ptr<MeshBase> &
187 MeshGenerator::getMeshByName(const MeshGeneratorName & mesh_generator_name)
188 {
189  checkGetMesh(mesh_generator_name, "");
190  if (isNullMeshName(mesh_generator_name))
191  return _null_mesh;
192 
193  _requested_mesh_generators.insert(mesh_generator_name);
194  auto & mesh = _app.getMeshGeneratorSystem().getMeshGeneratorOutput(mesh_generator_name);
195  _requested_meshes.emplace_back(mesh_generator_name, &mesh);
196  return mesh;
197 }
198 
199 std::vector<std::unique_ptr<MeshBase> *>
200 MeshGenerator::getMeshesByName(const std::vector<MeshGeneratorName> & mesh_generator_names)
201 {
202  std::vector<std::unique_ptr<MeshBase> *> meshes;
203  for (const auto & name : mesh_generator_names)
204  meshes.push_back(&getMeshByName(name));
205  return meshes;
206 }
207 
208 void
209 MeshGenerator::declareMeshForSub(const std::string & param_name)
210 {
212 }
213 
214 void
215 MeshGenerator::declareMeshesForSub(const std::string & param_name)
216 {
218 }
219 
220 void
221 MeshGenerator::declareMeshForSubByName(const MeshGeneratorName & mesh_generator_name)
222 {
223  checkGetMesh(mesh_generator_name, "");
224  if (isNullMeshName(mesh_generator_name))
225  return;
226 
227  _requested_mesh_generators_for_sub.insert(mesh_generator_name);
228 }
229 
230 void
232  const std::vector<MeshGeneratorName> & mesh_generator_names)
233 {
234  for (const auto & name : mesh_generator_names)
236 }
237 
238 std::unique_ptr<MeshBase>
240 {
241  mooseAssert(_mesh, "Need a MooseMesh object");
242  return _mesh->buildMeshBaseObject(dim);
243 }
244 
245 std::unique_ptr<ReplicatedMesh>
247 {
248  mooseAssert(_mesh, "Need a MooseMesh object");
249  return _mesh->buildTypedMesh<ReplicatedMesh>(dim);
250 }
251 
252 std::unique_ptr<DistributedMesh>
254 {
255  mooseAssert(_mesh, "Need a MooseMesh object");
256  return _mesh->buildTypedMesh<DistributedMesh>(dim);
257 }
258 
259 std::unique_ptr<MeshBase>
261 {
262  libmesh_parallel_only(comm());
263  mooseAssert(comm().verify(type() + name()), "Inconsistent execution ordering");
264 
265  if (hasGenerateData())
266  generateData();
267 
268  if (isDataOnly())
269  return nullptr;
270 
271  auto mesh = generate();
272  if (!mesh)
273  mooseError("A mesh was not generated by this generator (it was nullptr).");
274 
275  for (const auto & [requested_name, requested_mesh] : _requested_meshes)
276  if (*requested_mesh)
277  mooseError(
278  "The mesh from input ",
279  _app.getMeshGenerator(requested_name).type(),
280  " '",
281  _app.getMeshGenerator(requested_name).name(),
282  "' was not moved.\n\nThe MeshGenerator system requires that the memory from all input "
283  "meshes\nare managed by the requesting MeshGenerator during the generate phase.\n\nThis "
284  "is achieved with a std::move() operation within the generate() method.");
285 
286  if (getParam<bool>("show_info"))
287  {
288  const auto mesh_info = mesh->get_info(/* verbosity = */ 2);
289 
290  // We will prefix all information with "type() 'name()':" because this could potentially
291  // output a ton of information and looks a bit better with a prefix
292  std::stringstream oss;
293  const auto split = MooseUtils::split(mesh_info, "\n");
294  if (split.size())
295  for (std::size_t i = 0; i < split.size() - 1; ++i) // ignore the last line break
296  oss << COLOR_CYAN << "" << type() << " '" << name() << "': " << COLOR_DEFAULT << split[i]
297  << std::endl;
298  _console << oss.str() << std::flush;
299  }
300 
301  // output the current mesh block to file
302  if (hasOutput())
303  {
304  if (!mesh->is_prepared())
305  mesh->prepare_for_use();
306 
307  if (!getParam<bool>("nemesis"))
308  {
309  libMesh::ExodusII_IO exio(*mesh);
310 
311  if (mesh->mesh_dimension() == 1)
312  exio.write_as_dimension(3);
313 
314  // Default to non-HDF5 output for wider compatibility
315  exio.set_hdf5_writing(false);
316 
317  exio.write(name() + "_in.e");
318  }
319  else
320  {
321  libMesh::Nemesis_IO nemesis_io(*mesh);
322 
323  // Default to non-HDF5 output for wider compatibility
324  nemesis_io.set_hdf5_writing(false);
325 
326  nemesis_io.write(name() + "_in.e");
327  }
328  }
329 
330  return mesh;
331 }
332 
333 void
334 MeshGenerator::addMeshSubgenerator(const std::string & type,
335  const std::string & name,
336  InputParameters params)
337 {
339  mooseError("Can only call addMeshSubgenerator() during MeshGenerator construction");
340 
341  // In case the user forgot it
342  params.set<MooseApp *>("_moose_app") = &_app;
343 
344  // Set this to be data-only if this generator is data only
345  params.set<bool>(data_only_param) = isDataOnly();
346 
347  _app.addMeshGenerator(type, name, params);
348  _sub_mesh_generators.insert(&std::as_const(_app).getMeshGenerator(name));
349 }
350 
352 MeshGenerator::setMeshPropertyHelper(const std::string & data_name)
353 {
355 }
356 
357 void
359 {
360  mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
361  _parent_mesh_generators.insert(&mg);
362 }
363 
364 void
366 {
367  mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
368  _child_mesh_generators.insert(&mg);
369 }
370 
371 bool
372 MeshGenerator::isParentMeshGenerator(const MeshGeneratorName & name,
373  const bool direct /* = true */) const
374 {
375  return std::find_if(getParentMeshGenerators().begin(),
376  getParentMeshGenerators().end(),
377  [&name, &direct](const auto & mg)
378  {
379  return mg->name() == name ||
380  (!direct && mg->isParentMeshGenerator(name, /* direct = */ false));
381  }) != getParentMeshGenerators().end();
382 }
383 
384 bool
385 MeshGenerator::isChildMeshGenerator(const MeshGeneratorName & name,
386  const bool direct /* = true */) const
387 {
388  return std::find_if(getChildMeshGenerators().begin(),
389  getChildMeshGenerators().end(),
390  [&name, &direct](const auto & mg)
391  {
392  return mg->name() == name ||
393  (!direct && mg->isChildMeshGenerator(name, /* direct = */ false));
394  }) != getChildMeshGenerators().end();
395 }
396 
397 void
398 MeshGenerator::declareNullMeshName(const MeshGeneratorName & name)
399 {
400  mooseAssert(_app.constructingMeshGenerators(), "Should only be called at construction");
401  mooseAssert(!_null_mesh_names.count(name), "Already declared");
402  _null_mesh_names.insert(name);
403 }
404 
405 bool
407 {
408  return _save_with_name.size();
409 }
410 
411 bool
413 {
414  return getParam<bool>("output");
415 }
416 
417 const std::string &
419 {
420  return _save_with_name;
421 }
422 
423 void
425 {
426  mooseAssert(!hasGenerateData(), "Inconsistent flag");
427  mooseError("This MeshGenerator does not have a generateData() implementation.");
428 }
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Definition: MooseApp.C:3499
std::unique_ptr< DistributedMesh > buildDistributedMesh(unsigned int dim=libMesh::invalid_uint)
Build a distributed mesh that has correct remote element removal behavior and geometric ghosting func...
std::unique_ptr< MeshBase > & getMeshByName(const MeshGeneratorName &mesh_generator_name)
Like getMesh(), but takes the name of another MeshGenerator directly.
std::set< std::string > _null_mesh_names
The declared "null" mesh names that will not represent a mesh in input; see declareNullMeshName() ...
RestartableDataValue & setMeshPropertyHelper(const std::string &data_name)
Helper for getting a writable reference to a mesh property, used in declareMeshProperty and setMeshPr...
static const std::string data_only_param
The name of the private parameter for setting data only.
Definition: MeshGenerator.h:62
const MeshGenerator & getMeshGenerator(const std::string &name) const
Definition: MooseApp.h:897
bool isChildMeshGenerator(const MeshGeneratorName &name, const bool direct=true) const
void write_as_dimension(unsigned dim)
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
Build a replicated mesh.
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.
const std::string & _save_with_name
A user-defined name to save the mesh.
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
bool hasSaveMesh() const
Return whether or not to save the current mesh.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
static const RestartableDataMapName MESH_META_DATA
Definition: MooseApp.h:123
T * get(const std::unique_ptr< T > &u)
The MooseUtils::get() specializations are used to support making forwards-compatible code changes fro...
Definition: MooseUtils.h:1155
virtual void generateData()
Generate the mesh data.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
MeshBase & mesh
Base class for MOOSE-based applications.
Definition: MooseApp.h:96
static std::string meshPropertyName(const std::string &data_name, const std::string &prefix)
bool hasOutput() const
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:154
const Parallel::Communicator & comm() const
const std::set< const MeshGenerator *, Comparator > & getChildMeshGenerators() const
Gets the MeshGenerators that are children to this MeshGenerator.
std::unique_ptr< MeshBase > _null_mesh
A nullptr to use for when inputs aren&#39;t specified.
MeshGenerator(const InputParameters &parameters)
Definition: MeshGenerator.C:56
bool hasGenerateData() const
virtual const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:57
std::set< const MeshGenerator *, Comparator > _child_mesh_generators
The MeshGenerators that are children to this MeshGenerator.
bool isNullMeshName(const MeshGeneratorName &name) const
MooseMesh *const _mesh
Pointer to the owning mesh.
std::vector< std::string > split(const std::string &str, const std::string &delimiter, std::size_t max_count=std::numeric_limits< std::size_t >::max())
Python like split functions for strings.
Definition: MooseUtils.C:1126
void suppressParameter(const std::string &name)
This method suppresses an inherited parameter so that it isn&#39;t required or valid in the derived class...
void addChildMeshGenerator(const MeshGenerator &mg, const AddParentChildKey)
Adds the MeshGenerator mg as a child.
void declareMeshForSub(const std::string &param_name)
Declares that a MeshGenerator referenced in the InputParameters is to be used as a dependency of a su...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System...
std::vector< std::pair< std::string, std::unique_ptr< MeshBase > * > > _requested_meshes
The meshes that were requested by this MeshGenerator; used to verify that any input meshes that are r...
void addParentMeshGenerator(const MeshGenerator &mg, const AddParentChildKey)
Adds the MeshGenerator mg as a parent.
bool isParentMeshGenerator(const MeshGeneratorName &name, const bool direct=true) const
RestartableDataValue & getRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname, THREAD_ID tid)
Definition: MooseApp.C:2516
std::unique_ptr< T > buildTypedMesh(unsigned int dim=libMesh::invalid_uint)
Shortcut method to construct a unique pointer to a libMesh mesh instance.
Definition: MooseMesh.h:2090
void addMeshSubgenerator(const std::string &type, const std::string &name, Ts... extra_input_parameters)
Construct a "subgenerator", a different MeshGenerator subclass that will be added to the same MooseAp...
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Method to construct a libMesh::MeshBase object that is normally set and used by the MooseMesh object ...
Definition: MooseMesh.C:2851
void declareMeshesForSubByName(const std::vector< MeshGeneratorName > &mesh_generator_names)
Like declareMeshForSubByName(), but for multiple generators.
std::set< MeshGeneratorName > _requested_mesh_generators_for_sub
The names of the MeshGenerators that were requested in the declareMeshForSub methods.
std::unique_ptr< MeshBase > & getMesh(const std::string &param_name, const bool allow_invalid=false)
Takes the name of a MeshGeneratorName parameter and then gets a pointer to the Mesh that MeshGenerato...
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:88
virtual std::unique_ptr< MeshBase > generate()=0
Generate / modify the mesh.
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:51
std::set< MeshGeneratorName > _requested_mesh_generators
The names of the MeshGenerators that were requested in the getMesh methods.
std::vector< std::unique_ptr< MeshBase > * > getMeshesByName(const std::vector< MeshGeneratorName > &mesh_generator_names)
Like getMeshByName(), but for multiple generators.
std::vector< std::unique_ptr< MeshBase > * > getMeshes(const std::string &param_name)
Like getMesh(), but for multiple generators.
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
static InputParameters validParams()
Definition: MeshGenerator.C:23
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
std::unique_ptr< MeshBase > generateInternal()
Internal generation method - this is what is actually called within MooseApp to execute the MeshGener...
std::set< const MeshGenerator *, Comparator > _sub_mesh_generators
The sub MeshGenerators constructed by this MeshGenerator.
tbb::split split
bool isType(const std::string &name) const
void addMeshGenerator(const std::string &type, const std::string &name, const InputParameters &params)
Add a mesh generator that will act on the meshes in the system.
Definition: MooseApp.h:879
virtual void write(const std::string &fname) override
Class that is used as a parameter to add[Parent/Child]() that allows only MeshGeneratorSystem methods...
Definition: MeshGenerator.h:97
std::string type(const std::string &name) const
Prints the type of the requested parameter by name.
const std::set< const MeshGenerator *, Comparator > & getParentMeshGenerators() const
Gets the MeshGenerators that are parents to this MeshGenerator.
void checkGetMesh(const MeshGeneratorName &mesh_generator_name, const std::string &param_name) const
Helper for performing error checking in the getMesh methods.
std::set< const MeshGenerator *, Comparator > _parent_mesh_generators
The MeshGenerators that are parents to this MeshGenerator.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
const InputParameters & _pars
Parameters of this object, references the InputParameters stored in the InputParametersWarehouse.
static void setHasGenerateData(InputParameters &params)
Sets that a mesh generator has a generateData() implementation.
Definition: MeshGenerator.C:80
virtual void write(const std::string &base_filename) override
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
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...
The Interface used to retrieve mesh meta data (attributes) set by the MeshGenerator system...
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Build a MeshBase object whose underlying type will be determined by the Mesh input file block...
bool isDataOnly() const
MeshGeneratorSystem & getMeshGeneratorSystem()
Gets the system that manages the MeshGenerators.
Definition: MooseApp.h:863
static InputParameters validParams()
Definition: MooseObject.C:25
void declareMeshesForSub(const std::string &param_name)
Like declareMeshForSub(), but for multiple generators.
void declareNullMeshName(const MeshGeneratorName &name)
Registers the name name as a "null" mesh, which is a MeshGenerator used in InputParameters that will ...
const std::string & getSavedMeshName() const
Return the name of the saved mesh.
void declareMeshForSubByName(const MeshGeneratorName &mesh_generator_name)
Like declareMeshForSub(), but takes the name of another MeshGenerator directly.
void set_hdf5_writing(bool write_hdf5)
void set_hdf5_writing(bool write_hdf5)
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32
const std::vector< MeshGeneratorName > & getMeshGeneratorNamesFromParam(const std::string &param_name) const
Helper for getting a std::vector<MeshGeneratorName> parameter.
Abstract definition of a RestartableData value.
const MeshGeneratorName * getMeshGeneratorNameFromParam(const std::string &param_name, const bool allow_invalid) const
Helper for getting a MeshGeneratorName parameter.
Definition: MeshGenerator.C:92
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...