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 : #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";
21 : const std::string MeshGeneratorSystem::allow_data_driven_param =
22 : "allow_data_driven_mesh_generation";
23 :
24 62755 : MeshGeneratorSystem::MeshGeneratorSystem(MooseApp & app)
25 : : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
26 : ParallelObject(app),
27 62755 : _app(app),
28 62755 : _has_bmbb(false),
29 62755 : _verbose(false)
30 : {
31 62755 : }
32 :
33 : void
34 51231 : MeshGeneratorSystem::addMeshGenerator(const std::string & type,
35 : const std::string & name,
36 : const InputParameters & params)
37 : {
38 : mooseAssert(!_mesh_generator_params.count(name), "Already exists");
39 51231 : _mesh_generator_params.emplace(
40 51231 : std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
41 :
42 : // This should be a sub mesh generator. We can assume this because if we're in the middle of
43 : // constructing mesh generators (not "adding" them, where we simply store their parameters)
44 51231 : if (_app.constructingMeshGenerators())
45 224 : createMeshGenerator(name);
46 :
47 51227 : if (type == "BreakMeshByBlockGenerator")
48 236 : _has_bmbb = true;
49 51227 : }
50 :
51 : const MeshGenerator &
52 104 : MeshGeneratorSystem::appendMeshGenerator(const std::string & type,
53 : const std::string & name,
54 : InputParameters params)
55 : {
56 104 : if (!appendingMeshGenerators())
57 4 : mooseError("Can only call appendMeshGenerator() during the append_mesh_generator task");
58 100 : const auto param_name_mg_name_pairs = getMeshGeneratorParamDependencies(params, true);
59 :
60 : // Make sure this mesh generator has one and _only_ one input, in the "input" parameter,
61 : // Or several, listed in the "inputs" parameter
62 196 : if ((param_name_mg_name_pairs.size() == 0) ||
63 136 : (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first != "input" &&
64 276 : param_name_mg_name_pairs[0].first != "inputs") ||
65 164 : (param_name_mg_name_pairs.size() > 1 && param_name_mg_name_pairs[0].first != "inputs"))
66 4 : mooseError("While adding ",
67 : type,
68 : " '",
69 : name,
70 : "' via appendMeshGenerator():\nCan only append a mesh generator that takes a "
71 : "single input mesh generator via the parameter named 'input' or 'inputs'.");
72 :
73 : // If no final generator is set, we need to make sure that we have one; we will hit
74 : // this the first time we add an appended MeshGenerator and only need to do it once.
75 : // We'll then generate the final ordering within the execution phase. We'll also
76 : // clear the ordering because it could be invalid if we append any more generators,
77 : // and we'll be re-ordering within executeMeshgenerators() anyway (where we don't
78 : // keep track of any state for the sake of simpler logic)
79 96 : if (_final_generator_name.empty())
80 : {
81 16 : if (_mesh_generators.empty())
82 4 : mooseError("Cannot use appendMeshGenerator() because there is not a generator to append to!");
83 :
84 12 : createMeshGeneratorOrder();
85 12 : _ordered_mesh_generators.clear();
86 : }
87 :
88 : // Set the final generator as the input if a single generator
89 : mooseAssert(hasMeshGenerator(_final_generator_name), "Missing final generator");
90 92 : if (params.have_parameter<MeshGeneratorName>("input"))
91 12 : params.set<MeshGeneratorName>("input") = _final_generator_name;
92 : // We'll trust the final combiner generator with its list of inputs
93 :
94 : // Keep track of the new final generator
95 92 : _final_generator_name = name;
96 :
97 : // Need to add this to the param map so that createMeshGenerator can use it
98 : mooseAssert(!_mesh_generator_params.count(name), "Already exists");
99 92 : _mesh_generator_params.emplace(
100 92 : std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
101 :
102 184 : return *createMeshGenerator(name);
103 92 : }
104 :
105 : std::vector<std::pair<std::string, MeshGeneratorName>>
106 101762 : MeshGeneratorSystem::getMeshGeneratorParamDependencies(const InputParameters & params,
107 : const bool allow_empty /* = false */) const
108 : {
109 101762 : std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
110 :
111 : auto add_dependency =
112 113424 : [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
113 : {
114 56704 : if (dependency.size() || allow_empty)
115 54912 : dependencies.emplace_back(param_name, dependency);
116 158466 : };
117 :
118 3781244 : for (const auto & [name, param] : params)
119 3679482 : if (const auto dependency =
120 3679482 : dynamic_cast<const Parameters::Parameter<MeshGeneratorName> *>(param.get()))
121 48404 : add_dependency(name, dependency->get());
122 3631078 : else if (const auto dependencies =
123 3631078 : dynamic_cast<const Parameters::Parameter<std::vector<MeshGeneratorName>> *>(
124 7262156 : param.get()))
125 : {
126 3468 : if (allow_empty && dependencies->get().empty())
127 0 : add_dependency(name, std::string());
128 11768 : for (const auto & dependency : dependencies->get())
129 8300 : add_dependency(name, dependency);
130 : }
131 :
132 203524 : return dependencies;
133 0 : }
134 :
135 : void
136 61831 : MeshGeneratorSystem::createAddedMeshGenerators()
137 : {
138 : mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "create_added_mesh_generators",
139 : "Should not run now");
140 :
141 : // No generators were added via addMeshGenerator()
142 61831 : if (_mesh_generator_params.empty())
143 38281 : return;
144 :
145 23550 : DependencyResolver<std::string> resolver;
146 :
147 : // Define the dependencies known so far
148 74553 : for (const auto & [name, type_params_pair] : _mesh_generator_params)
149 : {
150 51003 : resolver.addItem(name);
151 51003 : for (const auto & param_dependency_pair :
152 129447 : getMeshGeneratorParamDependencies(type_params_pair.second))
153 78444 : resolver.addEdge(param_dependency_pair.second, name);
154 : }
155 :
156 23550 : std::vector<std::vector<std::string>> ordered_generators;
157 : try
158 : {
159 23550 : ordered_generators = resolver.getSortedValuesSets();
160 : }
161 4 : catch (CyclicDependencyException<std::string> & e)
162 : {
163 4 : mooseError("Cyclic dependencies detected in mesh generation: ",
164 4 : MooseUtils::join(e.getCyclicDependencies(), " <- "));
165 0 : }
166 :
167 23546 : const auto & moose_mesh = _app.actionWarehouse().getMesh();
168 :
169 : // If there is no mesh
170 23546 : if (!moose_mesh.get())
171 0 : mooseError("No mesh created. Either add a Mesh, an ActionComponents or a Components block");
172 :
173 : // If we're using data-driven generation, find that requirement now
174 : mooseAssert(!_data_driven_generator_name, "Should not be set");
175 47041 : if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
176 23495 : moose_mesh->isParamValid(data_driven_generator_param))
177 : {
178 36 : if (!hasDataDrivenAllowed())
179 4 : moose_mesh->paramError(
180 : data_driven_generator_param,
181 : "This application does not support data-driven mesh generation.\n\nThis generation is an "
182 : "advanced feature and must be enabled on the application via the '",
183 : allow_data_driven_param,
184 : "' parameter.");
185 :
186 : mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
187 : "Assumption for mesh type is now invalid");
188 :
189 32 : _data_driven_generator_name = moose_mesh->getParam<std::string>(data_driven_generator_param);
190 32 : if (!_mesh_generator_params.count(*_data_driven_generator_name))
191 8 : moose_mesh->paramError(data_driven_generator_param,
192 : "The data driven generator '",
193 4 : *_data_driven_generator_name,
194 : "' does not exist");
195 : }
196 :
197 : // Construct all of the mesh generators that we know exist
198 70467 : for (const auto & generator_names : ordered_generators)
199 97656 : for (const auto & generator_name : generator_names)
200 50727 : if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
201 : {
202 50695 : auto & params = it->second.second;
203 :
204 : // Determine now if we need to run this in data only mode
205 76 : const bool data_only = _data_driven_generator_name &&
206 50771 : getDataDrivenGeneratorName() != generator_name &&
207 56 : resolver.dependsOn(getDataDrivenGeneratorName(), generator_name);
208 50695 : params.set<bool>(MeshGenerator::data_only_param) = data_only;
209 :
210 50695 : createMeshGenerator(generator_name);
211 :
212 : mooseAssert(data_only == getMeshGenerator(generator_name).isDataOnly(),
213 : "Inconsistent data only");
214 : }
215 :
216 : mooseAssert(_mesh_generator_params.empty(), "Should be empty");
217 : mooseAssert(_final_generator_name.empty(), "Should be unset at this point");
218 :
219 : // Set the final generator if we have one set by the user
220 : // and if so make sure it also exists
221 46305 : if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
222 46305 : moose_mesh->isParamValid("final_generator"))
223 : {
224 : mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
225 : "Assumption for mesh type is now invalid");
226 :
227 402 : _final_generator_name = moose_mesh->getParam<std::string>("final_generator");
228 402 : if (!hasMeshGenerator(_final_generator_name))
229 8 : moose_mesh->paramError("final_generator",
230 : "The forced final MeshGenerator '",
231 4 : _final_generator_name,
232 : "' does not exist");
233 : }
234 23174 : }
235 :
236 : void
237 22236 : MeshGeneratorSystem::createMeshGeneratorOrder()
238 : {
239 : mooseAssert(_app.constructingMeshGenerators() ||
240 : _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
241 : "Incorrect call time");
242 : mooseAssert(_ordered_mesh_generators.empty(), "Already ordered");
243 : mooseAssert(_mesh_generators.size(), "No mesh generators to order");
244 :
245 22236 : TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
246 :
247 : // We dare not sort these based on address!
248 22236 : DependencyResolver<MeshGenerator *, MeshGenerator::Comparator> resolver;
249 :
250 : // The mesh generators that must be called
251 : // This is needed to mark the generators that could be cut due to a
252 : // final generator being set, but should still be called because they're
253 : // either being saved in memory or as output
254 22236 : std::vector<std::string> required_generators;
255 70645 : for (const auto & it : _mesh_generators)
256 48409 : if (it.second->hasSaveMesh() || it.second->hasOutput())
257 361 : required_generators.push_back(it.second->name());
258 :
259 : // The mesh generator tree should have all the mesh generators that
260 : // The final generator depends on and all the mesh generators
261 : // with 'save in' flag. Here we loop over all the mesh generators
262 : // and conditionally add all of the dependencies into the resolver
263 70645 : for (const auto & it : _mesh_generators)
264 : {
265 48409 : MeshGenerator * mg = it.second.get();
266 :
267 : // The mesh generator has to meet one of the following conditions:
268 : // Final mesh generator is not set, so we build the whole tree
269 2325 : if (_final_generator_name.empty() ||
270 : // This mesh generator is the final generator
271 2325 : mg->name() == _final_generator_name ||
272 : // This needs to be saved or output
273 3680 : mg->hasSaveMesh() || mg->hasOutput() ||
274 : // Final mesh generator set and is a child of this generator
275 101547 : (_final_generator_name.size() && mg->isChildMeshGenerator(_final_generator_name, false)) ||
276 : // This is a dependency of a generator that needs to be saved or output
277 650 : std::find_if(required_generators.begin(),
278 : required_generators.end(),
279 1154 : [&mg](const auto & name) { return mg->isChildMeshGenerator(name, false); }) !=
280 49059 : required_generators.end())
281 : {
282 47963 : resolver.addItem(mg);
283 73886 : for (const auto & dep_mg : mg->getParentMeshGenerators())
284 25923 : resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
285 : }
286 : }
287 :
288 : // ...and sort them
289 : try
290 : {
291 22236 : _ordered_mesh_generators = resolver.getSortedValuesSets();
292 : }
293 : // It is _quite_ hard to trigger this to test it. I've tried to no avail.
294 : // Now that we...
295 : // - check and sort up front
296 : // - know if dependencies exist at the time of requesting them
297 : // - require that sub generators depend only on other sub generators in an object's
298 : // tree + input dependencies that we explicitly declare
299 : // I don't think it's possible. But we'll leave it here anyway and it
300 : // definitely will not be covered
301 0 : catch (CyclicDependencyException<MeshGenerator *, MeshGenerator::Comparator> & e)
302 : {
303 0 : const auto & cycle = e.getCyclicDependencies();
304 0 : std::vector<std::string> names(cycle.size());
305 0 : for (const auto i : index_range(cycle))
306 0 : names[i] = cycle[i]->name();
307 :
308 0 : mooseError("Cyclic dependencies detected in mesh generation: ",
309 0 : MooseUtils::join(names, " <- "));
310 0 : }
311 :
312 : mooseAssert(_ordered_mesh_generators.size(), "No mesh generators found");
313 :
314 22236 : const auto & final_generators = _ordered_mesh_generators.back();
315 :
316 : // We haven't forced a final generator yet
317 22236 : if (_final_generator_name.empty())
318 : {
319 : mooseAssert(final_generators.size(), "Empty vector");
320 :
321 : // See if we have multiple independent trees of generators
322 21837 : const auto ancestor_list = resolver.getAncestors(final_generators.back());
323 21837 : if (ancestor_list.size() != resolver.size() && _final_generator_name.empty())
324 : {
325 : // Need to remove duplicates and possibly perform a difference so we'll import our list
326 : // into a set for these operations.
327 : std::set<MeshGenerator *, MeshGenerator::Comparator> ancestors(ancestor_list.begin(),
328 8 : ancestor_list.end());
329 : // Get all of the items from the resolver so we can compare against the tree from the
330 : // final generator we just pulled.
331 8 : const auto & allValues = resolver.getSortedValues();
332 8 : decltype(ancestors) all(allValues.begin(), allValues.end());
333 :
334 8 : decltype(ancestors) ind_tree;
335 8 : std::set_difference(all.begin(),
336 : all.end(),
337 : ancestors.begin(),
338 : ancestors.end(),
339 : std::inserter(ind_tree, ind_tree.end()));
340 :
341 8 : std::ostringstream oss;
342 : oss << "Your MeshGenerator tree contains multiple possible generator outputs :\n\""
343 24 : << final_generators.back()->name()
344 8 : << "\" and one or more of the following from an independent set: \"";
345 8 : bool first = true;
346 29 : for (const auto & gen : ind_tree)
347 : {
348 21 : if (!first)
349 13 : oss << ", ";
350 : else
351 8 : first = false;
352 :
353 21 : oss << gen->name();
354 : }
355 : oss << "\"\n\nThis may be due to a missing dependency or may be intentional. Please either\n"
356 : "- check that all the mesh generators are connected as a tree and culminate in a "
357 : "single final mesh. Having one wrong 'input=mg' parameter is the most common error\n"
358 : "- add additional dependencies to remove the ambiguity if you are using a user-built "
359 : "MeshGenerator\n"
360 : "- if you intend to execute a subset of the defined generators (uncommon), select the"
361 8 : " final MeshGenerator in the [Mesh] block with the \"final_generator\" parameter.";
362 8 : mooseError(oss.str());
363 0 : }
364 :
365 21829 : _final_generator_name = final_generators.back()->name();
366 21829 : }
367 : else
368 : mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
369 22228 : }
370 :
371 : void
372 57480 : MeshGeneratorSystem::executeMeshGenerators()
373 : {
374 : libmesh_parallel_only(comm());
375 :
376 : // we do not need to do this when there are no mesh generators
377 57480 : if (_mesh_generators.empty())
378 35256 : return;
379 :
380 : // Order the generators
381 22224 : createMeshGeneratorOrder();
382 :
383 : // Save all meshes marked to to_save_in_meshes and save in error checking
384 22216 : std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
385 66926 : for (const auto & generator_set : _ordered_mesh_generators)
386 92633 : for (const auto & generator : generator_set)
387 47923 : if (generator->hasSaveMesh())
388 : {
389 42 : if (_final_generator_name == generator->name())
390 4 : generator->paramError("save_with_name",
391 : "Cannot use the save in capability with the final mesh generator");
392 38 : to_save_in_meshes.emplace(generator->getSavedMeshName(),
393 76 : &getMeshGeneratorOutput(generator->name()));
394 : }
395 : // Grab the outputs from the final generator so MeshGeneratorMesh can pick it up
396 22212 : to_save_in_meshes.emplace(mainMeshGeneratorName(),
397 44424 : &getMeshGeneratorOutput(_final_generator_name));
398 :
399 : // Run the MeshGenerators in the proper order
400 66450 : for (const auto & generator_set : _ordered_mesh_generators)
401 : {
402 92129 : for (const auto & generator : generator_set)
403 : {
404 47891 : const auto & name = generator->name();
405 47891 : if (_verbose)
406 0 : _app._console << " [DBG] Executing mesh generator (" << COLOR_GREEN << std::setw(20) << name
407 0 : << COLOR_DEFAULT << ") in type (" << COLOR_GREEN << generator->type()
408 0 : << COLOR_DEFAULT << ")" << std::endl;
409 47891 : auto current_mesh = generator->generateInternal();
410 :
411 : // Only generating data for this generator
412 47439 : if (generator->isDataOnly())
413 : {
414 : mooseAssert(!current_mesh, "Should not have a mesh");
415 30 : continue;
416 : }
417 :
418 : #ifdef DEBUG
419 : // Assert that the mesh is either marked as not prepared or if it is marked as prepared,
420 : // that it's *actually* prepared
421 : if (!_has_bmbb && !MeshTools::valid_is_prepared(*current_mesh))
422 : generator->mooseError("The generated mesh is marked as prepared but is not actually "
423 : "prepared. Please edit the '",
424 : generator->type(),
425 : "' class to call 'set_isnt_prepared()'");
426 : #endif
427 :
428 : // Now we need to possibly give this mesh to downstream generators
429 47409 : auto & outputs = _mesh_generator_outputs[name];
430 :
431 47409 : if (outputs.size())
432 : {
433 47279 : auto & first_output = *outputs.begin();
434 :
435 47279 : first_output = std::move(current_mesh);
436 :
437 47279 : const auto & copy_from = *first_output;
438 :
439 47279 : auto output_it = ++outputs.begin();
440 :
441 : // For all of the rest we need to make a copy
442 47743 : for (; output_it != outputs.end(); ++output_it)
443 464 : (*output_it) = copy_from.clone();
444 : }
445 47439 : }
446 : }
447 :
448 : // Grab all the valid save in meshes from the temporary map to_save_in_meshes
449 : // and store them in _save_in_meshes
450 43558 : for (auto & [name, mesh_ptr] : to_save_in_meshes)
451 : {
452 : mooseAssert(mesh_ptr, "Invalid pointer");
453 : mooseAssert(*mesh_ptr, "Invalid pointer");
454 21798 : if (name != mainMeshGeneratorName())
455 : mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
456 21798 : _save_in_meshes[name] = std::move(*mesh_ptr);
457 : }
458 21772 : }
459 :
460 : std::shared_ptr<MeshGenerator>
461 51011 : MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
462 : {
463 : libmesh_parallel_only(comm());
464 : mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
465 :
466 51011 : const auto find_params = _mesh_generator_params.find(generator_name);
467 : mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
468 51011 : const auto & [type, params] = find_params->second;
469 : mooseAssert(comm().verify(type + generator_name), "Inconsistent construction order");
470 :
471 : std::shared_ptr<MeshGenerator> mg =
472 51011 : _app.getFactory().create<MeshGenerator>(type, generator_name, params);
473 :
474 50663 : if (mg->hasSaveMesh())
475 : {
476 52 : if (_save_in_meshes.count(mg->getSavedMeshName()))
477 8 : mg->paramError("save_with_name",
478 : "The save with name '",
479 4 : mg->getSavedMeshName(),
480 : "' has already been used");
481 48 : _save_in_meshes.emplace(mg->getSavedMeshName(), nullptr);
482 : }
483 :
484 : // Setup the children and parents
485 77964 : for (const auto & dependency : mg->getRequestedMeshGenerators())
486 : {
487 : // We _shouldn't_ hit this; now that we enforce construction ordering we do
488 : // all of this error checking at construction time because the info is available
489 : mooseAssert(hasMeshGenerator(dependency), "Missing dependency");
490 :
491 27305 : auto & dependency_mg = getMeshGeneratorInternal(dependency);
492 27305 : mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
493 27305 : dependency_mg.addChildMeshGenerator(*mg, MeshGenerator::AddParentChildKey());
494 : }
495 :
496 : // Loop through all of the MeshGeneratorName and std::vector<MeshGeneratorName>
497 : // parameters (meshes that we should depend on), and make sure that either:
498 : // - We directly depend on them and requested a mesh from them
499 : // - We created a sub generator that depends on them and we declared it
500 77898 : for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
501 : {
502 27251 : const auto & param_name = param_dependency_pair.first;
503 27251 : const auto & dependency_name = param_dependency_pair.second;
504 :
505 27251 : if (mg->isNullMeshName(dependency_name))
506 27215 : continue;
507 :
508 : // True if this dependency was requested and is a parent
509 27227 : if (mg->isParentMeshGenerator(dependency_name))
510 : {
511 : mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
512 27191 : continue;
513 : }
514 :
515 : // Whether or not this is a dependency of at least one SubGenerator
516 36 : auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
517 36 : mg->getSubMeshGenerators().end(),
518 88 : [&dependency_name](const auto & mg)
519 88 : { return mg->isParentMeshGenerator(dependency_name); });
520 36 : const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
521 :
522 : // This should be used by a sub generator
523 36 : if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
524 : {
525 28 : if (!is_sub_dependency)
526 4 : mg->mooseError("The sub generator dependency declared from MeshGenerator '",
527 : dependency_name,
528 : "' from the parameter '",
529 : param_name,
530 : "' was not used.\n\nDependencies that are declared by declareMeshForSub() "
531 : "must be used as an input to a sub generator created by this object.");
532 : }
533 : // This was used by a sub generator but wasn't declared
534 8 : else if (is_sub_dependency)
535 8 : mg->mooseError(
536 : "The MeshGenerator '",
537 : dependency_name,
538 : "' was referenced in the parameter '",
539 : param_name,
540 : "' and used in the sub generator ",
541 4 : (*find_sub_dependency)->type(),
542 : " '",
543 4 : (*find_sub_dependency)->name(),
544 : "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
545 4 : mg->type(),
546 : " to include a call to declareMesh(es)ForSub(\"",
547 : param_name,
548 : "\") in the constructor.");
549 : // Isn't used at all
550 : else
551 4 : mg->mooseError(
552 : "You failed to request the generated mesh(es) for the parameter '",
553 : param_name,
554 : "'.\n\nIn specific, the mesh from MeshGenerator '",
555 : dependency_name,
556 : "' was not requested.\n\nTo correct this, you should remove the parameter if the "
557 : "mesh(es)\nare not needed, or request the mesh(es) with getMesh()/getMeshes().");
558 50647 : }
559 :
560 : mooseAssert(!_mesh_generators.count(generator_name), "Already created");
561 50647 : _mesh_generators.emplace(generator_name, mg);
562 : mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
563 50647 : _mesh_generator_outputs[generator_name];
564 50647 : _mesh_generator_params.erase(find_params);
565 :
566 101294 : return mg;
567 0 : }
568 :
569 : std::unique_ptr<MeshBase> &
570 49803 : MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
571 : {
572 : mooseAssert(_app.constructingMeshGenerators() ||
573 : _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
574 : "Incorrect call time");
575 :
576 49803 : auto it = _mesh_generator_outputs.find(name);
577 : mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
578 49803 : it->second.push_back(nullptr);
579 99606 : return it->second.back();
580 : }
581 :
582 : bool
583 55006 : MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
584 : {
585 55006 : return _mesh_generators.count(name);
586 : }
587 :
588 : bool
589 20 : MeshGeneratorSystem::hasMeshGeneratorParams(const MeshGeneratorName & name) const
590 : {
591 20 : return _mesh_generator_params.count(name);
592 : }
593 :
594 : const MeshGenerator &
595 53440 : MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
596 : {
597 53440 : const auto it = _mesh_generators.find(name);
598 53440 : if (it == _mesh_generators.end())
599 4 : mooseError("Failed to find a MeshGenerator with the name '", name, "'");
600 : mooseAssert(it->second, "Invalid shared pointer");
601 106872 : return *it->second;
602 : }
603 :
604 : std::vector<std::string>
605 98854 : MeshGeneratorSystem::getMeshGeneratorNames() const
606 : {
607 98854 : std::vector<std::string> names;
608 150559 : for (auto & pair : _mesh_generators)
609 51705 : names.push_back(pair.first);
610 98854 : return names;
611 0 : }
612 :
613 : std::vector<std::string>
614 16 : MeshGeneratorSystem::getSavedMeshNames() const
615 : {
616 16 : std::vector<std::string> names;
617 48 : for (auto & pair : _save_in_meshes)
618 32 : names.push_back(pair.first);
619 16 : return names;
620 0 : }
621 :
622 : std::unique_ptr<MeshBase>
623 21784 : MeshGeneratorSystem::getSavedMesh(const std::string & name)
624 : {
625 21784 : auto find_mesh = _save_in_meshes.find(name);
626 21784 : if (find_mesh == _save_in_meshes.end())
627 4 : mooseError("Failed to find a saved mesh with the name '", name, "'");
628 :
629 21780 : auto & mesh_unique_ptr = find_mesh->second;
630 21780 : if (!mesh_unique_ptr)
631 4 : mooseError("While getting the saved mesh generator '",
632 : name,
633 : "', said mesh has already been retrieved");
634 :
635 43552 : return std::move(mesh_unique_ptr);
636 : }
637 :
638 : bool
639 51639 : MeshGeneratorSystem::appendingMeshGenerators() const
640 : {
641 51639 : return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
642 : }
643 :
644 : bool
645 36 : MeshGeneratorSystem::hasDataDrivenAllowed() const
646 : {
647 36 : return _app.parameters().get<bool>(allow_data_driven_param);
648 : }
649 :
650 : const std::string &
651 140 : MeshGeneratorSystem::getDataDrivenGeneratorName() const
652 : {
653 : mooseAssert(_data_driven_generator_name, "Not set");
654 140 : return *_data_driven_generator_name;
655 : }
656 :
657 : void
658 8 : MeshGeneratorSystem::dataDrivenError(const MeshGenerator & generator,
659 : const std::string & message) const
660 : {
661 8 : const auto & moose_mesh = _app.actionWarehouse().getMesh();
662 16 : moose_mesh->paramError(data_driven_generator_param,
663 : "The generator '",
664 8 : getDataDrivenGeneratorName(),
665 : "' cannot be used in data-driven mode because the parent ",
666 8 : generator.typeAndName(),
667 : " ",
668 : message);
669 : }
|