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