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 69954 : MeshGeneratorSystem::MeshGeneratorSystem(MooseApp & app)
25 : : PerfGraphInterface(app.perfGraph(), "MeshGeneratorSystem"),
26 : ParallelObject(app),
27 69954 : _app(app),
28 69954 : _has_bmbb(false),
29 69954 : _verbose(false),
30 209862 : _csg_only(false)
31 : {
32 69954 : }
33 :
34 : void
35 58014 : 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 58014 : _mesh_generator_params.emplace(
41 58014 : 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 58014 : if (_app.constructingMeshGenerators())
46 244 : createMeshGenerator(name);
47 :
48 58010 : if (type == "BreakMeshByBlockGenerator")
49 268 : _has_bmbb = true;
50 58010 : }
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 115322 : MeshGeneratorSystem::getMeshGeneratorParamDependencies(const InputParameters & params,
108 : const bool allow_empty /* = false */) const
109 : {
110 115322 : std::vector<std::pair<std::string, MeshGeneratorName>> dependencies;
111 :
112 : auto add_dependency =
113 64568 : [&dependencies, &allow_empty](const auto & param_name, const auto & dependency)
114 : {
115 64568 : if (dependency.size() || allow_empty)
116 62652 : dependencies.emplace_back(param_name, dependency);
117 179890 : };
118 :
119 4408591 : for (const auto & [name, param] : params)
120 4293269 : if (const auto dependency =
121 4293269 : dynamic_cast<const Parameters::Parameter<MeshGeneratorName> *>(param.get()))
122 55084 : add_dependency(name, dependency->get());
123 4238185 : else if (const auto dependencies =
124 4238185 : dynamic_cast<const Parameters::Parameter<std::vector<MeshGeneratorName>> *>(
125 8476370 : param.get()))
126 : {
127 3912 : if (allow_empty && dependencies->get().empty())
128 0 : add_dependency(name, std::string());
129 13396 : for (const auto & dependency : dependencies->get())
130 9484 : add_dependency(name, dependency);
131 : }
132 :
133 230644 : return dependencies;
134 0 : }
135 :
136 : void
137 68814 : 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 68814 : if (_mesh_generator_params.empty())
144 42207 : return;
145 :
146 26607 : DependencyResolver<std::string> resolver;
147 :
148 : // Define the dependencies known so far
149 84373 : for (const auto & [name, type_params_pair] : _mesh_generator_params)
150 : {
151 57766 : resolver.addItem(name);
152 57766 : for (const auto & param_dependency_pair :
153 146818 : getMeshGeneratorParamDependencies(type_params_pair.second))
154 89052 : resolver.addEdge(param_dependency_pair.second, name);
155 : }
156 :
157 26607 : std::vector<std::vector<std::string>> ordered_generators;
158 : try
159 : {
160 26607 : 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 26603 : const auto & moose_mesh = _app.actionWarehouse().getMesh();
169 :
170 : // If there is no mesh
171 26603 : 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 53150 : if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
177 26547 : 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 26595 : const bool csg_only = getCSGOnly();
200 26595 : 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 79810 : for (const auto & generator_names : ordered_generators)
206 110706 : for (const auto & generator_name : generator_names)
207 57491 : if (auto it = _mesh_generator_params.find(generator_name); it != _mesh_generator_params.end())
208 : {
209 57458 : 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 114909 : (csg_only ||
214 57451 : (_data_driven_generator_name && getDataDrivenGeneratorName() != generator_name &&
215 60 : resolver.dependsOn(getDataDrivenGeneratorName(), generator_name)));
216 57458 : params.set<bool>(MeshGenerator::data_only_param) = data_only;
217 :
218 57458 : createMeshGenerator(generator_name);
219 :
220 57098 : 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 52414 : if (moose_mesh->parameters().get<bool>("_mesh_generator_mesh") &&
236 104772 : 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 26231 : }
249 :
250 : void
251 25214 : 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 126070 : TIME_SECTION("createMeshGeneratorOrder", 1, "Ordering Mesh Generators");
260 :
261 : // We dare not sort these based on address!
262 25214 : 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 25214 : std::vector<std::string> required_generators;
269 80270 : for (const auto & it : _mesh_generators)
270 55056 : 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 80270 : for (const auto & it : _mesh_generators)
278 : {
279 55056 : 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 116033 : (_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 55961 : required_generators.end())
295 : {
296 54378 : resolver.addItem(mg);
297 83808 : for (const auto & dep_mg : mg->getParentMeshGenerators())
298 29430 : resolver.addEdge(&getMeshGeneratorInternal(dep_mg->name()), mg);
299 : }
300 : }
301 :
302 : // ...and sort them
303 : try
304 : {
305 25214 : _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 25214 : const auto & final_generators = _ordered_mesh_generators.back();
329 :
330 : // We haven't forced a final generator yet
331 25214 : 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 24750 : const auto ancestor_list = resolver.getAncestors(final_generators.back());
337 24750 : 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 26 : for (const auto & gen : ind_tree)
361 : {
362 18 : if (!first)
363 10 : oss << ", ";
364 : else
365 8 : first = false;
366 :
367 18 : 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 24742 : _final_generator_name = final_generators.back()->name();
380 24742 : }
381 : else
382 : mooseAssert(hasMeshGenerator(_final_generator_name), "Missing the preset final generator");
383 25206 : }
384 :
385 : void
386 64192 : MeshGeneratorSystem::executeMeshGenerators()
387 : {
388 : libmesh_parallel_only(comm());
389 :
390 : // we do not need to do this when there are no mesh generators
391 64192 : if (_mesh_generators.empty())
392 39031 : return;
393 :
394 : // Order the generators
395 25201 : createMeshGeneratorOrder();
396 :
397 : // Save all meshes marked to to_save_in_meshes and save in error checking
398 25193 : std::map<std::string, std::unique_ptr<MeshBase> *> to_save_in_meshes;
399 75944 : for (const auto & generator_set : _ordered_mesh_generators)
400 105088 : for (const auto & generator : generator_set)
401 54337 : 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 25189 : to_save_in_meshes.emplace(mainMeshGeneratorName(),
413 50378 : &getMeshGeneratorOutput(_final_generator_name));
414 :
415 : // Run the MeshGenerators in the proper order
416 75424 : for (const auto & generator_set : _ordered_mesh_generators)
417 : {
418 104540 : for (const auto & generator : generator_set)
419 : {
420 54305 : const auto & name = generator->name();
421 54305 : 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 54305 : auto current_mesh = generator->generateInternal();
426 :
427 : // Only generating data for this generator
428 53809 : if (generator->isDataOnly())
429 : {
430 : mooseAssert(!current_mesh, "Should not have a mesh");
431 113 : 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 53696 : auto & outputs = _mesh_generator_outputs[name];
446 :
447 53696 : if (outputs.size())
448 : {
449 53551 : auto & first_output = *outputs.begin();
450 :
451 53551 : first_output = std::move(current_mesh);
452 :
453 53551 : const auto & copy_from = *first_output;
454 :
455 53551 : auto output_it = ++outputs.begin();
456 :
457 : // For all of the rest we need to make a copy
458 54210 : for (; output_it != outputs.end(); ++output_it)
459 659 : (*output_it) = copy_from.clone();
460 : }
461 53809 : }
462 : }
463 :
464 : // No save in meshes exist in csg only mode
465 24693 : if (getCSGOnly())
466 40 : 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 49347 : for (auto & [name, mesh_ptr] : to_save_in_meshes)
471 : {
472 : mooseAssert(mesh_ptr, "Invalid pointer");
473 : mooseAssert(*mesh_ptr, "Invalid pointer");
474 24694 : if (name != mainMeshGeneratorName())
475 : mooseAssert(_save_in_meshes.count(name), "Mesh has not been requested for save");
476 24694 : _save_in_meshes[name] = std::move(*mesh_ptr);
477 : }
478 24705 : }
479 :
480 : std::shared_ptr<MeshGenerator>
481 57801 : MeshGeneratorSystem::createMeshGenerator(const std::string & generator_name)
482 : {
483 : libmesh_parallel_only(comm());
484 : mooseAssert(_app.constructingMeshGenerators(), "Should not run now");
485 :
486 57801 : const auto find_params = _mesh_generator_params.find(generator_name);
487 : mooseAssert(find_params != _mesh_generator_params.end(), "Not added");
488 57801 : 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 57801 : _app.getFactory().create<MeshGenerator>(type, generator_name, params);
493 :
494 57453 : 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 88637 : 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 31188 : auto & dependency_mg = getMeshGeneratorInternal(dependency);
512 31188 : mg->addParentMeshGenerator(dependency_mg, MeshGenerator::AddParentChildKey());
513 31188 : 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 88567 : for (const auto & param_dependency_pair : getMeshGeneratorParamDependencies(mg->parameters()))
521 : {
522 31130 : const auto & param_name = param_dependency_pair.first;
523 31130 : const auto & dependency_name = param_dependency_pair.second;
524 :
525 31130 : if (mg->isNullMeshName(dependency_name))
526 31091 : continue;
527 :
528 : // True if this dependency was requested and is a parent
529 31104 : if (mg->isParentMeshGenerator(dependency_name))
530 : {
531 : mooseAssert(mg->getRequestedMeshGenerators().count(dependency_name), "Wasn't requested");
532 31065 : 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 57437 : }
579 :
580 : mooseAssert(!_mesh_generators.count(generator_name), "Already created");
581 57437 : _mesh_generators.emplace(generator_name, mg);
582 : mooseAssert(!_mesh_generator_outputs.count(generator_name), "Already exists");
583 57437 : _mesh_generator_outputs[generator_name];
584 57437 : if (getCSGOnly())
585 : {
586 : mooseAssert(!_csg_base_outputs.count(generator_name), "CSG already exists");
587 89 : _csg_base_outputs[generator_name];
588 : }
589 57437 : _mesh_generator_params.erase(find_params);
590 :
591 114874 : return mg;
592 0 : }
593 :
594 : std::unique_ptr<MeshBase> &
595 56666 : MeshGeneratorSystem::getMeshGeneratorOutput(const MeshGeneratorName & name)
596 : {
597 : mooseAssert(_app.constructingMeshGenerators() ||
598 : _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
599 : "Incorrect call time");
600 :
601 56666 : auto it = _mesh_generator_outputs.find(name);
602 : mooseAssert(it != _mesh_generator_outputs.end(), "Not initialized");
603 56666 : it->second.push_back(nullptr);
604 113332 : return it->second.back();
605 : }
606 :
607 : bool
608 62882 : MeshGeneratorSystem::hasMeshGenerator(const MeshGeneratorName & name) const
609 : {
610 62882 : return _mesh_generators.count(name);
611 : }
612 :
613 : bool
614 20 : MeshGeneratorSystem::hasMeshGeneratorParams(const MeshGeneratorName & name) const
615 : {
616 20 : return _mesh_generator_params.count(name);
617 : }
618 :
619 : const MeshGenerator &
620 60946 : MeshGeneratorSystem::getMeshGenerator(const std::string & name) const
621 : {
622 60946 : const auto it = _mesh_generators.find(name);
623 60946 : if (it == _mesh_generators.end())
624 4 : mooseError("Failed to find a MeshGenerator with the name '", name, "'");
625 : mooseAssert(it->second, "Invalid shared pointer");
626 121884 : return *it->second;
627 : }
628 :
629 : std::vector<std::string>
630 109643 : MeshGeneratorSystem::getMeshGeneratorNames() const
631 : {
632 109643 : std::vector<std::string> names;
633 168149 : for (auto & pair : _mesh_generators)
634 58506 : names.push_back(pair.first);
635 109643 : return names;
636 0 : }
637 :
638 : std::vector<std::string>
639 17 : MeshGeneratorSystem::getSavedMeshNames() const
640 : {
641 17 : std::vector<std::string> names;
642 51 : for (auto & pair : _save_in_meshes)
643 34 : names.push_back(pair.first);
644 17 : return names;
645 0 : }
646 :
647 : std::unique_ptr<MeshBase>
648 24678 : MeshGeneratorSystem::getSavedMesh(const std::string & name)
649 : {
650 24678 : auto find_mesh = _save_in_meshes.find(name);
651 24678 : if (find_mesh == _save_in_meshes.end())
652 4 : mooseError("Failed to find a saved mesh with the name '", name, "'");
653 :
654 24674 : auto & mesh_unique_ptr = find_mesh->second;
655 24674 : if (!mesh_unique_ptr)
656 4 : mooseError("While getting the saved mesh generator '",
657 : name,
658 : "', said mesh has already been retrieved");
659 :
660 49340 : return std::move(mesh_unique_ptr);
661 : }
662 :
663 : bool
664 58446 : MeshGeneratorSystem::appendingMeshGenerators() const
665 : {
666 58446 : return _app.actionWarehouse().getCurrentTaskName() == "append_mesh_generator";
667 : }
668 :
669 : bool
670 38 : MeshGeneratorSystem::hasDataDrivenAllowed() const
671 : {
672 38 : return _app.parameters().get<bool>(allow_data_driven_param);
673 : }
674 :
675 : const std::string &
676 150 : MeshGeneratorSystem::getDataDrivenGeneratorName() const
677 : {
678 : mooseAssert(_data_driven_generator_name, "Not set");
679 150 : return *_data_driven_generator_name;
680 : }
681 :
682 : void
683 8 : MeshGeneratorSystem::dataDrivenError(const MeshGenerator & generator,
684 : const std::string & message) const
685 : {
686 8 : const auto & moose_mesh = _app.actionWarehouse().getMesh();
687 16 : moose_mesh->paramError(data_driven_generator_param,
688 : "The generator '",
689 8 : getDataDrivenGeneratorName(),
690 : "' cannot be used in data-driven mode because the parent ",
691 8 : generator.typeAndName(),
692 : " ",
693 : message);
694 : }
695 :
696 : void
697 40 : MeshGeneratorSystem::setCSGOnly()
698 : {
699 40 : _csg_only = true;
700 40 : }
701 :
702 : void
703 40 : MeshGeneratorSystem::saveOutputCSGBase(const MeshGeneratorName generator_name,
704 : std::unique_ptr<CSG::CSGBase> & csg_base)
705 : {
706 40 : auto & outputs = _csg_base_outputs[generator_name];
707 :
708 : // Store CSGBase instance for any downstream MG's that request it, creating copies
709 : // as needed
710 40 : if (outputs.size())
711 : {
712 : // Set first output to csg_base
713 40 : auto & first_output = *outputs.begin();
714 40 : first_output = std::move(csg_base);
715 40 : const auto & copy_from = *first_output;
716 40 : auto output_it = ++outputs.begin();
717 : // For all of the rest we create a clone of csg_base
718 49 : for (; output_it != outputs.end(); ++output_it)
719 9 : (*output_it) = copy_from.clone();
720 : }
721 40 : }
722 :
723 : std::unique_ptr<CSG::CSGBase> &
724 58 : MeshGeneratorSystem::getCSGBaseGeneratorOutput(const MeshGeneratorName & name)
725 : {
726 : mooseAssert(_app.constructingMeshGenerators() ||
727 : _app.actionWarehouse().getCurrentTaskName() == "execute_mesh_generators",
728 : "Incorrect call time");
729 :
730 58 : auto it = _csg_base_outputs.find(name);
731 : mooseAssert(it != _csg_base_outputs.end(), "CSG mesh not initialized");
732 58 : it->second.push_back(nullptr);
733 116 : return it->second.back();
734 : }
|