https://mooseframework.inl.gov
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 
18 using namespace libMesh;
19 
20 const std::string MeshGeneratorSystem::data_driven_generator_param = "data_driven_generator";
22  "allow_data_driven_mesh_generation";
23 
25  : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
26  ParallelObject(app),
27  _app(app),
28  _has_bmbb(false),
29  _verbose(false),
30  _csg_only(false)
31 {
32 }
33 
34 void
35 MeshGeneratorSystem::addMeshGenerator(const std::string & type,
36  const std::string & name,
37  const InputParameters & params)
38 {
39  mooseAssert(!_mesh_generator_params.count(name), "Already exists");
40  _mesh_generator_params.emplace(
41  std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
42 
43  // This should be a sub mesh generator. We can assume this because if we're in the middle of
44  // constructing mesh generators (not "adding" them, where we simply store their parameters)
47 
48  if (type == "BreakMeshByBlockGenerator")
49  _has_bmbb = true;
50 }
51 
52 const MeshGenerator &
54  const std::string & name,
55  InputParameters params)
56 {
58  mooseError("Can only call appendMeshGenerator() during the append_mesh_generator task");
59  const auto param_name_mg_name_pairs = getMeshGeneratorParamDependencies(params, true);
60 
61  // Make sure this mesh generator has one and _only_ one input, in the "input" parameter,
62  // Or several, listed in the "inputs" parameter
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"))
67  mooseError("While adding ",
68  type,
69  " '",
70  name,
71  "' via appendMeshGenerator():\nCan only append a mesh generator that takes a "
72  "single input mesh generator via the parameter named 'input' or 'inputs'.");
73 
74  // If no final generator is set, we need to make sure that we have one; we will hit
75  // this the first time we add an appended MeshGenerator and only need to do it once.
76  // We'll then generate the final ordering within the execution phase. We'll also
77  // clear the ordering because it could be invalid if we append any more generators,
78  // and we'll be re-ordering within executeMeshgenerators() anyway (where we don't
79  // keep track of any state for the sake of simpler logic)
80  if (_final_generator_name.empty())
81  {
82  if (_mesh_generators.empty())
83  mooseError("Cannot use appendMeshGenerator() because there is not a generator to append to!");
84 
87  }
88 
89  // Set the final generator as the input if a single generator
90  mooseAssert(hasMeshGenerator(_final_generator_name), "Missing final generator");
91  if (params.have_parameter<MeshGeneratorName>("input"))
92  params.set<MeshGeneratorName>("input") = _final_generator_name;
93  // We'll trust the final combiner generator with its list of inputs
94 
95  // Keep track of the new final generator
97 
98  // Need to add this to the param map so that createMeshGenerator can use it
99  mooseAssert(!_mesh_generator_params.count(name), "Already exists");
100  _mesh_generator_params.emplace(
101  std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
102 
103  return *createMeshGenerator(name);
104 }
105 
106 std::vector<std::pair<std::string, MeshGeneratorName>>
108  const bool allow_empty /* = false */) const
109 {
110  std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
111 
112  auto add_dependency =
113  [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
114  {
115  if (dependency.size() || allow_empty)
116  dependencies.emplace_back(param_name, dependency);
117  };
118 
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>> *>(
125  param.get()))
126  {
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);
131  }
132 
133  return dependencies;
134 }
135 
136 void
138 {
139  mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "create_added_mesh_generators",
140  "Should not run now");
141 
142  // No generators were added via addMeshGenerator()
143  if (_mesh_generator_params.empty())
144  return;
145 
147 
148  // Define the dependencies known so far
149  for (const auto & [name, type_params_pair] : _mesh_generator_params)
150  {
151  resolver.addItem(name);
152  for (const auto & param_dependency_pair :
153  getMeshGeneratorParamDependencies(type_params_pair.second))
154  resolver.addEdge(param_dependency_pair.second, name);
155  }
156 
157  std::vector<std::vector<std::string>> ordered_generators;
158  try
159  {
160  ordered_generators = resolver.getSortedValuesSets();
161  }
163  {
164  mooseError("Cyclic dependencies detected in mesh generation: ",
166  }
167 
168  const auto & moose_mesh = _app.actionWarehouse().getMesh();
169 
170  // If there is no mesh
171  if (!moose_mesh.get())
172  mooseError("No mesh created. Either add a Mesh, an ActionComponents or a Components block");
173 
174  // If we're using data-driven generation, find that requirement now
175  mooseAssert(!_data_driven_generator_name, "Should not be set");
176  if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
177  moose_mesh->isParamValid(data_driven_generator_param))
178  {
179  if (!hasDataDrivenAllowed())
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 '",
185  "' parameter.");
186 
187  mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
188  "Assumption for mesh type is now invalid");
189 
190  _data_driven_generator_name = moose_mesh->getParam<std::string>(data_driven_generator_param);
192  moose_mesh->paramError(data_driven_generator_param,
193  "The data driven generator '",
195  "' does not exist");
196  }
197 
198  // Check compatibility for CLI / meshing options with csg_only
199  const bool csg_only = getCSGOnly();
200  if (csg_only && _data_driven_generator_name)
201  moose_mesh->paramError(data_driven_generator_param,
202  "This parameter should not be set in conjunction with --csg-only");
203 
204  // Construct all of the mesh generators that we know exist
205  for (const auto & generator_names : ordered_generators)
206  for (const auto & generator_name : generator_names)
207  if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
208  {
209  auto & params = it->second.second;
210 
211  // Determine now if we need to run this in data only mode
212  const bool data_only =
213  (csg_only ||
215  resolver.dependsOn(getDataDrivenGeneratorName(), generator_name)));
216  params.set<bool>(MeshGenerator::data_only_param) = data_only;
217 
218  createMeshGenerator(generator_name);
219 
220  if (csg_only && !getMeshGenerator(generator_name).hasGenerateCSG())
221  mooseError("Mesh generator ",
222  generator_name,
223  " cannot be used in csg-only mode since it does not have a generateCSG "
224  "implementation");
225 
226  mooseAssert(data_only == getMeshGenerator(generator_name).isDataOnly(),
227  "Inconsistent data only");
228  }
229 
230  mooseAssert(_mesh_generator_params.empty(), "Should be empty");
231  mooseAssert(_final_generator_name.empty(), "Should be unset at this point");
232 
233  // Set the final generator if we have one set by the user
234  // and if so make sure it also exists
235  if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
236  moose_mesh->isParamValid("final_generator"))
237  {
238  mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
239  "Assumption for mesh type is now invalid");
240 
241  _final_generator_name = moose_mesh->getParam<std::string>("final_generator");
243  moose_mesh->paramError("final_generator",
244  "The forced final MeshGenerator '",
246  "' does not exist");
247  }
248 }
249 
250 void
252 {
253  mooseAssert(_app.constructingMeshGenerators() ||
254  _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
255  "Incorrect call time");
256  mooseAssert(_ordered_mesh_generators.empty(), "Already ordered");
257  mooseAssert(_mesh_generators.size(), "No mesh generators to order");
258 
259  TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
260 
261  // We dare not sort these based on address!
263 
264  // The mesh generators that must be called
265  // This is needed to mark the generators that could be cut due to a
266  // final generator being set, but should still be called because they're
267  // either being saved in memory or as output
268  std::vector<std::string> required_generators;
269  for (const auto & it : _mesh_generators)
270  if (it.second->hasSaveMesh() || it.second->hasOutput())
271  required_generators.push_back(it.second->name());
272 
273  // The mesh generator tree should have all the mesh generators that
274  // The final generator depends on and all the mesh generators
275  // with 'save in' flag. Here we loop over all the mesh generators
276  // and conditionally add all of the dependencies into the resolver
277  for (const auto & it : _mesh_generators)
278  {
279  MeshGenerator * mg = it.second.get();
280 
281  // The mesh generator has to meet one of the following conditions:
282  // Final mesh generator is not set, so we build the whole tree
283  if (_final_generator_name.empty() ||
284  // This mesh generator is the final generator
285  mg->name() == _final_generator_name ||
286  // This needs to be saved or output
287  mg->hasSaveMesh() || mg->hasOutput() ||
288  // Final mesh generator set and is a child of this generator
290  // This is a dependency of a generator that needs to be saved or output
291  std::find_if(required_generators.begin(),
292  required_generators.end(),
293  [&mg](const auto & name) { return mg->isChildMeshGenerator(name, false); }) !=
294  required_generators.end())
295  {
296  resolver.addItem(mg);
297  for (const auto & dep_mg : mg->getParentMeshGenerators())
298  resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
299  }
300  }
301 
302  // ...and sort them
303  try
304  {
306  }
307  // It is _quite_ hard to trigger this to test it. I've tried to no avail.
308  // Now that we...
309  // - check and sort up front
310  // - know if dependencies exist at the time of requesting them
311  // - require that sub generators depend only on other sub generators in an object's
312  // tree + input dependencies that we explicitly declare
313  // I don't think it's possible. But we'll leave it here anyway and it
314  // definitely will not be covered
316  {
317  const auto & cycle = e.getCyclicDependencies();
318  std::vector<std::string> names(cycle.size());
319  for (const auto i : index_range(cycle))
320  names[i] = cycle[i]->name();
321 
322  mooseError("Cyclic dependencies detected in mesh generation: ",
323  MooseUtils::join(names, " <- "));
324  }
325 
326  mooseAssert(_ordered_mesh_generators.size(), "No mesh generators found");
327 
328  const auto & final_generators = _ordered_mesh_generators.back();
329 
330  // We haven't forced a final generator yet
331  if (_final_generator_name.empty())
332  {
333  mooseAssert(final_generators.size(), "Empty vector");
334 
335  // See if we have multiple independent trees of generators
336  const auto ancestor_list = resolver.getAncestors(final_generators.back());
337  if (ancestor_list.size() != resolver.size() && _final_generator_name.empty())
338  {
339  // Need to remove duplicates and possibly perform a difference so we'll import our list
340  // into a set for these operations.
341  std::set<MeshGenerator *, MeshGenerator::Comparator> ancestors(ancestor_list.begin(),
342  ancestor_list.end());
343  // Get all of the items from the resolver so we can compare against the tree from the
344  // final generator we just pulled.
345  const auto & allValues = resolver.getSortedValues();
346  decltype(ancestors) all(allValues.begin(), allValues.end());
347 
348  decltype(ancestors) ind_tree;
349  std::set_difference(all.begin(),
350  all.end(),
351  ancestors.begin(),
352  ancestors.end(),
353  std::inserter(ind_tree, ind_tree.end()));
354 
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: \"";
359  bool first = true;
360  for (const auto & gen : ind_tree)
361  {
362  if (!first)
363  oss << ", ";
364  else
365  first = false;
366 
367  oss << gen->name();
368  }
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 "
373  "MeshGenerator\n"
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.";
376  mooseError(oss.str());
377  }
378 
379  _final_generator_name = final_generators.back()->name();
380  }
381  else
382  mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
383 }
384 
385 void
387 {
388  libmesh_parallel_only(comm());
389 
390  // we do not need to do this when there are no mesh generators
391  if (_mesh_generators.empty())
392  return;
393 
394  // Order the generators
396 
397  // Save all meshes marked to to_save_in_meshes and save in error checking
398  std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
399  for (const auto & generator_set : _ordered_mesh_generators)
400  for (const auto & generator : generator_set)
401  if (generator->hasSaveMesh())
402  {
403  if (_final_generator_name == generator->name())
404  generator->paramError("save_with_name",
405  "Cannot use the save in capability with the final mesh generator");
406  if (getCSGOnly())
407  generator->paramError("save_with_name", "Cannot use in conjunction with --csg-only");
408  to_save_in_meshes.emplace(generator->getSavedMeshName(),
409  &getMeshGeneratorOutput(generator->name()));
410  }
411  // Grab the outputs from the final generator so MeshGeneratorMesh can pick it up
412  to_save_in_meshes.emplace(mainMeshGeneratorName(),
414 
415  // Run the MeshGenerators in the proper order
416  for (const auto & generator_set : _ordered_mesh_generators)
417  {
418  for (const auto & generator : generator_set)
419  {
420  const auto & name = generator->name();
421  if (_verbose)
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();
426 
427  // Only generating data for this generator
428  if (generator->isDataOnly())
429  {
430  mooseAssert(!current_mesh, "Should not have a mesh");
431  continue;
432  }
433 
434 #ifdef DEBUG
435  // Assert that the mesh is either marked as not prepared or if it is marked as prepared,
436  // that it's *actually* prepared
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 '",
440  generator->type(),
441  "' class to call 'set_isnt_prepared()'");
442 #endif
443 
444  // Now we need to possibly give this mesh to downstream generators
445  auto & outputs = _mesh_generator_outputs[name];
446 
447  if (outputs.size())
448  {
449  auto & first_output = *outputs.begin();
450 
451  first_output = std::move(current_mesh);
452 
453  const auto & copy_from = *first_output;
454 
455  auto output_it = ++outputs.begin();
456 
457  // For all of the rest we need to make a copy
458  for (; output_it != outputs.end(); ++output_it)
459  (*output_it) = copy_from.clone();
460  }
461  }
462  }
463 
464  // No save in meshes exist in csg only mode
465  if (getCSGOnly())
466  return;
467 
468  // Grab all the valid save in meshes from the temporary map to_save_in_meshes
469  // and store them in _save_in_meshes
470  for (auto & [name, mesh_ptr] : to_save_in_meshes)
471  {
472  mooseAssert(mesh_ptr, "Invalid pointer");
473  mooseAssert(*mesh_ptr, "Invalid pointer");
474  if (name != mainMeshGeneratorName())
475  mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
476  _save_in_meshes[name] = std::move(*mesh_ptr);
477  }
478 }
479 
480 std::shared_ptr<MeshGenerator>
481 MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
482 {
483  libmesh_parallel_only(comm());
484  mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
485 
486  const auto find_params = _mesh_generator_params.find(generator_name);
487  mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
488  const auto & [type, params] = find_params->second;
489  mooseAssert(comm().verify(type + generator_name), "Inconsistent construction order");
490 
491  std::shared_ptr<MeshGenerator> mg =
492  _app.getFactory().create<MeshGenerator>(type, generator_name, params);
493 
494  if (mg->hasSaveMesh())
495  {
496  if (_save_in_meshes.count(mg->getSavedMeshName()))
497  mg->paramError("save_with_name",
498  "The save with name '",
499  mg->getSavedMeshName(),
500  "' has already been used");
501  _save_in_meshes.emplace(mg->getSavedMeshName(), nullptr);
502  }
503 
504  // Setup the children and parents
505  for (const auto & dependency : mg->getRequestedMeshGenerators())
506  {
507  // We _shouldn't_ hit this; now that we enforce construction ordering we do
508  // all of this error checking at construction time because the info is available
509  mooseAssert(hasMeshGenerator(dependency), "Missing dependency");
510 
511  auto & dependency_mg = getMeshGeneratorInternal(dependency);
512  mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
513  dependency_mg.addChildMeshGenerator(*mg, MeshGenerator::AddParentChildKey());
514  }
515 
516  // Loop through all of the MeshGeneratorName and std::vector<MeshGeneratorName>
517  // parameters (meshes that we should depend on), and make sure that either:
518  // - We directly depend on them and requested a mesh from them
519  // - We created a sub generator that depends on them and we declared it
520  for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
521  {
522  const auto & param_name = param_dependency_pair.first;
523  const auto & dependency_name = param_dependency_pair.second;
524 
525  if (mg->isNullMeshName(dependency_name))
526  continue;
527 
528  // True if this dependency was requested and is a parent
529  if (mg->isParentMeshGenerator(dependency_name))
530  {
531  mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
532  continue;
533  }
534 
535  // Whether or not this is a dependency of at least one SubGenerator
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();
541 
542  // This should be used by a sub generator
543  if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
544  {
545  if (!is_sub_dependency)
546  mg->mooseError("The sub generator dependency declared from MeshGenerator '",
547  dependency_name,
548  "' from the parameter '",
549  param_name,
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.");
552  }
553  // This was used by a sub generator but wasn't declared
554  else if (is_sub_dependency)
555  mg->mooseError(
556  "The MeshGenerator '",
557  dependency_name,
558  "' was referenced in the parameter '",
559  param_name,
560  "' and used in the sub generator ",
561  (*find_sub_dependency)->type(),
562  " '",
563  (*find_sub_dependency)->name(),
564  "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
565  mg->type(),
566  " to include a call to declareMesh(es)ForSub(\"",
567  param_name,
568  "\") in the constructor.");
569  // Isn't used at all
570  else
571  mg->mooseError(
572  "You failed to request the generated mesh(es) for the parameter '",
573  param_name,
574  "'.\n\nIn specific, the mesh from MeshGenerator '",
575  dependency_name,
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().");
578  }
579 
580  mooseAssert(!_mesh_generators.count(generator_name), "Already created");
581  _mesh_generators.emplace(generator_name, mg);
582  mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
583  _mesh_generator_outputs[generator_name];
584  _mesh_generator_params.erase(find_params);
585 
586  return mg;
587 }
588 
589 std::unique_ptr<MeshBase> &
590 MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
591 {
592  mooseAssert(_app.constructingMeshGenerators() ||
593  _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
594  "Incorrect call time");
595 
596  auto it = _mesh_generator_outputs.find(name);
597  mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
598  it->second.push_back(nullptr);
599  return it->second.back();
600 }
601 
602 bool
603 MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
604 {
605  return _mesh_generators.count(name);
606 }
607 
608 bool
609 MeshGeneratorSystem::hasMeshGeneratorParams(const MeshGeneratorName & name) const
610 {
611  return _mesh_generator_params.count(name);
612 }
613 
614 const MeshGenerator &
615 MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
616 {
617  const auto it = _mesh_generators.find(name);
618  if (it == _mesh_generators.end())
619  mooseError("Failed to find a MeshGenerator with the name '", name, "'");
620  mooseAssert(it->second, "Invalid shared pointer");
621  return *it->second;
622 }
623 
624 std::vector<std::string>
626 {
627  std::vector<std::string> names;
628  for (auto & pair : _mesh_generators)
629  names.push_back(pair.first);
630  return names;
631 }
632 
633 std::vector<std::string>
635 {
636  std::vector<std::string> names;
637  for (auto & pair : _save_in_meshes)
638  names.push_back(pair.first);
639  return names;
640 }
641 
642 std::unique_ptr<MeshBase>
643 MeshGeneratorSystem::getSavedMesh(const std::string & name)
644 {
645  auto find_mesh = _save_in_meshes.find(name);
646  if (find_mesh == _save_in_meshes.end())
647  mooseError("Failed to find a saved mesh with the name '", name, "'");
648 
649  auto & mesh_unique_ptr = find_mesh->second;
650  if (!mesh_unique_ptr)
651  mooseError("While getting the saved mesh generator '",
652  name,
653  "', said mesh has already been retrieved");
654 
655  return std::move(mesh_unique_ptr);
656 }
657 
658 bool
660 {
661  return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
662 }
663 
664 bool
666 {
667  return _app.parameters().get<bool>(allow_data_driven_param);
668 }
669 
670 const std::string &
672 {
673  mooseAssert(_data_driven_generator_name, "Not set");
675 }
676 
677 void
679  const std::string & message) const
680 {
681  const auto & moose_mesh = _app.actionWarehouse().getMesh();
682  moose_mesh->paramError(data_driven_generator_param,
683  "The generator '",
685  "' cannot be used in data-driven mode because the parent ",
686  generator.typeAndName(),
687  " ",
688  message);
689 }
690 
691 void
693 {
694  _csg_only = true;
695 }
696 
697 void
698 MeshGeneratorSystem::saveOutputCSGBase(const MeshGeneratorName generator_name,
699  std::unique_ptr<CSG::CSGBase> & csg_base)
700 {
701  mooseAssert(_csg_base_output.find(generator_name) == _csg_base_output.end(),
702  "CSG mesh already exists");
703  _csg_base_output[generator_name] = std::move(csg_base);
704 }
705 
706 std::unique_ptr<CSG::CSGBase> &
707 MeshGeneratorSystem::getCSGBaseGeneratorOutput(const MeshGeneratorName & name)
708 {
709  mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "execute_csg_generators",
710  "Incorrect call time");
711 
712  auto it = _csg_base_output.find(name);
713  mooseAssert(it != _csg_base_output.end(), "CSG mesh not initialized");
714  return it->second;
715 }
std::string name(const ElemQuality q)
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Definition: MooseApp.C:3600
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.
Definition: MooseUtils.h:144
static const std::string data_only_param
The name of the private parameter for setting data only.
Definition: MeshGenerator.h:76
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 &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:439
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...
Definition: MooseError.h:323
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.
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.
Definition: MooseBase.h:131
const std::shared_ptr< MooseMesh > & getMesh() const
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
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.
Definition: MooseApp.h:103
void executeMeshGenerators()
Execute and clear the Mesh Generators data structure.
bool hasOutput() const
std::optional< std::string > _data_driven_generator_name
The name of the data driven generator, if any.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
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 &#39;a&#39; and &#39;b&#39;.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition: MooseApp.h:401
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 &params)
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.
Definition: MooseBase.h:103
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.
Definition: MooseApp.h:211
std::string typeAndName() const
Get the class&#39;s combined type and name; useful in error handling.
Definition: MooseBase.C:57
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
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
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.
Definition: MeshGenerator.h:33
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 &params, const bool allow_empty=false) const
Gets the MeshGeneratorNames that are referenced in an object&#39;s parameters.
std::vector< std::vector< MeshGenerator * > > _ordered_mesh_generators
Holds the ordered mesh generators from createMeshGeneratorOrder() until they are executed in executeM...