https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MeshGeneratorSystem.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 "MeshGeneratorSystem.h"
11
12#include "MooseApp.h"
13#include "MeshGenerator.h"
14#include "DependencyResolver.h"
15
16#include "libmesh/mesh_tools.h"
17
18const std::string MeshGeneratorSystem::data_driven_generator_param = "data_driven_generator";
20 "allow_data_driven_mesh_generation";
21
23 : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
24 ParallelObject(app),
25 _app(app),
26 _verbose(false),
27 _csg_only(false)
28{
29}
30
31void
33 const std::string & name,
34 const InputParameters & params)
35{
36 mooseAssert(!_mesh_generator_params.count(name), "Already exists");
38 std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
39
40 // This should be a sub mesh generator. We can assume this because if we're in the middle of
41 // constructing mesh generators (not "adding" them, where we simply store their parameters)
44}
45
46const MeshGenerator &
48 const std::string & name,
49 InputParameters params)
50{
52 mooseError("Can only call appendMeshGenerator() during the append_mesh_generator task");
53 const auto param_name_mg_name_pairs = getMeshGeneratorParamDependencies(params, true);
54
55 // Make sure this mesh generator has one and _only_ one input, in the "input" parameter,
56 // Or several, listed in the "inputs" parameter
57 if ((param_name_mg_name_pairs.size() == 0) ||
58 (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first != "input" &&
59 param_name_mg_name_pairs[0].first != "inputs") ||
60 (param_name_mg_name_pairs.size() > 1 && param_name_mg_name_pairs[0].first != "inputs"))
61 mooseError("While adding ",
62 type,
63 " '",
64 name,
65 "' via appendMeshGenerator():\nCan only append a mesh generator that takes a "
66 "single input mesh generator via the parameter named 'input' or 'inputs'.");
67
68 // If no final generator is set, we need to make sure that we have one; we will hit
69 // this the first time we add an appended MeshGenerator and only need to do it once.
70 // We'll then generate the final ordering within the execution phase. We'll also
71 // clear the ordering because it could be invalid if we append any more generators,
72 // and we'll be re-ordering within executeMeshgenerators() anyway (where we don't
73 // keep track of any state for the sake of simpler logic)
74 if (_final_generator_name.empty())
75 {
76 if (_mesh_generators.empty())
77 mooseError("Cannot use appendMeshGenerator() because there is not a generator to append to!");
78
81 }
82
83 // Set the final generator as the input if a single generator
84 mooseAssert(hasMeshGenerator(_final_generator_name), "Missing final generator");
85 if (params.have_parameter<MeshGeneratorName>("input"))
86 params.set<MeshGeneratorName>("input") = _final_generator_name;
87 // We'll trust the final combiner generator with its list of inputs
88
89 // Keep track of the new final generator
91
92 // Need to add this to the param map so that createMeshGenerator can use it
93 mooseAssert(!_mesh_generator_params.count(name), "Already exists");
95 std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
96
97 return *createMeshGenerator(name);
98}
99
100std::vector<std::pair<std::string, MeshGeneratorName>>
102 const bool allow_empty /* = false */) const
103{
104 std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
105
106 auto add_dependency =
107 [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
108 {
109 if (dependency.size() || allow_empty)
110 dependencies.emplace_back(param_name, dependency);
111 };
112
113 for (const auto & [name, param] : params)
114 if (const auto dependency =
115 dynamic_cast<const libMesh::Parameters::Parameter<MeshGeneratorName> *>(param.get()))
116 add_dependency(name, dependency->get());
117 else if (const auto dependencies = dynamic_cast<
119 param.get()))
120 {
121 if (allow_empty && dependencies->get().empty())
122 add_dependency(name, std::string());
123 for (const auto & dependency : dependencies->get())
124 add_dependency(name, dependency);
125 }
126
127 return dependencies;
128}
129
130void
132{
133 mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "create_added_mesh_generators",
134 "Should not run now");
135
136 // No generators were added via addMeshGenerator()
137 if (_mesh_generator_params.empty())
138 return;
139
141
142 // Define the dependencies known so far
143 for (const auto & [name, type_params_pair] : _mesh_generator_params)
144 {
145 resolver.addItem(name);
146 for (const auto & param_dependency_pair :
147 getMeshGeneratorParamDependencies(type_params_pair.second))
148 resolver.addEdge(param_dependency_pair.second, name);
149 }
150
151 std::vector<std::vector<std::string>> ordered_generators;
152 try
153 {
154 ordered_generators = resolver.getSortedValuesSets();
155 }
157 {
158 mooseError("Cyclic dependencies detected in mesh generation: ",
159 MooseUtils::join(e.getCyclicDependencies(), " <- "));
160 }
161
162 const auto & moose_mesh = _app.actionWarehouse().getMesh();
163
164 // If there is no mesh
165 if (!moose_mesh.get())
166 mooseError("No mesh created. Either add a Mesh, an ActionComponents or a Components block");
167
168 // If we're using data-driven generation, find that requirement now
169 mooseAssert(!_data_driven_generator_name, "Should not be set");
170 if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
171 moose_mesh->isParamValid(data_driven_generator_param))
172 {
174 moose_mesh->paramError(
176 "This application does not support data-driven mesh generation.\n\nThis generation is an "
177 "advanced feature and must be enabled on the application via the '",
179 "' parameter.");
180
181 mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
182 "Assumption for mesh type is now invalid");
183
184 _data_driven_generator_name = moose_mesh->getParam<std::string>(data_driven_generator_param);
186 moose_mesh->paramError(data_driven_generator_param,
187 "The data driven generator '",
189 "' does not exist");
190 }
191
192 // Check compatibility for CLI / meshing options with csg_only
193 const bool csg_only = getCSGOnly();
194 if (csg_only && _data_driven_generator_name)
195 moose_mesh->paramError(data_driven_generator_param,
196 "This parameter should not be set in conjunction with --csg-only");
197
198 // Construct all of the mesh generators that we know exist
199 for (const auto & generator_names : ordered_generators)
200 for (const auto & generator_name : generator_names)
201 if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
202 {
203 auto & params = it->second.second;
204
205 // Determine now if we need to run this in data only mode
206 const bool data_only =
207 (csg_only ||
209 resolver.dependsOn(getDataDrivenGeneratorName(), generator_name)));
210 params.set<bool>(MeshGenerator::data_only_param) = data_only;
211
212 createMeshGenerator(generator_name);
213
214 if (csg_only && !getMeshGenerator(generator_name).hasGenerateCSG())
215 mooseError("Mesh generator ",
216 generator_name,
217 " cannot be used in csg-only mode since it does not have a generateCSG "
218 "implementation");
219
220 mooseAssert(data_only == getMeshGenerator(generator_name).isDataOnly(),
221 "Inconsistent data only");
222 }
223
224 mooseAssert(_mesh_generator_params.empty(), "Should be empty");
225 mooseAssert(_final_generator_name.empty(), "Should be unset at this point");
226
227 // Set the final generator if we have one set by the user
228 // and if so make sure it also exists
229 if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
230 moose_mesh->isParamValid("final_generator"))
231 {
232 mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
233 "Assumption for mesh type is now invalid");
234
235 _final_generator_name = moose_mesh->getParam<std::string>("final_generator");
237 moose_mesh->paramError("final_generator",
238 "The forced final MeshGenerator '",
240 "' does not exist");
241 }
242}
243
244void
246{
247 mooseAssert(_app.constructingMeshGenerators() ||
248 _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
249 "Incorrect call time");
250 mooseAssert(_ordered_mesh_generators.empty(), "Already ordered");
251 mooseAssert(_mesh_generators.size(), "No mesh generators to order");
252
253 TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
254
255 // We dare not sort these based on address!
257
258 // The mesh generators that must be called
259 // This is needed to mark the generators that could be cut due to a
260 // final generator being set, but should still be called because they're
261 // either being saved in memory or as output
262 std::vector<std::string> required_generators;
263 for (const auto & it : _mesh_generators)
264 if (it.second->hasSaveMesh() || it.second->hasOutput())
265 required_generators.push_back(it.second->name());
266
267 // The mesh generator tree should have all the mesh generators that
268 // The final generator depends on and all the mesh generators
269 // with 'save in' flag. Here we loop over all the mesh generators
270 // and conditionally add all of the dependencies into the resolver
271 for (const auto & it : _mesh_generators)
272 {
273 MeshGenerator * mg = it.second.get();
274
275 // The mesh generator has to meet one of the following conditions:
276 // Final mesh generator is not set, so we build the whole tree
277 if (_final_generator_name.empty() ||
278 // This mesh generator is the final generator
279 mg->name() == _final_generator_name ||
280 // This needs to be saved or output
281 mg->hasSaveMesh() || mg->hasOutput() ||
282 // Final mesh generator set and is a child of this generator
284 // This is a dependency of a generator that needs to be saved or output
285 std::find_if(required_generators.begin(),
286 required_generators.end(),
287 [&mg](const auto & name) { return mg->isChildMeshGenerator(name, false); }) !=
288 required_generators.end())
289 {
290 resolver.addItem(mg);
291 for (const auto & dep_mg : mg->getParentMeshGenerators())
292 resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
293 }
294 }
295
296 // ...and sort them
297 try
298 {
300 }
301 // It is _quite_ hard to trigger this to test it. I've tried to no avail.
302 // Now that we...
303 // - check and sort up front
304 // - know if dependencies exist at the time of requesting them
305 // - require that sub generators depend only on other sub generators in an object's
306 // tree + input dependencies that we explicitly declare
307 // I don't think it's possible. But we'll leave it here anyway and it
308 // definitely will not be covered
310 {
311 const auto & cycle = e.getCyclicDependencies();
312 std::vector<std::string> names(cycle.size());
313 for (const auto i : index_range(cycle))
314 names[i] = cycle[i]->name();
315
316 mooseError("Cyclic dependencies detected in mesh generation: ",
317 MooseUtils::join(names, " <- "));
318 }
319
320 mooseAssert(_ordered_mesh_generators.size(), "No mesh generators found");
321
322 const auto & final_generators = _ordered_mesh_generators.back();
323
324 // We haven't forced a final generator yet
325 if (_final_generator_name.empty())
326 {
327 mooseAssert(final_generators.size(), "Empty vector");
328
329 // See if we have multiple independent trees of generators
330 const auto ancestor_list = resolver.getAncestors(final_generators.back());
331 if (ancestor_list.size() != resolver.size() && _final_generator_name.empty())
332 {
333 // Need to remove duplicates and possibly perform a difference so we'll import our list
334 // into a set for these operations.
335 std::set<MeshGenerator *, MeshGenerator::Comparator> ancestors(ancestor_list.begin(),
336 ancestor_list.end());
337 // Get all of the items from the resolver so we can compare against the tree from the
338 // final generator we just pulled.
339 const auto & allValues = resolver.getSortedValues();
340 decltype(ancestors) all(allValues.begin(), allValues.end());
341
342 decltype(ancestors) ind_tree;
343 std::set_difference(all.begin(),
344 all.end(),
345 ancestors.begin(),
346 ancestors.end(),
347 std::inserter(ind_tree, ind_tree.end()));
348
349 std::ostringstream oss;
350 oss << "Your MeshGenerator tree contains multiple possible generator outputs :\n\""
351 << final_generators.back()->name()
352 << "\" and one or more of the following from an independent set: \"";
353 bool first = true;
354 for (const auto & gen : ind_tree)
355 {
356 if (!first)
357 oss << ", ";
358 else
359 first = false;
360
361 oss << gen->name();
362 }
363 oss << "\"\n\nThis may be due to a missing dependency or may be intentional. Please either\n"
364 "- check that all the mesh generators are connected as a tree and culminate in a "
365 "single final mesh. Having one wrong 'input=mg' parameter is the most common error\n"
366 "- add additional dependencies to remove the ambiguity if you are using a user-built "
367 "MeshGenerator\n"
368 "- if you intend to execute a subset of the defined generators (uncommon), select the"
369 " final MeshGenerator in the [Mesh] block with the \"final_generator\" parameter.";
370 mooseError(oss.str());
371 }
372
373 _final_generator_name = final_generators.back()->name();
374 }
375 else
376 mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
377}
378
379void
381{
382 libmesh_parallel_only(comm());
383
384 // we do not need to do this when there are no mesh generators
385 if (_mesh_generators.empty())
386 return;
387
388 // Order the generators
390
391 // Save all meshes marked to to_save_in_meshes and save in error checking
392 std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
393 for (const auto & generator_set : _ordered_mesh_generators)
394 for (const auto & generator : generator_set)
395 if (generator->hasSaveMesh())
396 {
397 if (_final_generator_name == generator->name())
398 generator->paramError("save_with_name",
399 "Cannot use the save in capability with the final mesh generator");
400 if (getCSGOnly())
401 generator->paramError("save_with_name", "Cannot use in conjunction with --csg-only");
402 to_save_in_meshes.emplace(generator->getSavedMeshName(),
403 &getMeshGeneratorOutput(generator->name()));
404 }
405 // Grab the outputs from the final generator so MeshGeneratorMesh can pick it up
406 to_save_in_meshes.emplace(mainMeshGeneratorName(),
408
409 // Run the MeshGenerators in the proper order
410 for (const auto & generator_set : _ordered_mesh_generators)
411 {
412 for (const auto & generator : generator_set)
413 {
414 mooseAssert(comm().verify(generator->typeAndName().size()) &&
415 comm().verify(generator->typeAndName()),
416 "Mesh generator generation is parallel inconsistent; about to execute "
417 << generator->typeAndName());
418
419 const auto & name = generator->name();
420 if (_verbose)
421 _app._console << " [DBG] Executing mesh generator (" << COLOR_GREEN << std::setw(20) << name
422 << COLOR_DEFAULT << ") in type (" << COLOR_GREEN << generator->type()
423 << COLOR_DEFAULT << ")" << std::endl;
424 auto current_mesh = generator->generateInternal();
425
426 if (!generator->isDataOnly())
427 mooseAssert(comm().verify(current_mesh->is_prepared()),
428 "Mesh prepared state after " << generator->typeAndName()
429 << " is parallel inconsistent");
430
431 mooseAssert(comm().verify(generator->typeAndName().size()) &&
432 comm().verify(generator->typeAndName()),
433 "Mesh generator generation is parallel inconsistent; just executed "
434 << generator->typeAndName());
435
436 // Only generating data for this generator
437 if (generator->isDataOnly())
438 {
439 mooseAssert(!current_mesh, "Should not have a mesh");
440 continue;
441 }
442
443#ifdef DEBUG
444 // Assert that the mesh is either marked as not prepared or if it is marked as prepared,
445 // that it's *actually* prepared.
446 //
447 // In newer version of libMesh, this also asserts that a mesh
448 // marked as partially prepared is indeed prepared in (at least)
449 // the aspects which are so marked.
450 if (!MeshTools::valid_is_prepared(*current_mesh))
451 generator->mooseError(
452 "The generated mesh is marked as (at least partially) prepared but is not "
453 "prepared in the marked sense(s). Please edit the '",
454 generator->type(),
455 "' class to call 'unset_is_prepared()', or more fine-grained "
456 "alternatives as appropriate.");
457#endif
458
459 // Now we need to possibly give this mesh to downstream generators
460 auto & outputs = _mesh_generator_outputs[name];
461
462 if (outputs.size())
463 {
464 auto & first_output = *outputs.begin();
465
466 first_output = std::move(current_mesh);
467
468 const auto & copy_from = *first_output;
469
470 auto output_it = ++outputs.begin();
471
472 // For all of the rest we need to make a copy
473 for (; output_it != outputs.end(); ++output_it)
474 (*output_it) = copy_from.clone();
475 }
476 }
477 }
478
479 // No save in meshes exist in csg only mode
480 if (getCSGOnly())
481 return;
482
483 // Grab all the valid save in meshes from the temporary map to_save_in_meshes
484 // and store them in _save_in_meshes
485 for (auto & [name, mesh_ptr] : to_save_in_meshes)
486 {
487 mooseAssert(mesh_ptr, "Invalid pointer");
488 mooseAssert(*mesh_ptr, "Invalid pointer");
489 if (name != mainMeshGeneratorName())
490 mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
491 _save_in_meshes[name] = std::move(*mesh_ptr);
492 }
493}
494
495std::shared_ptr<MeshGenerator>
496MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
497{
498 libmesh_parallel_only(comm());
499 mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
500
501 const auto find_params = _mesh_generator_params.find(generator_name);
502 mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
503 const auto & [type, params] = find_params->second;
504 mooseAssert(comm().verify(type + generator_name), "Inconsistent construction order");
505
506 std::shared_ptr<MeshGenerator> mg =
507 _app.getFactory().create<MeshGenerator>(type, generator_name, params);
508
509 if (mg->hasSaveMesh())
510 {
511 if (_save_in_meshes.count(mg->getSavedMeshName()))
512 mg->paramError("save_with_name",
513 "The save with name '",
514 mg->getSavedMeshName(),
515 "' has already been used");
516 _save_in_meshes.emplace(mg->getSavedMeshName(), nullptr);
517 }
518
519 // Setup the children and parents
520 for (const auto & dependency : mg->getRequestedMeshGenerators())
521 {
522 // We _shouldn't_ hit this; now that we enforce construction ordering we do
523 // all of this error checking at construction time because the info is available
524 mooseAssert(hasMeshGenerator(dependency), "Missing dependency");
525
526 auto & dependency_mg = getMeshGeneratorInternal(dependency);
527 mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
528 dependency_mg.addChildMeshGenerator(*mg, MeshGenerator::AddParentChildKey());
529 }
530
531 // Loop through all of the MeshGeneratorName and std::vector<MeshGeneratorName>
532 // parameters (meshes that we should depend on), and make sure that either:
533 // - We directly depend on them and requested a mesh from them
534 // - We created a sub generator that depends on them and we declared it
535 for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
536 {
537 const auto & param_name = param_dependency_pair.first;
538 const auto & dependency_name = param_dependency_pair.second;
539
540 if (mg->isNullMeshName(dependency_name))
541 continue;
542
543 // True if this dependency was requested and is a parent
544 if (mg->isParentMeshGenerator(dependency_name))
545 {
546 mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
547 continue;
548 }
549
550 // Whether or not this is a dependency of at least one SubGenerator
551 auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
552 mg->getSubMeshGenerators().end(),
553 [&dependency_name](const auto & mg)
554 { return mg->isParentMeshGenerator(dependency_name); });
555 const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
556
557 // This should be used by a sub generator
558 if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
559 {
560 if (!is_sub_dependency)
561 mg->mooseError("The sub generator dependency declared from MeshGenerator '",
562 dependency_name,
563 "' from the parameter '",
564 param_name,
565 "' was not used.\n\nDependencies that are declared by declareMeshForSub() "
566 "must be used as an input to a sub generator created by this object.");
567 }
568 // This was used by a sub generator but wasn't declared
569 else if (is_sub_dependency)
570 mg->mooseError(
571 "The MeshGenerator '",
572 dependency_name,
573 "' was referenced in the parameter '",
574 param_name,
575 "' and used in the sub generator ",
576 (*find_sub_dependency)->type(),
577 " '",
578 (*find_sub_dependency)->name(),
579 "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
580 mg->type(),
581 " to include a call to declareMesh(es)ForSub(\"",
582 param_name,
583 "\") in the constructor.");
584 // Isn't used at all
585 else
586 mg->mooseError(
587 "You failed to request the generated mesh(es) for the parameter '",
588 param_name,
589 "'.\n\nIn specific, the mesh from MeshGenerator '",
590 dependency_name,
591 "' was not requested.\n\nTo correct this, you should remove the parameter if the "
592 "mesh(es)\nare not needed, or request the mesh(es) with getMesh()/getMeshes().");
593 }
594
595 mooseAssert(!_mesh_generators.count(generator_name), "Already created");
596 _mesh_generators.emplace(generator_name, mg);
597 mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
598 _mesh_generator_outputs[generator_name];
599 if (getCSGOnly())
600 {
601 mooseAssert(!_csg_base_outputs.count(generator_name), "CSG already exists");
602 _csg_base_outputs[generator_name];
603 }
604 _mesh_generator_params.erase(find_params);
605
606 return mg;
607}
608
609std::unique_ptr<MeshBase> &
610MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
611{
612 mooseAssert(_app.constructingMeshGenerators() ||
613 _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
614 "Incorrect call time");
615
616 auto it = _mesh_generator_outputs.find(name);
617 mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
618 it->second.push_back(nullptr);
619 return it->second.back();
620}
621
622bool
623MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
624{
625 return _mesh_generators.count(name);
626}
627
628bool
629MeshGeneratorSystem::hasMeshGeneratorParams(const MeshGeneratorName & name) const
630{
631 return _mesh_generator_params.count(name);
632}
633
634const MeshGenerator &
635MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
636{
637 const auto it = _mesh_generators.find(name);
638 if (it == _mesh_generators.end())
639 mooseError("Failed to find a MeshGenerator with the name '", name, "'");
640 mooseAssert(it->second, "Invalid shared pointer");
641 return *it->second;
642}
643
644std::vector<std::string>
646{
647 std::vector<std::string> names;
648 for (auto & pair : _mesh_generators)
649 names.push_back(pair.first);
650 return names;
651}
652
653std::vector<std::string>
655{
656 std::vector<std::string> names;
657 for (auto & pair : _save_in_meshes)
658 names.push_back(pair.first);
659 return names;
660}
661
662std::unique_ptr<MeshBase>
663MeshGeneratorSystem::getSavedMesh(const std::string & name)
664{
665 auto find_mesh = _save_in_meshes.find(name);
666 if (find_mesh == _save_in_meshes.end())
667 mooseError("Failed to find a saved mesh with the name '", name, "'");
668
669 auto & mesh_unique_ptr = find_mesh->second;
670 if (!mesh_unique_ptr)
671 mooseError("While getting the saved mesh generator '",
672 name,
673 "', said mesh has already been retrieved");
674
675 return std::move(mesh_unique_ptr);
676}
677
678bool
680{
681 return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
682}
683
684bool
689
690const std::string &
696
697void
699 const std::string & message) const
700{
701 const auto & moose_mesh = _app.actionWarehouse().getMesh();
702 moose_mesh->paramError(data_driven_generator_param,
703 "The generator '",
705 "' cannot be used in data-driven mode because the parent ",
706 generator.typeAndName(),
707 " ",
708 message);
709}
710
711void
716
717void
718MeshGeneratorSystem::saveOutputCSGBase(const MeshGeneratorName generator_name,
719 std::unique_ptr<CSG::CSGBase> & csg_base)
720{
721 auto & outputs = _csg_base_outputs[generator_name];
722
723 // Store CSGBase instance for any downstream MG's that request it, creating copies
724 // as needed
725 if (outputs.size())
726 {
727 // Set first output to csg_base
728 auto & first_output = *outputs.begin();
729 first_output = std::move(csg_base);
730 const auto & copy_from = *first_output;
731 auto output_it = ++outputs.begin();
732 // For all of the rest we create a clone of csg_base
733 for (; output_it != outputs.end(); ++output_it)
734 (*output_it) = copy_from.clone();
735 }
736}
737
738std::unique_ptr<CSG::CSGBase> &
740{
741 mooseAssert(_app.constructingMeshGenerators() ||
742 _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
743 "Incorrect call time");
744
745 auto it = _csg_base_outputs.find(name);
746 mooseAssert(it != _csg_base_outputs.end(), "CSG mesh not initialized");
747 it->second.push_back(nullptr);
748 return it->second.back();
749}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
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.
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition Factory.C:142
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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.
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
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 &params)
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 &params, 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
bool hasOutput() const
Base class for MOOSE-based applications.
Definition MooseApp.h:110
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
Definition MooseApp.h:217
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Definition MooseApp.C:3499
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition MooseApp.h:407
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
std::string typeAndName() const
Get the class's combined type and name; useful in error handling.
Definition MooseBase.C:57
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
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 ...
Definition MooseBase.h:457
Interface for objects interacting with the PerfGraph.
const Parallel::Communicator & comm() const
bool valid_is_prepared(const MeshBase &mesh)