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 70055 : MeshGeneratorSystem::MeshGeneratorSystem(MooseApp & app)
25 : : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
26 : ParallelObject(app),
27 70055 : _app(app),
28 70055 : _has_bmbb(false),
29 70055 : _verbose(false),
30 210165 : _csg_only(false)
31 : {
32 70055 : }
33 :
34 : void
35 58045 : 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 58045 : _mesh_generator_params.emplace(
41 58045 : 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)
45 58045 : if (_app.constructingMeshGenerators())
46 244 : createMeshGenerator(name);
47 :
48 58041 : if (type == "BreakMeshByBlockGenerator")
49 268 : _has_bmbb = true;
50 58041 : }
51 :
52 : const MeshGenerator &
53 111 : MeshGeneratorSystem::appendMeshGenerator(const std::string & type,
54 : const std::string & name,
55 : InputParameters params)
56 : {
57 111 : if (!appendingMeshGenerators())
58 4 : mooseError("Can only call appendMeshGenerator() during the append_mesh_generator task");
59 107 : 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 210 : if ((param_name_mg_name_pairs.size() == 0) ||
64 133 : (param_name_mg_name_pairs.size() == 1 && param_name_mg_name_pairs[0].first != "input" &&
65 296 : param_name_mg_name_pairs[0].first != "inputs") ||
66 176 : (param_name_mg_name_pairs.size() > 1 && param_name_mg_name_pairs[0].first != "inputs"))
67 4 : 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 103 : if (_final_generator_name.empty())
81 : {
82 17 : if (_mesh_generators.empty())
83 4 : mooseError("Cannot use appendMeshGenerator() because there is not a generator to append to!");
84 :
85 13 : createMeshGeneratorOrder();
86 13 : _ordered_mesh_generators.clear();
87 : }
88 :
89 : // Set the final generator as the input if a single generator
90 : mooseAssert(hasMeshGenerator(_final_generator_name), "Missing final generator");
91 99 : if (params.have_parameter<MeshGeneratorName>("input"))
92 39 : 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
96 99 : _final_generator_name = name;
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 99 : _mesh_generator_params.emplace(
101 99 : std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(type, params));
102 :
103 198 : return *createMeshGenerator(name);
104 99 : }
105 :
106 : std::vector<std::pair<std::string, MeshGeneratorName>>
107 115384 : MeshGeneratorSystem::getMeshGeneratorParamDependencies(const InputParameters & params,
108 : const bool allow_empty /* = false */) const
109 : {
110 115384 : std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
111 :
112 : auto add_dependency =
113 64496 : [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
114 : {
115 64496 : if (dependency.size() || allow_empty)
116 62580 : dependencies.emplace_back(param_name, dependency);
117 179880 : };
118 :
119 4412695 : for (const auto & [name, param] : params)
120 4297311 : if (const auto dependency =
121 4297311 : dynamic_cast<const Parameters::Parameter<MeshGeneratorName> *>(param.get()))
122 55048 : add_dependency(name, dependency->get());
123 4242263 : else if (const auto dependencies =
124 4242263 : dynamic_cast<const Parameters::Parameter<std::vector<MeshGeneratorName>> *>(
125 8484526 : param.get()))
126 : {
127 3894 : if (allow_empty && dependencies->get().empty())
128 0 : add_dependency(name, std::string());
129 13342 : for (const auto & dependency : dependencies->get())
130 9448 : add_dependency(name, dependency);
131 : }
132 :
133 230768 : return dependencies;
134 0 : }
135 :
136 : void
137 68915 : MeshGeneratorSystem::createAddedMeshGenerators()
138 : {
139 : mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "create_added_mesh_generators",
140 : "Should not run now");
141 :
142 : // No generators were added via addMeshGenerator()
143 68915 : if (_mesh_generator_params.empty())
144 42250 : return;
145 :
146 26665 : DependencyResolver<std::string> resolver;
147 :
148 : // Define the dependencies known so far
149 84462 : for (const auto & [name, type_params_pair] : _mesh_generator_params)
150 : {
151 57797 : resolver.addItem(name);
152 57797 : for (const auto & param_dependency_pair :
153 146844 : getMeshGeneratorParamDependencies(type_params_pair.second))
154 89047 : resolver.addEdge(param_dependency_pair.second, name);
155 : }
156 :
157 26665 : std::vector<std::vector<std::string>> ordered_generators;
158 : try
159 : {
160 26665 : ordered_generators = resolver.getSortedValuesSets();
161 : }
162 4 : catch (CyclicDependencyException<std::string> & e)
163 : {
164 4 : mooseError("Cyclic dependencies detected in mesh generation: ",
165 4 : MooseUtils::join(e.getCyclicDependencies(), " <- "));
166 0 : }
167 :
168 26661 : const auto & moose_mesh = _app.actionWarehouse().getMesh();
169 :
170 : // If there is no mesh
171 26661 : if (!moose_mesh.get())
172 0 : 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 53266 : if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
177 26605 : moose_mesh->isParamValid(data_driven_generator_param))
178 : {
179 38 : if (!hasDataDrivenAllowed())
180 4 : moose_mesh->paramError(
181 : data_driven_generator_param,
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 '",
184 : allow_data_driven_param,
185 : "' parameter.");
186 :
187 : mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
188 : "Assumption for mesh type is now invalid");
189 :
190 34 : _data_driven_generator_name = moose_mesh->getParam<std::string>(data_driven_generator_param);
191 34 : if (!_mesh_generator_params.count(*_data_driven_generator_name))
192 8 : moose_mesh->paramError(data_driven_generator_param,
193 : "The data driven generator '",
194 4 : *_data_driven_generator_name,
195 : "' does not exist");
196 : }
197 :
198 : // Check compatibility for CLI / meshing options with csg_only
199 26653 : const bool csg_only = getCSGOnly();
200 26653 : if (csg_only && _data_driven_generator_name)
201 0 : 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 79908 : for (const auto & generator_names : ordered_generators)
206 110777 : for (const auto & generator_name : generator_names)
207 57522 : if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
208 : {
209 57489 : 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 115007 : (csg_only ||
214 57518 : (_data_driven_generator_name && getDataDrivenGeneratorName() != generator_name &&
215 60 : resolver.dependsOn(getDataDrivenGeneratorName(), generator_name)));
216 57489 : params.set<bool>(MeshGenerator::data_only_param) = data_only;
217 :
218 57489 : createMeshGenerator(generator_name);
219 :
220 57129 : if (csg_only && !getMeshGenerator(generator_name).hasGenerateCSG())
221 0 : 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 52530 : if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
236 105004 : moose_mesh->isParamValid("final_generator"))
237 : {
238 : mooseAssert(moose_mesh->type() == "MeshGeneratorMesh",
239 : "Assumption for mesh type is now invalid");
240 :
241 932 : _final_generator_name = moose_mesh->getParam<std::string>("final_generator");
242 466 : if (!hasMeshGenerator(_final_generator_name))
243 8 : moose_mesh->paramError("final_generator",
244 : "The forced final MeshGenerator '",
245 4 : _final_generator_name,
246 : "' does not exist");
247 : }
248 26289 : }
249 :
250 : void
251 25271 : MeshGeneratorSystem::createMeshGeneratorOrder()
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 126355 : TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
260 :
261 : // We dare not sort these based on address!
262 25271 : DependencyResolver<MeshGenerator *, MeshGenerator::Comparator> resolver;
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 25271 : std::vector<std::string> required_generators;
269 80357 : for (const auto & it : _mesh_generators)
270 55086 : if (it.second->hasSaveMesh() || it.second->hasOutput())
271 396 : 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 80357 : for (const auto & it : _mesh_generators)
278 : {
279 55086 : 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 2835 : if (_final_generator_name.empty() ||
284 : // This mesh generator is the final generator
285 2835 : mg->name() == _final_generator_name ||
286 : // This needs to be saved or output
287 4552 : mg->hasSaveMesh() || mg->hasOutput() ||
288 : // Final mesh generator set and is a child of this generator
289 116093 : (_final_generator_name.size() && mg->isChildMeshGenerator(_final_generator_name, false)) ||
290 : // This is a dependency of a generator that needs to be saved or output
291 905 : std::find_if(required_generators.begin(),
292 : required_generators.end(),
293 1462 : [&mg](const auto & name) { return mg->isChildMeshGenerator(name, false); }) !=
294 55991 : required_generators.end())
295 : {
296 54408 : resolver.addItem(mg);
297 83802 : for (const auto & dep_mg : mg->getParentMeshGenerators())
298 29394 : resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
299 : }
300 : }
301 :
302 : // ...and sort them
303 : try
304 : {
305 25271 : _ordered_mesh_generators = resolver.getSortedValuesSets();
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
315 0 : catch (CyclicDependencyException<MeshGenerator *, MeshGenerator::Comparator> & e)
316 : {
317 0 : const auto & cycle = e.getCyclicDependencies();
318 0 : std::vector<std::string> names(cycle.size());
319 0 : for (const auto i : index_range(cycle))
320 0 : names[i] = cycle[i]->name();
321 :
322 0 : mooseError("Cyclic dependencies detected in mesh generation: ",
323 0 : MooseUtils::join(names, " <- "));
324 0 : }
325 :
326 : mooseAssert(_ordered_mesh_generators.size(), "No mesh generators found");
327 :
328 25271 : const auto & final_generators = _ordered_mesh_generators.back();
329 :
330 : // We haven't forced a final generator yet
331 25271 : 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 24807 : const auto ancestor_list = resolver.getAncestors(final_generators.back());
337 24807 : 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 8 : 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 8 : const auto & allValues = resolver.getSortedValues();
346 8 : decltype(ancestors) all(allValues.begin(), allValues.end());
347 :
348 8 : decltype(ancestors) ind_tree;
349 8 : std::set_difference(all.begin(),
350 : all.end(),
351 : ancestors.begin(),
352 : ancestors.end(),
353 : std::inserter(ind_tree, ind_tree.end()));
354 :
355 8 : std::ostringstream oss;
356 : oss << "Your MeshGenerator tree contains multiple possible generator outputs :\n\""
357 8 : << final_generators.back()->name()
358 16 : << "\" and one or more of the following from an independent set: \"";
359 8 : bool first = true;
360 27 : for (const auto & gen : ind_tree)
361 : {
362 19 : if (!first)
363 11 : oss << ", ";
364 : else
365 8 : first = false;
366 :
367 19 : 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 8 : " final MeshGenerator in the [Mesh] block with the \"final_generator\" parameter.";
376 8 : mooseError(oss.str());
377 0 : }
378 :
379 24799 : _final_generator_name = final_generators.back()->name();
380 24799 : }
381 : else
382 : mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
383 25263 : }
384 :
385 : void
386 64289 : MeshGeneratorSystem::executeMeshGenerators()
387 : {
388 : libmesh_parallel_only(comm());
389 :
390 : // we do not need to do this when there are no mesh generators
391 64289 : if (_mesh_generators.empty())
392 39062 : return;
393 :
394 : // Order the generators
395 25258 : createMeshGeneratorOrder();
396 :
397 : // Save all meshes marked to to_save_in_meshes and save in error checking
398 25250 : std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
399 76040 : for (const auto & generator_set : _ordered_mesh_generators)
400 105157 : for (const auto & generator : generator_set)
401 54367 : if (generator->hasSaveMesh())
402 : {
403 45 : if (_final_generator_name == generator->name())
404 8 : generator->paramError("save_with_name",
405 : "Cannot use the save in capability with the final mesh generator");
406 41 : if (getCSGOnly())
407 0 : generator->paramError("save_with_name", "Cannot use in conjunction with --csg-only");
408 41 : to_save_in_meshes.emplace(generator->getSavedMeshName(),
409 82 : &getMeshGeneratorOutput(generator->name()));
410 : }
411 : // Grab the outputs from the final generator so MeshGeneratorMesh can pick it up
412 25246 : to_save_in_meshes.emplace(mainMeshGeneratorName(),
413 50492 : &getMeshGeneratorOutput(_final_generator_name));
414 :
415 : // Run the MeshGenerators in the proper order
416 75520 : for (const auto & generator_set : _ordered_mesh_generators)
417 : {
418 104609 : for (const auto & generator : generator_set)
419 : {
420 54335 : const auto & name = generator->name();
421 54335 : if (_verbose)
422 0 : _app._console << " [DBG] Executing mesh generator (" << COLOR_GREEN << std::setw(20) << name
423 0 : << COLOR_DEFAULT << ") in type (" << COLOR_GREEN << generator->type()
424 0 : << COLOR_DEFAULT << ")" << std::endl;
425 54335 : auto current_mesh = generator->generateInternal();
426 :
427 : // Only generating data for this generator
428 53839 : if (generator->isDataOnly())
429 : {
430 : mooseAssert(!current_mesh, "Should not have a mesh");
431 77 : 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 53762 : auto & outputs = _mesh_generator_outputs[name];
446 :
447 53762 : if (outputs.size())
448 : {
449 53617 : auto & first_output = *outputs.begin();
450 :
451 53617 : first_output = std::move(current_mesh);
452 :
453 53617 : const auto & copy_from = *first_output;
454 :
455 53617 : auto output_it = ++outputs.begin();
456 :
457 : // For all of the rest we need to make a copy
458 54276 : for (; output_it != outputs.end(); ++output_it)
459 659 : (*output_it) = copy_from.clone();
460 : }
461 53839 : }
462 : }
463 :
464 : // No save in meshes exist in csg only mode
465 24750 : if (getCSGOnly())
466 31 : 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 49479 : for (auto & [name, mesh_ptr] : to_save_in_meshes)
471 : {
472 : mooseAssert(mesh_ptr, "Invalid pointer");
473 : mooseAssert(*mesh_ptr, "Invalid pointer");
474 24760 : if (name != mainMeshGeneratorName())
475 : mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
476 24760 : _save_in_meshes[name] = std::move(*mesh_ptr);
477 : }
478 24762 : }
479 :
480 : std::shared_ptr<MeshGenerator>
481 57832 : MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
482 : {
483 : libmesh_parallel_only(comm());
484 : mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
485 :
486 57832 : const auto find_params = _mesh_generator_params.find(generator_name);
487 : mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
488 57832 : 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 57832 : _app.getFactory().create<MeshGenerator>(type, generator_name, params);
493 :
494 57484 : if (mg->hasSaveMesh())
495 : {
496 55 : if (_save_in_meshes.count(mg->getSavedMeshName()))
497 8 : mg->paramError("save_with_name",
498 : "The save with name '",
499 4 : mg->getSavedMeshName(),
500 : "' has already been used");
501 51 : _save_in_meshes.emplace(mg->getSavedMeshName(), nullptr);
502 : }
503 :
504 : // Setup the children and parents
505 88632 : 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 31152 : auto & dependency_mg = getMeshGeneratorInternal(dependency);
512 31152 : mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
513 31152 : 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 88562 : for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
521 : {
522 31094 : const auto & param_name = param_dependency_pair.first;
523 31094 : const auto & dependency_name = param_dependency_pair.second;
524 :
525 31094 : if (mg->isNullMeshName(dependency_name))
526 31055 : continue;
527 :
528 : // True if this dependency was requested and is a parent
529 31068 : if (mg->isParentMeshGenerator(dependency_name))
530 : {
531 : mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
532 31029 : continue;
533 : }
534 :
535 : // Whether or not this is a dependency of at least one SubGenerator
536 39 : auto find_sub_dependency = std::find_if(mg->getSubMeshGenerators().begin(),
537 39 : mg->getSubMeshGenerators().end(),
538 97 : [&dependency_name](const auto & mg)
539 97 : { return mg->isParentMeshGenerator(dependency_name); });
540 39 : const auto is_sub_dependency = find_sub_dependency != mg->getSubMeshGenerators().end();
541 :
542 : // This should be used by a sub generator
543 39 : if (mg->getRequestedMeshGeneratorsForSub().count(dependency_name))
544 : {
545 31 : if (!is_sub_dependency)
546 4 : 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 8 : else if (is_sub_dependency)
555 8 : 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 4 : (*find_sub_dependency)->type(),
562 : " '",
563 4 : (*find_sub_dependency)->name(),
564 : "', but was not declared as a sub dependency.\n\nTo correct this, modify the code of ",
565 4 : 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 4 : 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 57468 : }
579 :
580 : mooseAssert(!_mesh_generators.count(generator_name), "Already created");
581 57468 : _mesh_generators.emplace(generator_name, mg);
582 : mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
583 57468 : _mesh_generator_outputs[generator_name];
584 57468 : _mesh_generator_params.erase(find_params);
585 :
586 114936 : return mg;
587 0 : }
588 :
589 : std::unique_ptr<MeshBase> &
590 56687 : MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
591 : {
592 : mooseAssert(_app.constructingMeshGenerators() ||
593 : _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
594 : "Incorrect call time");
595 :
596 56687 : auto it = _mesh_generator_outputs.find(name);
597 : mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
598 56687 : it->second.push_back(nullptr);
599 113374 : return it->second.back();
600 : }
601 :
602 : bool
603 62720 : MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
604 : {
605 62720 : return _mesh_generators.count(name);
606 : }
607 :
608 : bool
609 20 : MeshGeneratorSystem::hasMeshGeneratorParams(const MeshGeneratorName & name) const
610 : {
611 20 : return _mesh_generator_params.count(name);
612 : }
613 :
614 : const MeshGenerator &
615 60838 : MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
616 : {
617 60838 : const auto it = _mesh_generators.find(name);
618 60838 : if (it == _mesh_generators.end())
619 4 : mooseError("Failed to find a MeshGenerator with the name '", name, "'");
620 : mooseAssert(it->second, "Invalid shared pointer");
621 121668 : return *it->second;
622 : }
623 :
624 : std::vector<std::string>
625 109797 : MeshGeneratorSystem::getMeshGeneratorNames() const
626 : {
627 109797 : std::vector<std::string> names;
628 168371 : for (auto & pair : _mesh_generators)
629 58574 : names.push_back(pair.first);
630 109797 : return names;
631 0 : }
632 :
633 : std::vector<std::string>
634 17 : MeshGeneratorSystem::getSavedMeshNames() const
635 : {
636 17 : std::vector<std::string> names;
637 51 : for (auto & pair : _save_in_meshes)
638 34 : names.push_back(pair.first);
639 17 : return names;
640 0 : }
641 :
642 : std::unique_ptr<MeshBase>
643 24744 : MeshGeneratorSystem::getSavedMesh(const std::string & name)
644 : {
645 24744 : auto find_mesh = _save_in_meshes.find(name);
646 24744 : if (find_mesh == _save_in_meshes.end())
647 4 : mooseError("Failed to find a saved mesh with the name '", name, "'");
648 :
649 24740 : auto & mesh_unique_ptr = find_mesh->second;
650 24740 : if (!mesh_unique_ptr)
651 4 : mooseError("While getting the saved mesh generator '",
652 : name,
653 : "', said mesh has already been retrieved");
654 :
655 49472 : return std::move(mesh_unique_ptr);
656 : }
657 :
658 : bool
659 58477 : MeshGeneratorSystem::appendingMeshGenerators() const
660 : {
661 58477 : return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
662 : }
663 :
664 : bool
665 38 : MeshGeneratorSystem::hasDataDrivenAllowed() const
666 : {
667 38 : return _app.parameters().get<bool>(allow_data_driven_param);
668 : }
669 :
670 : const std::string &
671 150 : MeshGeneratorSystem::getDataDrivenGeneratorName() const
672 : {
673 : mooseAssert(_data_driven_generator_name, "Not set");
674 150 : return *_data_driven_generator_name;
675 : }
676 :
677 : void
678 8 : MeshGeneratorSystem::dataDrivenError(const MeshGenerator & generator,
679 : const std::string & message) const
680 : {
681 8 : const auto & moose_mesh = _app.actionWarehouse().getMesh();
682 16 : moose_mesh->paramError(data_driven_generator_param,
683 : "The generator '",
684 8 : getDataDrivenGeneratorName(),
685 : "' cannot be used in data-driven mode because the parent ",
686 8 : generator.typeAndName(),
687 : " ",
688 : message);
689 : }
690 :
691 : void
692 31 : MeshGeneratorSystem::setCSGOnly()
693 : {
694 31 : _csg_only = true;
695 31 : }
696 :
697 : void
698 13 : 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 13 : _csg_base_output[generator_name] = std::move(csg_base);
704 13 : }
705 :
706 : std::unique_ptr<CSG::CSGBase> &
707 13 : MeshGeneratorSystem::getCSGBaseGeneratorOutput(const MeshGeneratorName & name)
708 : {
709 : mooseAssert(_app.actionWarehouse().getCurrentTaskName() == "execute_csg_generators",
710 : "Incorrect call time");
711 :
712 13 : auto it = _csg_base_output.find(name);
713 : mooseAssert(it != _csg_base_output.end(), "CSG mesh not initialized");
714 26 : return it->second;
715 : }
|