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 : #pragma once
11 :
12 : #include "MooseObject.h"
13 : #include "MeshMetaDataInterface.h"
14 : #include "MooseApp.h"
15 : #include "CSGBase.h"
16 :
17 : // Included so mesh generators don't need to include this when constructing MeshBase objects
18 : #include "MooseMesh.h"
19 :
20 : #include "libmesh/mesh_base.h"
21 : #include "libmesh/parameters.h"
22 :
23 : class MooseMesh;
24 : namespace libMesh
25 : {
26 : class ReplicatedMesh;
27 : class DistributedMesh;
28 : }
29 :
30 : /**
31 : * MeshGenerators are objects that can modify or add to an existing mesh.
32 : */
33 : class MeshGenerator : public MooseObject, public MeshMetaDataInterface
34 : {
35 : public:
36 : /**
37 : * Comparator for MeshGenerators that sorts by name
38 : */
39 : struct Comparator
40 : {
41 3363350 : bool operator()(const MeshGenerator * const & a, const MeshGenerator * const & b) const
42 : {
43 3363350 : return a->name() < b->name();
44 : }
45 : };
46 :
47 : static InputParameters validParams();
48 :
49 : /**
50 : * Sets that a mesh generator has a generateData() implementation.
51 : *
52 : * This must be called in the validParams() implementation for all
53 : * mesh generators that implement generateData().
54 : */
55 : static void setHasGenerateData(InputParameters & params);
56 : /**
57 : * @return Whether or not the mesh generator noted by the given parameters
58 : * has a generateData() implementation
59 : */
60 : static bool hasGenerateData(const InputParameters & params);
61 :
62 : /**
63 : * Sets that a mesh generator has a generateCSG() implementation.
64 : *
65 : * This must be called in the validParams() implementation for all
66 : * mesh generators that implement generateCSG().
67 : */
68 : static void setHasGenerateCSG(InputParameters & params);
69 : /**
70 : * @return Whether or not the mesh generator noted by the given parameters
71 : * has a generateCSG() implementation
72 : */
73 : static bool hasGenerateCSG(const InputParameters & params);
74 :
75 : /// The name of the private parameter for setting data only
76 : static const std::string data_only_param;
77 :
78 : MeshGenerator(const InputParameters & parameters);
79 :
80 : /**
81 : * Generate / modify the mesh
82 : */
83 : virtual std::unique_ptr<MeshBase> generate() = 0;
84 :
85 : /**
86 : * Internal generation method for CSG object generation
87 : */
88 : [[nodiscard]] std::unique_ptr<CSG::CSGBase> generateInternalCSG();
89 :
90 : /**
91 : * Internal generation method - this is what is actually called
92 : * within MooseApp to execute the MeshGenerator.
93 : */
94 : [[nodiscard]] std::unique_ptr<MeshBase> generateInternal();
95 :
96 : /**
97 : * @returns The names of the MeshGenerators that were requested in the getMesh methods
98 : */
99 57503 : const std::set<MeshGeneratorName> & getRequestedMeshGenerators() const
100 : {
101 57503 : return _requested_mesh_generators;
102 : }
103 : /**
104 : * @returns The names of the MeshGenerators that were requested in the declareMeshForSub
105 : * methods
106 : */
107 39 : const std::set<MeshGeneratorName> & getRequestedMeshGeneratorsForSub() const
108 : {
109 39 : return _requested_mesh_generators_for_sub;
110 : }
111 :
112 : /**
113 : * Class that is used as a parameter to add[Parent/Child]() that allows only
114 : * MeshGeneratorSystem methods to call said methods
115 : */
116 : class AddParentChildKey
117 : {
118 : friend class MeshGeneratorSystem;
119 62304 : AddParentChildKey() {}
120 : AddParentChildKey(const AddParentChildKey &) {}
121 : };
122 :
123 : /**
124 : * Adds the MeshGenerator \p mg as a parent.
125 : *
126 : * Protected by the AddParentChildKey so that parents can only be
127 : * added by the MooseApp.
128 : */
129 : void addParentMeshGenerator(const MeshGenerator & mg, const AddParentChildKey);
130 : /**
131 : * Adds the MeshGenerator \p mg as a child.
132 : *
133 : * Protected by the AddParentChildKey so that parents can only be
134 : * added by the MooseApp.
135 : */
136 : void addChildMeshGenerator(const MeshGenerator & mg, const AddParentChildKey);
137 :
138 : /**
139 : * Gets the MeshGenerators that are parents to this MeshGenerator.
140 : */
141 147925 : const std::set<const MeshGenerator *, Comparator> & getParentMeshGenerators() const
142 : {
143 147925 : return _parent_mesh_generators;
144 : }
145 : /**
146 : * Gets the MeshGenerators that are children to this MeshGenerator.
147 : */
148 16650 : const std::set<const MeshGenerator *, Comparator> & getChildMeshGenerators() const
149 : {
150 16650 : return _child_mesh_generators;
151 : }
152 : /**
153 : * Gets the MeshGenerators that are children to this MeshGenerator.
154 : */
155 117 : const std::set<const MeshGenerator *, Comparator> & getSubMeshGenerators() const
156 : {
157 117 : return _sub_mesh_generators;
158 : }
159 :
160 : /**
161 : * @returns Whether or not the MeshGenerator with the name \p name is a parent of this
162 : * MeshGenerator.
163 : *
164 : * If \p direct = true, check only immediate parents of this generator. Otherwise, check
165 : * all parents.
166 : */
167 : bool isParentMeshGenerator(const MeshGeneratorName & name, const bool direct = true) const;
168 :
169 : /**
170 : * @returns Whether or not the MeshGenerator with the name \p name is a child of this
171 : * MeshGenerator.
172 : *
173 : * If \p direct = true, check only immediate children of this generator. Otherwise, check
174 : * all children.
175 : */
176 : bool isChildMeshGenerator(const MeshGeneratorName & name, const bool direct = true) const;
177 :
178 : /**
179 : * @returns Whether or not the name \p name is registered as a "null" mesh, that is,
180 : * a MeshGenerator that will not represent an input mesh when requested via getMesh.
181 : *
182 : * See declareNullMeshName().
183 : */
184 62710 : bool isNullMeshName(const MeshGeneratorName & name) const { return _null_mesh_names.count(name); }
185 :
186 : /**
187 : * Return whether or not to save the current mesh
188 : */
189 : bool hasSaveMesh() const;
190 :
191 : /**
192 : * @return Whether or not to output this mesh generator separately (output parameter is set)
193 : */
194 : bool hasOutput() const;
195 :
196 : /**
197 : * Return the name of the saved mesh
198 : */
199 : const std::string & getSavedMeshName() const;
200 :
201 : /**
202 : * @return Whether or not this generator has a generateData() implementation
203 : */
204 54406 : bool hasGenerateData() const { return hasGenerateData(_pars); }
205 :
206 : /**
207 : * @return Whether or not this generator has a generateCSG() implementation
208 : */
209 62413 : bool hasGenerateCSG() const { return hasGenerateCSG(_pars); }
210 :
211 : /**
212 : * @return Whether or not this generator is to be generated in data-only mode
213 : */
214 166304 : bool isDataOnly() const { return _data_only; }
215 :
216 : protected:
217 : /**
218 : * Generate the mesh data
219 : */
220 : virtual void generateData();
221 :
222 : /**
223 : * Generate the CSG representation of the mesh (or meshing operation) created by this mesh
224 : * generator
225 : */
226 : virtual std::unique_ptr<CSG::CSGBase> generateCSG();
227 :
228 : /**
229 : * Methods for writing out attributes to the mesh meta-data store, which can be retrieved from
230 : * most other MOOSE systems and is recoverable.
231 : */
232 : ///@{
233 : template <typename T, typename... Args>
234 : T & declareMeshProperty(const std::string & data_name, Args &&... args);
235 : template <typename T>
236 203365 : T & declareMeshProperty(const std::string & data_name, const T & data_value)
237 : {
238 203365 : return declareMeshProperty<T, const T &>(data_name, data_value);
239 : }
240 : ///@}
241 :
242 : /**
243 : * Method for updating attributes to the mesh meta-data store, which can only be invoked in
244 : * the MeshGenerator generate routine only if the mesh generator property has already been
245 : * declared.
246 : */
247 : ///@{
248 : template <typename T, typename... Args>
249 : T & setMeshProperty(const std::string & data_name, Args &&... args);
250 : template <typename T>
251 : T & setMeshProperty(const std::string & data_name, const T & data_value)
252 : {
253 : return setMeshProperty<T, const T &>(data_name, data_value);
254 : }
255 : ///@}
256 :
257 : /**
258 : * Method for copying attribute from input mesh meta-data store to current mesh meta-data store.
259 : * This may often be avoided as getMeshProperty calls can traverse the tree of mesh generators to
260 : * find a metadata instance
261 : */
262 : template <typename T>
263 : T & copyMeshProperty(const std::string & target_data_name,
264 : const std::string & source_data_name,
265 : const std::string & source_mesh)
266 : {
267 : return declareMeshProperty(target_data_name, getMeshProperty<T>(source_data_name, source_mesh));
268 : }
269 :
270 : /**
271 : * Method for copying attribute from input mesh meta-data store to current mesh meta-data store,
272 : * keeping source and target data names the same. This may often be avoided as getMeshProperty
273 : * calls can traverse the tree of mesh generators to find a metadata instance
274 : */
275 : template <typename T>
276 : T & copyMeshProperty(const std::string & source_data_name, const std::string & source_mesh)
277 : {
278 : return copyMeshProperty<T>(source_data_name, source_data_name, source_mesh);
279 : }
280 :
281 : /**
282 : * Takes the name of a MeshGeneratorName parameter and then gets a pointer to the
283 : * Mesh that MeshGenerator is going to create.
284 : *
285 : * That MeshGenerator is made to be a dependency of this one, so
286 : * will generate() its mesh first.
287 : *
288 : * @param param_name The name of the parameter that contains the name of the MeshGenerator
289 : * @param allow_invalid If true, will allow for invalid parameters and will return a nullptr
290 : * mesh if said parameter does not exist
291 : * @return The Mesh generated by that MeshGenerator
292 : *
293 : * NOTE: You MUST catch this by reference!
294 : */
295 : [[nodiscard]] std::unique_ptr<MeshBase> & getMesh(const std::string & param_name,
296 : const bool allow_invalid = false);
297 : /**
298 : * Like getMesh(), but for multiple generators.
299 : *
300 : * @returns The generated meshes
301 : */
302 : [[nodiscard]] std::vector<std::unique_ptr<MeshBase> *> getMeshes(const std::string & param_name);
303 : /**
304 : * Like \p getMesh(), but takes the name of another MeshGenerator directly.
305 : *
306 : * NOTE: You MUST catch this by reference!
307 : *
308 : * @return The Mesh generated by that MeshGenerator
309 : */
310 : [[nodiscard]] std::unique_ptr<MeshBase> &
311 : getMeshByName(const MeshGeneratorName & mesh_generator_name);
312 : /**
313 : * Like getMeshByName(), but for multiple generators.
314 : *
315 : * @returns The generated meshes
316 : */
317 : [[nodiscard]] std::vector<std::unique_ptr<MeshBase> *>
318 : getMeshesByName(const std::vector<MeshGeneratorName> & mesh_generator_names);
319 :
320 : /**
321 : * Takes the name of a MeshGeneratorName parameter and then gets a pointer to the
322 : * CSGBase object that MeshGenerator has created.
323 : *
324 : * NOTE: You MUST catch this by reference!
325 : *
326 : * @param param_name The name of the parameter that contains the name of the MeshGenerator
327 : * @return The CSGBase object generated by that MeshGenerator
328 : */
329 : [[nodiscard]] std::unique_ptr<CSG::CSGBase> & getCSGBase(const std::string & param_name);
330 :
331 : /**
332 : * Like \p getCSGBase(), but takes the name of another MeshGenerator directly.
333 : *
334 : * NOTE: You MUST catch this by reference!
335 : *
336 : * @param mesh_generator_name The name of the MeshGenerator associated with the CSGBase object
337 : * @return The CSGBase pointer generated by that MeshGenerator
338 : */
339 : [[nodiscard]] std::unique_ptr<CSG::CSGBase> &
340 : getCSGBaseByName(const MeshGeneratorName & mesh_generator_name);
341 :
342 : /**
343 : * Like \p getCSGBase(), but for multiple generators.
344 : *
345 : * NOTE: You MUST catch this by reference!
346 : *
347 : * @param param_name The name of the parameter that contains the names of MeshGenerator objects
348 : * @return Vector of CSGBase pointers associated with input parameter
349 : */
350 : [[nodiscard]] std::vector<std::unique_ptr<CSG::CSGBase> *>
351 : getCSGBases(const std::string & param_name);
352 :
353 : /**
354 : * Like \p getCSGBaseByName(), but for multiple generators.
355 : *
356 : * NOTE: You MUST catch this by reference!
357 : *
358 : * @param mesh_generator_names The names of MeshGenerator objects
359 : * @return Vector of CSGBase pointers associated with input parameter
360 : */
361 : [[nodiscard]] std::vector<std::unique_ptr<CSG::CSGBase> *>
362 : getCSGBasesByName(const std::vector<MeshGeneratorName> & mesh_generator_names);
363 :
364 : /**
365 : * Declares that a MeshGenerator referenced in the InputParameters is to be
366 : * used as a dependency of a sub MeshGenerator created by this MeshGenerator
367 : * (see addSubMeshGenerator)
368 : *
369 : * You _must_ declare all such MeshGenerators that are passed by parameter to this
370 : * MeshGenerator but instead used in a sub MeshGenerator. This is in order to
371 : * declare the intention to use an input mesh as a dependency for a sub generator
372 : * instead of this one.
373 : */
374 : void declareMeshForSub(const std::string & param_name);
375 : /**
376 : * Like declareMeshForSub(), but for multiple generators.
377 : */
378 : void declareMeshesForSub(const std::string & param_name);
379 : /**
380 : * Like declareMeshForSub(), but takes the name of another MeshGenerator directly.
381 : */
382 : void declareMeshForSubByName(const MeshGeneratorName & mesh_generator_name);
383 : /**
384 : * Like declareMeshForSubByName(), but for multiple generators.
385 : */
386 : void declareMeshesForSubByName(const std::vector<MeshGeneratorName> & mesh_generator_names);
387 :
388 : /**
389 : * Build a \p MeshBase object whose underlying type will be determined by the Mesh input file
390 : * block
391 : * @param dim The logical dimension of the mesh, e.g. 3 for hexes/tets, 2 for quads/tris. If the
392 : * caller doesn't specify a value for \p dim, then the value in the \p Mesh input file block will
393 : * be used
394 : */
395 : [[nodiscard]] std::unique_ptr<MeshBase>
396 : buildMeshBaseObject(unsigned int dim = libMesh::invalid_uint);
397 :
398 : /**
399 : * Build a replicated mesh
400 : * @param dim The logical dimension of the mesh, e.g. 3 for hexes/tets, 2 for quads/tris. If the
401 : * caller doesn't specify a value for \p dim, then the value in the \p Mesh input file block will
402 : * be used
403 : */
404 : [[nodiscard]] std::unique_ptr<ReplicatedMesh>
405 : buildReplicatedMesh(unsigned int dim = libMesh::invalid_uint);
406 :
407 : /**
408 : * Build a distributed mesh that has correct remote element removal behavior and geometric
409 : * ghosting functors based on the simulation objects
410 : * @param dim The logical dimension of the mesh, e.g. 3 for hexes/tets, 2 for quads/tris. If the
411 : * caller doesn't specify a value for \p dim, then the value in the \p Mesh input file block will
412 : * be used
413 : */
414 : [[nodiscard]] std::unique_ptr<DistributedMesh>
415 : buildDistributedMesh(unsigned int dim = libMesh::invalid_uint);
416 :
417 : /**
418 : * Construct a "subgenerator", a different MeshGenerator subclass
419 : * that will be added to the same MooseApp on the fly.
420 : *
421 : * @param type The type of MeshGenerator
422 : * @param name The name of the MeshGenerator
423 : * @param extra_input_parameters ... Additional InputParameters to pass
424 : *
425 : * Sub generators must be added in the order that they are executed.
426 : *
427 : * Any input dependencies for a sub generator that come from inputs for
428 : * this generator must first be declared with the declareMesh(es)ForSub()
429 : * method.
430 : *
431 : * You can use the output of a sub generator as a mesh in this generator
432 : * by calling getMesh() with the sub generator's name _after_ adding
433 : * said sub generator.
434 : */
435 : template <typename... Ts>
436 : void addMeshSubgenerator(const std::string & type,
437 : const std::string & name,
438 : Ts... extra_input_parameters);
439 :
440 : /**
441 : * Construct a "subgenerator", as above. User code is responsible
442 : * for constructing valid InputParameters.
443 : *
444 : * @param type The type of MeshGenerator
445 : * @param name The name of the MeshGenerator
446 : * @param params The parameters to use to construct the MeshGenerator
447 : */
448 : void
449 : addMeshSubgenerator(const std::string & type, const std::string & name, InputParameters params);
450 :
451 : /**
452 : * Registers the name \p name as a "null" mesh, which is a MeshGenerator used in
453 : * InputParameters that will not represent an input mesh when requested via getMesh.
454 : *
455 : * An example use case for this is when you as a developer want users to represent a hole
456 : * in a mesh pattern that is defined in input.
457 : *
458 : */
459 : void declareNullMeshName(const MeshGeneratorName & name);
460 :
461 : /// Pointer to the owning mesh
462 : MooseMesh * const _mesh;
463 :
464 : private:
465 : /**
466 : * Override of the default prefix to use when getting mesh properties.
467 : *
468 : * Until we support getting mesh properties from other mesh generators (which is coming),
469 : * we will default to properties returned by this generator.
470 : */
471 407438 : virtual std::string meshPropertyPrefix(const std::string &) const override final
472 : {
473 407438 : return name();
474 : }
475 :
476 : /**
477 : * Helper for performing error checking in the getMesh methods.
478 : */
479 : void checkGetMesh(const MeshGeneratorName & mesh_generator_name,
480 : const std::string & param_name) const;
481 :
482 : /**
483 : * Helper for getting a MeshGeneratorName parameter
484 : */
485 : const MeshGeneratorName * getMeshGeneratorNameFromParam(const std::string & param_name,
486 : const bool allow_invalid) const;
487 : /**
488 : * Helper for getting a std::vector<MeshGeneratorName> parameter
489 : */
490 : const std::vector<MeshGeneratorName> &
491 : getMeshGeneratorNamesFromParam(const std::string & param_name) const;
492 :
493 : /**
494 : * Helper for getting a writable reference to a mesh property, used in
495 : * declareMeshProperty and setMeshProperty.
496 : */
497 : RestartableDataValue & setMeshPropertyHelper(const std::string & data_name);
498 :
499 : /// The names of the MeshGenerators that were requested in the getMesh methods
500 : std::set<MeshGeneratorName> _requested_mesh_generators;
501 : /// The names of the MeshGenerators that were requested in the declareMeshForSub methods
502 : std::set<MeshGeneratorName> _requested_mesh_generators_for_sub;
503 : /// The meshes that were requested by this MeshGenerator; used to verify that
504 : /// any input meshes that are requested are properly released after generation
505 : std::vector<std::pair<std::string, std::unique_ptr<MeshBase> *>> _requested_meshes;
506 : /// The CSGBase objects that were requested by this MeshGenerator; used to verify that
507 : /// any input meshes that are requested are properly released after generation
508 : std::vector<std::pair<std::string, std::unique_ptr<CSG::CSGBase> *>> _requested_csg_bases;
509 :
510 : /// A nullptr to use for when inputs aren't specified
511 : std::unique_ptr<MeshBase> _null_mesh = nullptr;
512 :
513 : /// The MeshGenerators that are parents to this MeshGenerator
514 : std::set<const MeshGenerator *, Comparator> _parent_mesh_generators;
515 : /// The MeshGenerators that are children to this MeshGenerator
516 : std::set<const MeshGenerator *, Comparator> _child_mesh_generators;
517 : /// The sub MeshGenerators constructed by this MeshGenerator
518 : std::set<const MeshGenerator *, Comparator> _sub_mesh_generators;
519 :
520 : /// The declared "null" mesh names that will not represent a mesh in input; see declareNullMeshName()
521 : std::set<std::string> _null_mesh_names;
522 :
523 : /// A user-defined name to save the mesh
524 : const std::string & _save_with_name;
525 :
526 : /// Whether or not this mesh generator will run in data only mode
527 : const bool _data_only;
528 : };
529 :
530 : template <typename T, typename... Args>
531 : T &
532 203701 : MeshGenerator::declareMeshProperty(const std::string & data_name, Args &&... args)
533 : {
534 203701 : if (!_app.constructingMeshGenerators())
535 4 : mooseError("Can only call declareMeshProperty() during MeshGenerator construction");
536 :
537 : // We sort construction ordering so that we _must_ declare before retrieving
538 203697 : if (hasMeshProperty(data_name))
539 4 : mooseError("While declaring mesh property '",
540 : data_name,
541 : "' with type '",
542 : MooseUtils::prettyCppType<T>(),
543 : "',\nsaid property has already been declared with type '",
544 4 : setMeshPropertyHelper(data_name).type(),
545 : "'");
546 :
547 203693 : const auto full_name = meshPropertyName(data_name);
548 203693 : auto new_T_value =
549 203693 : std::make_unique<RestartableData<T>>(full_name, nullptr, std::forward<Args>(args)...);
550 : auto value =
551 203693 : &_app.registerRestartableData(std::move(new_T_value), 0, false, MooseApp::MESH_META_DATA);
552 : mooseAssert(value->declared(), "Should be declared");
553 :
554 203693 : RestartableData<T> * T_value = dynamic_cast<RestartableData<T> *>(value);
555 : mooseAssert(T_value, "Bad cast");
556 :
557 407386 : return T_value->set();
558 203693 : }
559 :
560 : template <typename T, typename... Args>
561 : T &
562 22 : MeshGenerator::setMeshProperty(const std::string & data_name, Args &&... args)
563 : {
564 22 : if (_app.actionWarehouse().getCurrentTaskName() != "execute_mesh_generators")
565 0 : mooseError("Updating mesh meta data with setMeshProperty() can only be called during "
566 : "MeshGenerator::generate()");
567 :
568 22 : if (!hasMeshProperty(data_name))
569 0 : mooseError("Failed to get the mesh property '", data_name, "'");
570 22 : RestartableDataValue * value = &setMeshPropertyHelper(data_name);
571 22 : RestartableData<T> * T_value = dynamic_cast<RestartableData<T> *>(value);
572 22 : if (!T_value)
573 0 : mooseError("While retrieving mesh property '",
574 : data_name,
575 : "' with type '",
576 : MooseUtils::prettyCppType<T>(),
577 : "',\nthe property was found with type '",
578 0 : value->type(),
579 : "'");
580 :
581 : // Set the value if someone provided arguments to set it to
582 : if constexpr (sizeof...(args) > 0)
583 : T_value->set() = T(std::forward<Args>(args)...);
584 :
585 22 : return T_value->set();
586 : }
587 :
588 : template <typename... Ts>
589 : void
590 9 : MeshGenerator::addMeshSubgenerator(const std::string & type,
591 : const std::string & name,
592 : Ts... extra_input_parameters)
593 : {
594 9 : InputParameters subgenerator_params = _app.getFactory().getValidParams(type);
595 :
596 9 : subgenerator_params.setParameters(extra_input_parameters...);
597 :
598 9 : addMeshSubgenerator(type, name, subgenerator_params);
599 9 : }
|