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 : #pragma once
11 :
12 : #ifdef MOOSE_LIBTORCH_ENABLED
13 : // Libtorch includes
14 : #include <torch/types.h>
15 : #include <torch/mps.h>
16 : #include <torch/cuda.h>
17 : #include <c10/core/DeviceType.h>
18 : #endif
19 :
20 : #ifdef MOOSE_MFEM_ENABLED
21 : #include "libmesh/ignore_warnings.h"
22 : #include <mfem.hpp>
23 : #include "libmesh/restore_warnings.h"
24 : #endif
25 :
26 : // MOOSE includes
27 : #include "Moose.h"
28 : #include "Parser.h"
29 : #include "Builder.h"
30 : #include "ActionWarehouse.h"
31 : #include "Factory.h"
32 : #include "ActionFactory.h"
33 : #include "OutputWarehouse.h"
34 : #include "RestartableData.h"
35 : #include "RestartableDataMap.h"
36 : #include "ConsoleStreamInterface.h"
37 : #include "PerfGraph.h"
38 : #include "PerfGraphInterface.h"
39 : #include "TheWarehouse.h"
40 : #include "RankMap.h"
41 : #include "MeshGeneratorSystem.h"
42 : #include "ChainControlDataSystem.h"
43 : #include "RestartableDataReader.h"
44 : #include "Backup.h"
45 : #include "MooseBase.h"
46 : #include "Capabilities.h"
47 : #include "MoosePassKey.h"
48 :
49 : #include "libmesh/parallel_object.h"
50 : #include "libmesh/mesh_base.h"
51 : #include "libmesh/point.h"
52 :
53 : // C++ includes
54 : #include <list>
55 : #include <map>
56 : #include <set>
57 : #include <unordered_set>
58 : #include <typeindex>
59 : #include <filesystem>
60 : #include <variant>
61 :
62 : // Forward declarations
63 : class Executioner;
64 : class Executor;
65 : class NullExecutor;
66 : class FEProblemBase;
67 : class InputParameterWarehouse;
68 : class SystemInfo;
69 : class CommandLine;
70 : class RelationshipManager;
71 : class SolutionInvalidity;
72 : class MultiApp;
73 : #ifdef MOOSE_MFEM_ENABLED
74 : class MFEMExecutioner;
75 : #endif
76 :
77 : namespace libMesh
78 : {
79 : class ExodusII_IO;
80 : }
81 : namespace hit
82 : {
83 : class Node;
84 : }
85 :
86 : /**
87 : * Base class for MOOSE-based applications
88 : *
89 : * This generic class for application provides:
90 : * - parsing command line arguments,
91 : * - parsing an input file,
92 : * - executing the simulation
93 : *
94 : * Each application should register its own objects and register its own special syntax
95 : */
96 : class MooseApp : public ConsoleStreamInterface,
97 : public PerfGraphInterface,
98 : public libMesh::ParallelObject,
99 : public MooseBase
100 : {
101 : public:
102 : /// Get the device accelerated computations are supposed to be running on.
103 : std::optional<MooseEnum> getComputeDevice() const;
104 :
105 : #ifdef MOOSE_LIBTORCH_ENABLED
106 : /// Get the device torch is supposed to be running on.
107 62 : torch::DeviceType getLibtorchDevice() const { return _libtorch_device; }
108 : #endif
109 :
110 : /**
111 : * Stores configuration options relating to the fixed-point solving
112 : * capability. This is used for communicating input-file-based config from
113 : * the MultiApp object/syntax to the execution (e.g. executor) system.
114 : */
115 : struct FixedPointConfig
116 : {
117 67610 : FixedPointConfig() : sub_relaxation_factor(1.0) {}
118 : /// relaxation factor to be used for a MultiApp's subapps.
119 : Real sub_relaxation_factor;
120 : /// The names of variables to transform for fixed point solve algorithms (e.g. secant, etc.).
121 : std::vector<std::string> sub_transformed_vars;
122 : /// The names of postprocessors to transform for fixed point solve algorithms (e.g. secant, etc.).
123 : std::vector<PostprocessorName> sub_transformed_pps;
124 : };
125 :
126 : static const RestartableDataMapName MESH_META_DATA;
127 : static const std::string MESH_META_DATA_SUFFIX;
128 :
129 : static InputParameters validParams();
130 :
131 : virtual ~MooseApp();
132 :
133 33173001 : TheWarehouse & theWarehouse() { return *_the_warehouse; }
134 :
135 : /**
136 : * Get printable name of the application.
137 : */
138 34 : virtual std::string getPrintableName() const { return "Application"; }
139 :
140 21 : virtual std::string appBinaryName() const
141 : {
142 21 : auto name = Moose::getExecutableName();
143 21 : name = name.substr(0, name.find_last_of("-"));
144 21 : if (name.find_first_of("/") != std::string::npos)
145 21 : name = name.substr(name.find_first_of("/") + 1, std::string::npos);
146 21 : return name;
147 0 : }
148 :
149 : /**
150 : * Get the shell exit code for the application
151 : * @return The shell exit code
152 : */
153 50860 : int exitCode() const { return _exit_code; }
154 :
155 : /**
156 : * Sets the exit code that the application will exit with.
157 : */
158 245 : void setExitCode(const int exit_code) { _exit_code = exit_code; }
159 :
160 : /**
161 : * Get the parameters of the object
162 : * @return The parameters of the object
163 : */
164 676396 : const InputParameters & parameters() { return _pars; }
165 :
166 : /**
167 : * The RankMap is a useful object for determining how the processes
168 : * are laid out on the physical nodes of the cluster
169 : */
170 962 : const RankMap & rankMap() { return _rank_map; }
171 :
172 : /**
173 : * Get the PerfGraph for this app
174 : */
175 104672464 : PerfGraph & perfGraph() { return _perf_graph; }
176 :
177 : /**
178 : * Get the SolutionInvalidity for this app
179 : */
180 : ///@{
181 12911823 : SolutionInvalidity & solutionInvalidity() { return _solution_invalidity; }
182 : const SolutionInvalidity & solutionInvalidity() const { return _solution_invalidity; }
183 : ///@}
184 :
185 : ///@{
186 : /**
187 : * Retrieve a parameter for the object
188 : * @param name The name of the parameter
189 : * @return The value of the parameter
190 : */
191 : template <typename T>
192 : const T & getParam(const std::string & name);
193 :
194 : template <typename T>
195 : const T & getParam(const std::string & name) const;
196 : ///@}
197 :
198 : /**
199 : * Retrieve a renamed parameter for the object. This helper makes sure we
200 : * check both names before erroring, and that only one parameter is passed to avoid
201 : * silent errors
202 : * @param old_name the old name for the parameter
203 : * @param new_name the new name for the parameter
204 : */
205 : template <typename T>
206 : const T & getRenamedParam(const std::string & old_name, const std::string & new_name) const;
207 :
208 867151 : inline bool isParamValid(const std::string & name) const { return _pars.isParamValid(name); }
209 :
210 1147623 : inline bool isParamSetByUser(const std::string & nm) const { return _pars.isParamSetByUser(nm); }
211 :
212 : /**
213 : * Run the application
214 : */
215 : virtual void run();
216 :
217 : /**
218 : * Returns the framework version.
219 : */
220 : std::string getFrameworkVersion() const;
221 :
222 : /**
223 : * Returns the current version of the framework or application (default: framework version).
224 : */
225 : virtual std::string getVersion() const;
226 :
227 : /**
228 : * Non-virtual method for printing out the version string in a consistent format.
229 : */
230 : std::string getPrintableVersion() const;
231 :
232 : /**
233 : * Setup options based on InputParameters.
234 : */
235 : virtual void setupOptions();
236 :
237 : /**
238 : * Return a writable reference to the ActionWarehouse associated with this app
239 : */
240 8616131 : ActionWarehouse & actionWarehouse() { return _action_warehouse; }
241 : /**
242 : * Return a const reference to the ActionWarehouse associated with this app
243 : */
244 : const ActionWarehouse & actionWarehouse() const { return _action_warehouse; }
245 :
246 : /**
247 : * Returns a writable reference to the builder
248 : */
249 31250 : Moose::Builder & builder() { return _builder; }
250 :
251 : /**
252 : * Returns a writable reference to the syntax object.
253 : */
254 2398 : Syntax & syntax() { return _syntax; }
255 :
256 : /**
257 : * @return the input file names set in the Parser
258 : */
259 : const std::vector<std::string> & getInputFileNames() const;
260 :
261 : /**
262 : * @return The last input filename set (if any)
263 : */
264 : const std::string & getLastInputFileName() const;
265 :
266 : /**
267 : * Override the selection of the output file base name.
268 : * Note: This method is supposed to be called by MultiApp only.
269 : */
270 : void setOutputFileBase(const std::string & output_file_base);
271 :
272 : /**
273 : * Get the output file base name.
274 : * @param for_non_moose_build_output True for getting the file base for outputs generated with
275 : * Outputs/[outputname] input syntax.
276 : * @return The file base name used by output objects
277 : * Note: for_non_moose_build_output does not affect the returned value when this is a subapp.
278 : * for_non_moose_build_output also does not affect the returned value when Outputs/file_base
279 : * parameter is available. When for_non_moose_build_output does affect the returned value,
280 : * i.e. master without Outputs/file_base, the suffix _out is removed.
281 : */
282 : std::string getOutputFileBase(bool for_non_moose_build_output = false) const;
283 :
284 : /**
285 : * Tell the app to output in a specific position.
286 : */
287 : void setOutputPosition(const Point & p);
288 :
289 : /**
290 : * Get all checkpoint directories
291 : * @return A Set of checkpoint directories
292 : */
293 : std::list<std::string> getCheckpointDirectories() const;
294 :
295 : /**
296 : * Extract all possible checkpoint file names
297 : * @return A Set of checkpoint filenames
298 : */
299 : std::list<std::string> getCheckpointFiles() const;
300 :
301 : /**
302 : * Whether or not an output position has been set.
303 : * @return True if it has
304 : */
305 171127 : bool hasOutputPosition() const { return _output_position_set; }
306 :
307 : /**
308 : * Get the output position.
309 : * @return The position offset for the output.
310 : */
311 9820 : Point getOutputPosition() const { return _output_position; }
312 :
313 : /**
314 : * Set the starting time for the simulation. This will override any choice
315 : * made in the input file.
316 : *
317 : * @param time The start time for the simulation.
318 : */
319 : void setStartTime(Real time);
320 :
321 : /**
322 : * @return Whether or not a start time has been programmatically set using setStartTime()
323 : */
324 31094 : bool hasStartTime() const { return _start_time_set; }
325 :
326 : /**
327 : * @return The start time
328 : */
329 18383 : Real getStartTime() const { return _start_time; }
330 :
331 : /**
332 : * Each App has it's own local time. The "global" time of the whole problem might be
333 : * different. This offset is how far off the local App time is from the global time.
334 : */
335 12364 : void setGlobalTimeOffset(Real offset) { _global_time_offset = offset; }
336 :
337 : /**
338 : * Each App has it's own local time. The "global" time of the whole problem might be
339 : * different. This offset is how far off the local App time is from the global time.
340 : */
341 388909 : Real getGlobalTimeOffset() const { return _global_time_offset; }
342 :
343 : /**
344 : * Return the primary (first) filename that was parsed
345 : * Note: When stripLeadingPath is false, this function returns the same name as
346 : * getInputFileName() method when the input file is not a link.
347 : */
348 : std::string getFileName(bool stripLeadingPath = true) const;
349 :
350 : /**
351 : * Set a flag so that the parser will throw an error if overridden parameters are detected
352 : */
353 : void setErrorOverridden();
354 :
355 : /**
356 : * Removes warnings and error checks for unrecognized variables in the input file
357 : */
358 : void disableCheckUnusedFlag();
359 :
360 : /**
361 : * Retrieve the Executioner for this App
362 : */
363 : Executioner * getExecutioner() const;
364 8 : Executor * getExecutor() const { return _executor.get(); }
365 92 : NullExecutor * getNullExecutor() const { return _null_executor.get(); }
366 : bool useExecutor() const { return _use_executor; }
367 : FEProblemBase & feProblem() const;
368 :
369 : /**
370 : * Set the Executioner for this App
371 : */
372 62125 : void setExecutioner(std::shared_ptr<Executioner> && executioner) { _executioner = executioner; }
373 : void setExecutor(std::shared_ptr<Executor> && executor) { _executor = executor; }
374 : void
375 : addExecutor(const std::string & type, const std::string & name, const InputParameters & params);
376 :
377 : /**
378 : * Adds the parameters for an Executor to the list of parameters. This is done
379 : * so that the Executors can be created in _exactly_ the correct order.
380 : */
381 : void addExecutorParams(const std::string & type,
382 : const std::string & name,
383 : const InputParameters & params);
384 :
385 : /**
386 : * @return The Parser
387 : **/
388 : Parser & parser();
389 :
390 : /**
391 : * After adding all of the Executor Params - this function will actually cause all of them to be
392 : * built
393 : */
394 : void createExecutors();
395 :
396 : /**
397 : * Get an Executor
398 : *
399 : * @param name The name of the Executor
400 : * @param fail_if_not_found Whether or not to fail if the executor doesn't exist. If this is
401 : * false then this function will return a NullExecutor
402 : */
403 : Executor & getExecutor(const std::string & name, bool fail_if_not_found = true);
404 :
405 : /**
406 : * This info is stored here because we need a "globalish" place to put it in
407 : * order to allow communication between a multiapp and solver-specific
408 : * internals (i.e. relating to fixed-point inner loops like picard, etc.)
409 : * for handling subapp-specific modifications necessary for those solve
410 : * processes.
411 : */
412 74136 : FixedPointConfig & fixedPointConfig() { return _fixed_point_config; }
413 :
414 : /**
415 : * Returns a writable Boolean indicating whether this app will use a Nonlinear or Eigen System.
416 : */
417 124680 : bool & useNonlinear() { return _use_nonlinear; }
418 :
419 : /**
420 : * Returns a writable Boolean indicating whether this app will use an eigenvalue executioner.
421 : */
422 124696 : bool & useEigenvalue() { return _use_eigen_value; }
423 :
424 : /**
425 : * Retrieve a writable reference to the Factory associated with this App.
426 : */
427 8579286 : Factory & getFactory() { return _factory; }
428 :
429 : /**
430 : * Retrieve a writable reference to the ActionFactory associated with this App.
431 : */
432 8974235 : ActionFactory & getActionFactory() { return _action_factory; }
433 :
434 : /**
435 : * Returns the MPI processor ID of the current processor.
436 : */
437 198369 : processor_id_type processor_id() const { return _comm->rank(); }
438 :
439 : /**
440 : * Get the command line
441 : * @return The reference to the command line object
442 : * Setup options based on InputParameters.
443 : */
444 293643 : std::shared_ptr<CommandLine> commandLine() const { return _command_line; }
445 :
446 : /**
447 : * Set the flag to indicate whether or not we need to use a separate Exodus reader to read the
448 : * mesh BEFORE we create the mesh.
449 : */
450 442 : void setExodusFileRestart(bool flag) { _initial_from_file = flag; }
451 :
452 : /**
453 : * Whether or not we need to use a separate Exodus reader to read the mesh BEFORE we create the
454 : * mesh.
455 : */
456 74035 : bool getExodusFileRestart() const { return _initial_from_file; }
457 :
458 : /**
459 : * Set the Exodus reader to restart variables from an Exodus mesh file
460 : */
461 297 : void setExReaderForRestart(std::shared_ptr<libMesh::ExodusII_IO> && exreader)
462 : {
463 297 : _ex_reader = exreader;
464 297 : }
465 :
466 : /**
467 : * Get the Exodus reader to restart variables from an Exodus mesh file
468 : */
469 148628 : libMesh::ExodusII_IO * getExReaderForRestart() const { return _ex_reader.get(); }
470 :
471 : /**
472 : * Actually build everything in the input file.
473 : */
474 : virtual void runInputFile();
475 :
476 : /**
477 : * Execute the Executioner that was built.
478 : */
479 : virtual void executeExecutioner();
480 :
481 : /**
482 : * Returns true if the user specified --distributed-mesh (or
483 : * --parallel-mesh, for backwards compatibility) on the command line
484 : * and false otherwise.
485 : */
486 65468 : bool getDistributedMeshOnCommandLine() const { return _distributed_mesh_on_command_line; }
487 :
488 : /**
489 : * Whether or not this is a "recover" calculation. More specifically whether this simulation has
490 : * been recovered with something like the \p --recover command line argument. Note that this will
491 : * never return true when \p isRestarting is true
492 : */
493 : bool isRecovering() const;
494 :
495 : /**
496 : * Whether or not this is a "restart" calculation. More specifically whether this has been
497 : * restarted using the \p Problem/restart_file_base parameter. Note that this will only return
498 : * true when doing \emph checkpoint restart. This will be false if doing \emph exodus restart.
499 : * Finally this will never return true when \p isRecovering is true
500 : */
501 : bool isRestarting() const;
502 :
503 : /**
504 : * Whether or not this is a split mesh operation.
505 : */
506 : bool isSplitMesh() const;
507 :
508 : ///@{
509 : /**
510 : * Return true if the recovery file base is set
511 : */
512 : bool hasRestartRecoverFileBase() const;
513 : bool hasRecoverFileBase() const;
514 : ///@}
515 :
516 : ///@{
517 : /**
518 : * The file_base for the recovery file.
519 : */
520 15109 : std::string getRestartRecoverFileBase() const { return _restart_recover_base; }
521 : std::string getRecoverFileBase() const
522 : {
523 : mooseDeprecated("MooseApp::getRecoverFileBase is deprecated, use "
524 : "MooseApp::getRestartRecoverFileBase() instead.");
525 : return _restart_recover_base;
526 : }
527 : ///@}
528 :
529 : /**
530 : * mutator for recover_base (set by RecoverBaseAction)
531 : */
532 3366 : void setRestartRecoverFileBase(const std::string & file_base)
533 : {
534 3366 : if (file_base.empty())
535 2900 : _restart_recover_base = MooseUtils::getLatestCheckpointFilePrefix(getCheckpointFiles());
536 : else
537 466 : _restart_recover_base = file_base;
538 3358 : }
539 :
540 : /**
541 : * Whether or not this simulation should only run half its transient (useful for testing
542 : * recovery)
543 : */
544 115103 : bool testCheckpointHalfTransient() const { return _test_checkpoint_half_transient; }
545 :
546 : /**
547 : * Whether or not this simulation should fail a timestep and repeat (for testing).
548 : * Selection rules for which time step to fail in TransientBase.C constructor.
549 : */
550 60877 : bool testReStep() const { return _test_restep; }
551 :
552 : /**
553 : * Store a map of outputter names and file numbers
554 : * The MultiApp system requires this to get the file numbering to propagate down through the
555 : * Multiapps.
556 : * @param numbers Map of outputter names and file numbers
557 : *
558 : * @see MultiApp TransientMultiApp OutputWarehouse
559 : */
560 12364 : void setOutputFileNumbers(const std::map<std::string, unsigned int> & numbers)
561 : {
562 12364 : _output_file_numbers = numbers;
563 12364 : }
564 :
565 : /**
566 : * Store a map of outputter names and file numbers
567 : * The MultiApp system requires this to get the file numbering to propogate down through the
568 : * multiapps.
569 : *
570 : * @see MultiApp TransientMultiApp
571 : */
572 8446 : const std::map<std::string, unsigned int> & getOutputFileNumbers() const
573 : {
574 8446 : return _output_file_numbers;
575 : }
576 :
577 : /**
578 : * Get the OutputWarehouse objects
579 : */
580 : OutputWarehouse & getOutputWarehouse();
581 : const OutputWarehouse & getOutputWarehouse() const;
582 :
583 : /**
584 : * Get SystemInfo object
585 : * @return A pointer to the SystemInformation object
586 : */
587 166806 : const SystemInfo * getSystemInfo() const { return _sys_info.get(); }
588 :
589 : ///@{
590 : /**
591 : * Thes methods are called to register applications or objects on demand. This method
592 : * attempts to load a dynamic library and register it when it is needed. Throws an error if
593 : * no suitable library is found that contains the app_name in question.
594 : */
595 : void dynamicAllRegistration(const std::string & app_name,
596 : Factory * factory,
597 : ActionFactory * action_factory,
598 : Syntax * syntax,
599 : std::string library_path,
600 : const std::string & library_name);
601 : void dynamicAppRegistration(const std::string & app_name,
602 : std::string library_path,
603 : const std::string & library_name,
604 : bool lib_load_deps);
605 : ///@}
606 :
607 : /**
608 : * Converts an application name to a library name:
609 : * Examples:
610 : * AnimalApp -> libanimal-oprof.la (assuming METHOD=oprof)
611 : * ThreeWordAnimalApp -> libthree_word_animal-dbg.la (assuming METHOD=dbg)
612 : */
613 : std::string appNameToLibName(const std::string & app_name) const;
614 :
615 : /**
616 : * Converts a library name to an application name:
617 : */
618 : std::string libNameToAppName(const std::string & library_name) const;
619 :
620 : /**
621 : * Return the paths of loaded libraries
622 : */
623 : std::set<std::string> getLoadedLibraryPaths() const;
624 :
625 : /**
626 : * Return the paths searched by MOOSE when loading libraries
627 : */
628 : std::set<std::string> getLibrarySearchPaths(const std::string & library_path_from_param) const;
629 :
630 : /**
631 : * Get the InputParameterWarehouse for MooseObjects
632 : */
633 : InputParameterWarehouse & getInputParameterWarehouse();
634 :
635 : /*
636 : * Register a piece of restartable data. This is data that will get
637 : * written / read to / from a restart file.
638 : *
639 : * @param data The actual data object.
640 : * @param tid The thread id of the object. Use 0 if the object is not threaded.
641 : * @param read_only Restrict the data for read-only
642 : * @param metaname (optional) register the data to the meta data storage (tid must be 0)
643 : */
644 : RestartableDataValue & registerRestartableData(std::unique_ptr<RestartableDataValue> data,
645 : THREAD_ID tid,
646 : bool read_only,
647 : const RestartableDataMapName & metaname = "");
648 :
649 : /*
650 : * Deprecated method to register a piece of restartable data.
651 : *
652 : * Use the call without a data name instead.
653 : */
654 : RestartableDataValue & registerRestartableData(const std::string & name,
655 : std::unique_ptr<RestartableDataValue> data,
656 : THREAD_ID tid,
657 : bool read_only,
658 : const RestartableDataMapName & metaname = "");
659 :
660 : /*
661 : * Check if a restartable meta data exists or not.
662 : *
663 : * @param name The full (unique) name.
664 : * @param metaname The name to the meta data storage
665 : */
666 : bool hasRestartableMetaData(const std::string & name,
667 : const RestartableDataMapName & metaname) const;
668 :
669 : /*
670 : * Retrieve restartable meta data from restartable data map
671 : *
672 : * @param name The full (unique) name.
673 : * @param metaname The name to the meta data storage
674 : * @return A reference to the restartable meta data value
675 : */
676 : RestartableDataValue & getRestartableMetaData(const std::string & name,
677 : const RestartableDataMapName & metaname,
678 : THREAD_ID tid);
679 :
680 : /**
681 : * Loads the restartable meta data for \p name if it is available with the folder base \p
682 : * folder_base
683 : */
684 : void possiblyLoadRestartableMetaData(const RestartableDataMapName & name,
685 : const std::filesystem::path & folder_base);
686 : /**
687 : * Loads all available restartable meta data if it is available with the folder base \p
688 : * folder_base
689 : */
690 : void loadRestartableMetaData(const std::filesystem::path & folder_base);
691 :
692 : /**
693 : * Writes the restartable meta data for \p name with a folder base of \p folder_base
694 : *
695 : * @return The files that were written
696 : */
697 : std::vector<std::filesystem::path>
698 : writeRestartableMetaData(const RestartableDataMapName & name,
699 : const std::filesystem::path & folder_base);
700 : /**
701 : * Writes all available restartable meta data with a file base of \p file_base
702 : *
703 : * @return The files that were written
704 : */
705 : std::vector<std::filesystem::path>
706 : writeRestartableMetaData(const std::filesystem::path & folder_base);
707 :
708 : /**
709 : * Return reference to the restartable data object
710 : * @return A reference to the restartable data object
711 : */
712 : ///@{
713 : const std::vector<RestartableDataMap> & getRestartableData() const { return _restartable_data; }
714 54 : std::vector<RestartableDataMap> & getRestartableData() { return _restartable_data; }
715 : ///@}
716 :
717 : /**
718 : * Return a reference to restartable data for the specific type flag.
719 : */
720 : RestartableDataMap & getRestartableDataMap(const RestartableDataMapName & name);
721 :
722 : /**
723 : * @return Whether or not the restartable data has the given name registered.
724 : */
725 : bool hasRestartableDataMap(const RestartableDataMapName & name) const;
726 :
727 : /**
728 : * Reserve a location for storing custom RestartableDataMap objects.
729 : *
730 : * This should be called in the constructor of an application.
731 : *
732 : * @param name A key to use for accessing the data object
733 : * @param suffix The suffix to use when appending to checkpoint output, if not supplied the
734 : * given name is used to generate the suffix (MyMetaData -> _mymetadata)
735 : */
736 : void registerRestartableDataMapName(const RestartableDataMapName & name, std::string suffix = "");
737 :
738 : /**
739 : * @return The output name for the restartable data with name \p name
740 : */
741 : const std::string & getRestartableDataMapName(const RestartableDataMapName & name) const;
742 :
743 : /**
744 : * Return a reference to the recoverable data object
745 : * @return A const reference to the recoverable data
746 : */
747 515 : const DataNames & getRecoverableData() const { return _recoverable_data_names; }
748 :
749 : /**
750 : * Backs up the application to the folder \p folder_base
751 : *
752 : * @return The files that are written in the backup
753 : */
754 : std::vector<std::filesystem::path> backup(const std::filesystem::path & folder_base);
755 : /**
756 : * Backs up the application memory in a Backup.
757 : *
758 : * @return The backup
759 : */
760 : std::unique_ptr<Backup> backup();
761 :
762 : /**
763 : * Insertion point for other apps that is called before backup()
764 : */
765 45210 : virtual void preBackup() {}
766 :
767 : /**
768 : * Restore an application from file
769 :
770 : * @param folder_base The backup folder base
771 : * @param for_restart Whether this restoration is explicitly for the first restoration of restart
772 : * data
773 : *
774 : * You must call finalizeRestore() after this in order to finalize the restoration.
775 : * The restore process is kept open in order to restore additional data after
776 : * the initial restore (that is, the restoration of data that has already been declared).
777 : */
778 : void restore(const std::filesystem::path & folder_base, const bool for_restart);
779 :
780 : /**
781 : * Restore an application from the backup \p backup
782 : *
783 : * @param backup The backup
784 : * @param for_restart Whether this restoration is explicitly for the first restoration of restart
785 : * data
786 : *
787 : * You must call finalizeRestore() after this in order to finalize the restoration.
788 : * The restore process is kept open in order to restore additional data after
789 : * the initial restore (that is, the restoration of data that has already been declared).
790 : */
791 : void restore(std::unique_ptr<Backup> backup, const bool for_restart);
792 :
793 : /**
794 : * Insertion point for other apps that is called after restore()
795 : *
796 : * @param for_restart Whether this restoration is explicitly for the
797 : * first restoration of restart data
798 : */
799 14214 : virtual void postRestore(const bool /* for_restart */) {}
800 :
801 : /**
802 : * Restores from a "initial" backup, that is, one set in _initial_backup.
803 : *
804 : * @param for_restart Whether this restoration is explicitly for the first restoration of restart
805 : * data
806 : *
807 : * This is only used for restoration of multiapp subapps, which have been given
808 : * a Backup from their parent on initialization. Said Backup is passed to this app
809 : * via the "_initial_backup" private input parameter.
810 : *
811 : * See restore() for more information
812 : */
813 : void restoreFromInitialBackup(const bool for_restart);
814 :
815 : /**
816 : * Finalizes (closes) the restoration process done in restore().
817 : *
818 : * @return The underlying Backup that was used to do the restoration (if any, will be null when
819 : * backed up from file); can be ignored to destruct it
820 : *
821 : * This releases access to the stream in which the restore was loaded from
822 : * and makes it no longer possible to restore additional data.
823 : */
824 : std::unique_ptr<Backup> finalizeRestore();
825 :
826 : /**
827 : * Returns a string to be printed at the beginning of a simulation
828 : */
829 : virtual std::string header() const;
830 :
831 : /**
832 : * The MultiApp Level
833 : * @return The current number of levels from the master app
834 : */
835 5925048 : unsigned int multiAppLevel() const { return _multiapp_level; }
836 :
837 : /**
838 : * The MultiApp number
839 : * @return The numbering in all the sub-apps on the same level
840 : */
841 60069 : unsigned int multiAppNumber() const { return _multiapp_number; }
842 :
843 : /**
844 : * Whether or not this app is the ultimate master app. (ie level == 0)
845 : */
846 1173608 : bool isUltimateMaster() const { return !_multiapp_level; }
847 :
848 : /**
849 : * Returns whether to use the parent app mesh as the mesh for this app
850 : */
851 327352 : bool useMasterMesh() const { return _use_master_mesh; }
852 :
853 : /**
854 : * Returns a pointer to the master mesh
855 : */
856 981 : const MooseMesh * masterMesh() const { return _master_mesh; }
857 :
858 : /**
859 : * Returns a pointer to the master displaced mesh
860 : */
861 849 : const MooseMesh * masterDisplacedMesh() const { return _master_displaced_mesh; }
862 :
863 : /**
864 : * Gets the system that manages the MeshGenerators
865 : */
866 300146 : MeshGeneratorSystem & getMeshGeneratorSystem() { return _mesh_generator_system; }
867 :
868 : /**
869 : * Gets the system that manages the ChainControls
870 : */
871 365262 : ChainControlDataSystem & getChainControlDataSystem() { return _chain_control_system; }
872 :
873 : /**
874 : * Add a mesh generator that will act on the meshes in the system
875 : *
876 : * @param type The type of MeshGenerator
877 : * @param name The name of the MeshGenerator
878 : * @param params The params used to construct the MeshGenerator
879 : *
880 : * See MeshGeneratorSystem::addMeshGenerator()
881 : */
882 54263 : void addMeshGenerator(const std::string & type,
883 : const std::string & name,
884 : const InputParameters & params)
885 : {
886 54263 : _mesh_generator_system.addMeshGenerator(type, name, params);
887 54259 : }
888 :
889 : /**
890 : * @returns Whether or not a mesh generator exists with the name \p name.
891 : */
892 : bool hasMeshGenerator(const MeshGeneratorName & name) const
893 : {
894 : return _mesh_generator_system.hasMeshGenerator(name);
895 : }
896 :
897 : /**
898 : * @returns The MeshGenerator with the name \p name.
899 : */
900 231 : const MeshGenerator & getMeshGenerator(const std::string & name) const
901 : {
902 231 : return _mesh_generator_system.getMeshGenerator(name);
903 : }
904 :
905 : /**
906 : * @returns The final mesh generated by the mesh generator system
907 : */
908 : std::unique_ptr<MeshBase> getMeshGeneratorMesh()
909 : {
910 : return _mesh_generator_system.getSavedMesh(_mesh_generator_system.mainMeshGeneratorName());
911 : }
912 :
913 : /**
914 : * @returns The names of all mesh generators
915 : *
916 : * See MeshGeneratorSystem::getMeshGeneratorNames()
917 : */
918 106263 : std::vector<std::string> getMeshGeneratorNames() const
919 : {
920 106263 : return _mesh_generator_system.getMeshGeneratorNames();
921 : }
922 :
923 : /**
924 : * Append a mesh generator that will act on the final mesh generator in the system
925 : *
926 : * @param type The type of MeshGenerator
927 : * @param name The name of the MeshGenerator
928 : * @param params The params used to construct the MeshGenerator
929 : *
930 : * See MeshGeneratorSystem::appendMeshGenerator()
931 : */
932 : const MeshGenerator &
933 25 : appendMeshGenerator(const std::string & type, const std::string & name, InputParameters params)
934 : {
935 25 : return _mesh_generator_system.appendMeshGenerator(type, name, params);
936 : }
937 :
938 : /**
939 : * Whether this app is constructing mesh generators
940 : *
941 : * This is virtual to allow MooseUnitApp to override it so that we can
942 : * construct MeshGenerators in unit tests
943 : */
944 : virtual bool constructingMeshGenerators() const;
945 :
946 : ///@{
947 : /**
948 : * Sets the restart/recover flags
949 : * @param state The state to set the flag to
950 : */
951 : void setRestart(bool value);
952 : void setRecover(bool value);
953 : ///@}
954 :
955 : /// Returns whether the Application is running in check input mode
956 : bool checkInput() const { return _check_input; }
957 :
958 : /// Returns whether FPE trapping is turned on (either because of debug or user requested)
959 3929168 : bool getFPTrapFlag() const { return _trap_fpe; }
960 :
961 : /**
962 : * Returns a Boolean indicating whether a RelationshipManater exists with the same name.
963 : */
964 : bool hasRelationshipManager(const std::string & name) const;
965 :
966 : /**
967 : * Transfers ownership of a RelationshipManager to the application for lifetime management.
968 : * The RelationshipManager will NOT be duplicately added if an equivalent RelationshipManager
969 : * is already active. In that case, it's possible that the object will be destroyed if the
970 : * reference count drops to zero.
971 : */
972 : bool addRelationshipManager(std::shared_ptr<RelationshipManager> relationship_manager);
973 :
974 : /// The file suffix for the checkpoint mesh
975 : static const std::string & checkpointSuffix();
976 : /// The file suffix for meta data (header and data)
977 : static std::filesystem::path metaDataFolderBase(const std::filesystem::path & folder_base,
978 : const std::string & map_suffix);
979 : /// The file suffix for restartable data
980 : std::filesystem::path restartFolderBase(const std::filesystem::path & folder_base) const;
981 :
982 : /**
983 : * @return The hit node that is responsible for creating the current action that is running,
984 : * if any
985 : *
986 : * Can be used to link objects that are created by an action to the action that
987 : * created them in input
988 : */
989 : const hit::Node * getCurrentActionHitNode() const;
990 :
991 : /**
992 : * Attach the relationship managers of the given type
993 : * Note: Geometric relationship managers that are supposed to be attached late
994 : * will be attached when Algebraic are attached.
995 : */
996 : void attachRelationshipManagers(Moose::RelationshipManagerType rm_type,
997 : bool attach_geometric_rm_final = false);
998 :
999 : /**
1000 : * Attach geometric relationship managers to the given \p MeshBase object. This API is designed to
1001 : * work with \p MeshGenerators which are executed at the very beginning of a simulation. No
1002 : * attempt will be made to add relationship managers to a displaced mesh, because it doesn't exist
1003 : * yet.
1004 : */
1005 : void attachRelationshipManagers(MeshBase & mesh, MooseMesh & moose_mesh);
1006 :
1007 : /**
1008 : * Retrieve the relationship managers
1009 : */
1010 : const std::vector<std::shared_ptr<RelationshipManager>> & getReleationshipManagers();
1011 :
1012 : /**
1013 : * Returns the Relationship managers info suitable for printing.
1014 : */
1015 : std::vector<std::pair<std::string, std::string>> getRelationshipManagerInfo() const;
1016 :
1017 : /**
1018 : * Return the app level ExecFlagEnum, this contains all the available flags for the app.
1019 : */
1020 1060327 : const ExecFlagEnum & getExecuteOnEnum() const { return _execute_flags; }
1021 :
1022 : /**
1023 : * @return Whether or not this app currently has an "initial" backup
1024 : *
1025 : * See _initial_backup and restoreFromInitialBackup() for more info.
1026 : */
1027 4352 : bool hasInitialBackup() const
1028 : {
1029 4352 : return _initial_backup != nullptr && *_initial_backup != nullptr;
1030 : }
1031 :
1032 : /**
1033 : * Whether to enable automatic scaling by default
1034 : */
1035 61411 : bool defaultAutomaticScaling() const { return _automatic_automatic_scaling; }
1036 :
1037 : // Return the communicator for this application
1038 127 : const std::shared_ptr<libMesh::Parallel::Communicator> getCommunicator() const { return _comm; }
1039 :
1040 : /**
1041 : * Return the container of relationship managers
1042 : */
1043 51 : const std::set<std::shared_ptr<RelationshipManager>> & relationshipManagers() const
1044 : {
1045 51 : return _relationship_managers;
1046 : }
1047 :
1048 : /**
1049 : * Function to check the integrity of the restartable meta data structure
1050 : */
1051 : void checkMetaDataIntegrity() const;
1052 :
1053 : ///@{
1054 : /**
1055 : * Iterator based access to the extra RestartableDataMap objects; see Checkpoint.C for use case.
1056 : *
1057 : * These are MOOSE internal functions and should not be used otherwise.
1058 : */
1059 37 : auto getRestartableDataMapBegin() { return _restartable_meta_data.begin(); }
1060 :
1061 74 : auto getRestartableDataMapEnd() { return _restartable_meta_data.end(); }
1062 : ///@}
1063 :
1064 : /**
1065 : * Whether this application should by default error on Jacobian nonzero reallocations. The
1066 : * application level setting can always be overridden by setting the \p
1067 : * error_on_jacobian_nonzero_reallocation parameter in the \p Problem block of the input file
1068 : */
1069 162 : virtual bool errorOnJacobianNonzeroReallocation() const { return false; }
1070 :
1071 : /**
1072 : * Registers an interface object for accessing with getInterfaceObjects.
1073 : *
1074 : * This should be called within the constructor of the interface in interest.
1075 : */
1076 : template <class T>
1077 : void registerInterfaceObject(T & interface);
1078 :
1079 : /**
1080 : * Gets the registered interface objects for a given interface.
1081 : *
1082 : * For this to work, the interface must register itself using registerInterfaceObject.
1083 : */
1084 : template <class T>
1085 : const std::vector<T *> & getInterfaceObjects() const;
1086 :
1087 : static void addAppParam(InputParameters & params);
1088 : static void addInputParam(InputParameters & params);
1089 :
1090 : /**
1091 : * Whether or not we are forcefully restarting (allowing the load of potentially
1092 : * incompatibie checkpoints); used within RestartableDataReader
1093 : */
1094 70868 : bool forceRestart() const { return _force_restart; }
1095 :
1096 : /// Returns whether the flag for unused parameters is set to throw a warning only
1097 3363 : bool unusedFlagIsWarning() const { return _enable_unused_check == WARN_UNUSED; }
1098 :
1099 : /// Returns whether the flag for unused parameters is set to throw an error
1100 3353 : bool unusedFlagIsError() const { return _enable_unused_check == ERROR_UNUSED; }
1101 :
1102 : #ifdef MOOSE_MFEM_ENABLED
1103 : /**
1104 : * Create/configure the MFEM device with the provided \p device_string. More than one device can
1105 : * be configured. If supplying multiple devices, they should be comma separated
1106 : */
1107 : void setMFEMDevice(const std::string & device_string, Moose::PassKey<MFEMExecutioner>);
1108 :
1109 : /**
1110 : * Get the MFEM device object
1111 : */
1112 8271 : std::shared_ptr<mfem::Device> getMFEMDevice(Moose::PassKey<MultiApp>) { return _mfem_device; }
1113 :
1114 : /**
1115 : * Get the configured MFEM devices
1116 : */
1117 : const std::set<std::string> & getMFEMDevices(Moose::PassKey<MultiApp>) const;
1118 : #endif
1119 :
1120 : protected:
1121 : /**
1122 : * Helper method for dynamic loading of objects
1123 : */
1124 : void dynamicRegistration(const libMesh::Parameters & params);
1125 :
1126 : /**
1127 : * Recursively loads libraries and dependencies in the proper order to fully register a
1128 : * MOOSE application that may have several dependencies. REQUIRES: dynamic linking loader support.
1129 : */
1130 : void loadLibraryAndDependencies(const std::string & library_filename,
1131 : const libMesh::Parameters & params,
1132 : bool load_dependencies = true);
1133 :
1134 : /// Constructor is protected so that this object is constructed through the AppFactory object
1135 : MooseApp(const InputParameters & parameters);
1136 :
1137 : /**
1138 : * NOTE: This is an internal function meant for MOOSE use only!
1139 : *
1140 : * Register a piece of restartable data that will be used in a filter in/out during
1141 : * deserialization. Note however that this data will always be written to the restart file.
1142 : *
1143 : * @param name The full (unique) name.
1144 : * @param filter The filter name where to direct the name
1145 : */
1146 : void registerRestartableNameWithFilter(const std::string & name,
1147 : Moose::RESTARTABLE_FILTER filter);
1148 :
1149 : /**
1150 : * Runs post-initialization error checking that cannot be run correctly unless the simulation
1151 : * has been fully set up and initialized.
1152 : */
1153 : void errorCheck();
1154 :
1155 : /**
1156 : * Outputs machine readable data (JSON, YAML, etc.) either to the screen (if no filename was
1157 : * provided as an argument to the parameter param) or to a file (if a filename was provided).
1158 : */
1159 : void outputMachineReadableData(const std::string & param,
1160 : const std::string & start_marker,
1161 : const std::string & end_marker,
1162 : const std::string & data) const;
1163 : ///@{ register a new capability
1164 : static void addCapability(const std::string & capability,
1165 : CapabilityUtils::Type value,
1166 : const std::string & doc);
1167 : static void
1168 : addCapability(const std::string & capability, const char * value, const std::string & doc);
1169 : //@}
1170 :
1171 : /// Parameters of this object
1172 : const InputParameters & _pars;
1173 :
1174 : /// The string representation of the type of this object as registered (see registerApp(AppName))
1175 : const std::string _type;
1176 :
1177 : /// The MPI communicator this App is going to use
1178 : const std::shared_ptr<libMesh::Parallel::Communicator> _comm;
1179 :
1180 : /// The output file basename
1181 : std::string _output_file_base;
1182 :
1183 : /// Whether or not file base is set through input or setOutputFileBase by MultiApp
1184 : bool _file_base_set_by_user;
1185 :
1186 : /// Whether or not an output position has been set for this app
1187 : bool _output_position_set;
1188 :
1189 : /// The output position
1190 : Point _output_position;
1191 :
1192 : /// Whether or not an start time has been set
1193 : bool _start_time_set;
1194 :
1195 : /// The time at which to start the simulation
1196 : Real _start_time;
1197 :
1198 : /// Offset of the local App time to the "global" problem time
1199 : Real _global_time_offset;
1200 :
1201 : /// Command line object
1202 : std::shared_ptr<CommandLine> _command_line;
1203 :
1204 : /// Syntax of the input file
1205 : Syntax _syntax;
1206 :
1207 : /// Input parameter storage structure; unique_ptr so we can control
1208 : /// its destruction order
1209 : std::unique_ptr<InputParameterWarehouse> _input_parameter_warehouse;
1210 :
1211 : /// The Factory responsible for building Actions
1212 : ActionFactory _action_factory;
1213 :
1214 : /// Where built actions are stored
1215 : ActionWarehouse _action_warehouse;
1216 :
1217 : /// OutputWarehouse object for this App
1218 : OutputWarehouse _output_warehouse;
1219 :
1220 : /// Parser for parsing the input file
1221 : const std::shared_ptr<Parser> _parser;
1222 :
1223 : /// Builder for building app related parser tree
1224 : Moose::Builder _builder;
1225 :
1226 : /// Where the restartable data is held (indexed on tid)
1227 : std::vector<RestartableDataMap> _restartable_data;
1228 :
1229 : /**
1230 : * Data names that will only be read from the restart file during RECOVERY.
1231 : * e.g. these names are _excluded_ during restart.
1232 : */
1233 : DataNames _recoverable_data_names;
1234 :
1235 : /// The PerfGraph object for this application (recoverable)
1236 : PerfGraph & _perf_graph;
1237 :
1238 : /// The SolutionInvalidity object for this application
1239 : SolutionInvalidity & _solution_invalidity;
1240 :
1241 : /// The RankMap is a useful object for determining how the processes are laid out on the physical hardware
1242 : const RankMap _rank_map;
1243 :
1244 : /// Pointer to the executioner of this run (typically build by actions)
1245 : std::shared_ptr<Executioner> _executioner;
1246 :
1247 : /// Pointer to the Executor of this run
1248 : std::shared_ptr<Executor> _executor;
1249 :
1250 : /// Pointers to all of the Executors for this run
1251 : std::map<std::string, std::shared_ptr<Executor>> _executors;
1252 :
1253 : /// Used in building the Executors
1254 : /// Maps the name of the Executor block to the <type, params>
1255 : std::unordered_map<std::string, std::pair<std::string, std::unique_ptr<InputParameters>>>
1256 : _executor_params;
1257 :
1258 : /// Multiapp-related fixed point algorithm configuration details
1259 : /// primarily intended to be passed to and used by the executioner/executor system.
1260 : FixedPointConfig _fixed_point_config;
1261 :
1262 : /// Indicates whether we are operating in the new/experimental executor mode
1263 : /// instead of using the legacy executioner system.
1264 : const bool _use_executor;
1265 :
1266 : /// Used to return an executor that does nothing
1267 : std::shared_ptr<NullExecutor> _null_executor;
1268 :
1269 : /// Boolean to indicate whether to use a Nonlinear or EigenSystem (inspected by actions)
1270 : bool _use_nonlinear;
1271 :
1272 : /// Boolean to indicate whether to use an eigenvalue executioner
1273 : bool _use_eigen_value;
1274 :
1275 : /// System Information
1276 : std::unique_ptr<SystemInfo> _sys_info;
1277 :
1278 : /// Indicates whether warnings, errors, or no output is displayed when unused parameters are detected
1279 : enum UNUSED_CHECK
1280 : {
1281 : OFF,
1282 : WARN_UNUSED,
1283 : ERROR_UNUSED
1284 : } _enable_unused_check;
1285 :
1286 : Factory _factory;
1287 :
1288 : /// Indicates whether warnings or errors are displayed when overridden parameters are detected
1289 : bool _error_overridden;
1290 : /// Indicates if simulation is ready to exit, and keeps track of which param caused it to exit
1291 : std::string _early_exit_param;
1292 : bool _ready_to_exit;
1293 : /// The exit code
1294 : int _exit_code;
1295 :
1296 : /// This variable indicates when a request has been made to restart from an Exodus file
1297 : bool _initial_from_file;
1298 :
1299 : /// The Exodus reader when _initial_from_file is set to true
1300 : std::shared_ptr<libMesh::ExodusII_IO> _ex_reader;
1301 :
1302 : /// This variable indicates that DistributedMesh should be used for the libMesh mesh underlying MooseMesh.
1303 : bool _distributed_mesh_on_command_line;
1304 :
1305 : /// Whether or not this is a recovery run
1306 : bool _recover;
1307 :
1308 : /// Whether or not this is a restart run
1309 : bool _restart;
1310 :
1311 : /// Whether or not we are performing a split mesh operation (--split-mesh)
1312 : bool _split_mesh;
1313 :
1314 : /// Whether or not we are using a (pre-)split mesh (automatically DistributedMesh)
1315 : const bool _use_split;
1316 :
1317 : /// Whether or not we are forcefully attempting to load checkpoints (--force-restart)
1318 : const bool _force_restart;
1319 :
1320 : /// Whether or not FPE trapping should be turned on.
1321 : bool _trap_fpe;
1322 :
1323 : /// The base name to restart/recover from. If blank then we will find the newest checkpoint file.
1324 : std::string _restart_recover_base;
1325 :
1326 : /// Whether or not this simulation should only run half its transient (useful for testing recovery)
1327 : const bool _test_checkpoint_half_transient;
1328 : /// Whether or not this simulation should fail its middle timestep and repeat (for testing)
1329 : const bool _test_restep;
1330 :
1331 : /// Map of outputer name and file number (used by MultiApps to propagate file numbers down through the multiapps)
1332 : std::map<std::string, unsigned int> _output_file_numbers;
1333 :
1334 : /// true if we want to just check the input file
1335 : bool _check_input;
1336 :
1337 : /// The relationship managers that have been added
1338 : std::set<std::shared_ptr<RelationshipManager>> _relationship_managers;
1339 :
1340 : /// The relationship managers that have been attached (type -> RMs)
1341 : std::map<Moose::RelationshipManagerType, std::set<const RelationshipManager *>>
1342 : _attached_relationship_managers;
1343 :
1344 : /// A map from undisplaced relationship managers to their displaced clone (stored as the base
1345 : /// GhostingFunctor). Anytime we clone in attachRelationshipManagers we create a map entry from
1346 : /// the cloned undisplaced relationship manager to its displaced clone counterpart. We leverage
1347 : /// this map when removing relationship managers/ghosting functors
1348 : std::unordered_map<RelationshipManager *, std::shared_ptr<libMesh::GhostingFunctor>>
1349 : _undisp_to_disp_rms;
1350 :
1351 : struct DynamicLibraryInfo
1352 : {
1353 : void * library_handle;
1354 : std::string full_path;
1355 : std::unordered_set<std::string> entry_symbols;
1356 : };
1357 :
1358 : /// The library archive (name only), registration method and the handle to the method
1359 : std::unordered_map<std::string, DynamicLibraryInfo> _lib_handles;
1360 :
1361 : private:
1362 : /**
1363 : * Internal function used to recursively create the executor objects.
1364 : *
1365 : * Called by createExecutors
1366 : *
1367 : * @param current_executor_name The name of the executor currently needing to be built
1368 : * @param possible_roots The names of executors that are currently candidates for being the root
1369 : */
1370 : void recursivelyCreateExecutors(const std::string & current_executor_name,
1371 : std::list<std::string> & possible_roots,
1372 : std::list<std::string> & current_branch);
1373 :
1374 : /**
1375 : * Register all base MooseApp capabilities to the Moose::Capabilities registry.
1376 : * Apps and Modules may register additional capabilities in their registerAll
1377 : * function.
1378 : */
1379 : void registerCapabilities();
1380 :
1381 : /**
1382 : * Purge this relationship manager from meshes and DofMaps and finally from us. This method is
1383 : * private because only this object knows when we should remove relationship managers: when we are
1384 : * adding relationship managers to this object's storage, we perform an operator>= comparison
1385 : * between our existing RMs and the RM we are trying to add. If any comparison returns true, we do
1386 : * not add the new RM because the comparison indicates that we would gain no new coverage.
1387 : * However, if no comparison return true, then we add the new RM and we turn the comparison
1388 : * around! Consequently if our new RM is >= than any of our preexisting RMs, we remove those
1389 : * preexisting RMs using this method
1390 : */
1391 : void removeRelationshipManager(std::shared_ptr<RelationshipManager> relationship_manager);
1392 :
1393 : #ifdef MOOSE_LIBTORCH_ENABLED
1394 : /**
1395 : * Function to determine the device which should be used by libtorch on this
1396 : * application. We use this function to decide what is available on different
1397 : * builds.
1398 : * @param device Enum to describe if a cpu or a gpu should be used.
1399 : */
1400 : torch::DeviceType determineLibtorchDeviceType(const MooseEnum & device) const;
1401 : #endif
1402 :
1403 : ///@{
1404 : /// Structs that are used in the _interface_registry
1405 : struct InterfaceRegistryObjectsBase
1406 : {
1407 225049 : virtual ~InterfaceRegistryObjectsBase() {}
1408 : };
1409 :
1410 : template <class T>
1411 : struct InterfaceRegistryObjects : public InterfaceRegistryObjectsBase
1412 : {
1413 : std::vector<T *> _objects;
1414 : };
1415 : ///@}
1416 :
1417 : /** Method for creating the minimum required actions for an application (no input file)
1418 : *
1419 : * Mimics the following input file:
1420 : *
1421 : * [Mesh]
1422 : * type = GeneratedMesh
1423 : * dim = 1
1424 : * nx = 1
1425 : * []
1426 : *
1427 : * [Executioner]
1428 : * type = Transient
1429 : * num_steps = 1
1430 : * dt = 1
1431 : * []
1432 : *
1433 : * [Problem]
1434 : * solve = false
1435 : * []
1436 : *
1437 : * [Outputs]
1438 : * console = false
1439 : * []
1440 : */
1441 : void createMinimalApp();
1442 :
1443 : /**
1444 : * Set a flag so that the parser will either warn or error when unused variables are seen after
1445 : * parsing is complete.
1446 : */
1447 : void setCheckUnusedFlag(bool warn_is_error = false);
1448 :
1449 : /**
1450 : * @return whether we have created any clones for the provided template relationship manager and
1451 : * mesh yet. This may be false for instance when we are in the initial add relationship manager
1452 : * stage and haven't attempted attaching any relationship managers to the mesh or dof map yet
1453 : * (which is when we generate the clones). It's also maybe possible that we've created a clone of
1454 : * a given \p template_rm but not for the provided mesh so we return false in that case as well
1455 : */
1456 : bool hasRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const;
1457 :
1458 : /**
1459 : * Return the relationship manager clone originally created from the provided template
1460 : * relationship manager and mesh
1461 : */
1462 : RelationshipManager & getRMClone(const RelationshipManager & template_rm,
1463 : const MeshBase & mesh) const;
1464 :
1465 : /**
1466 : * Take an input relationship manager, clone it, and then initialize it with provided mesh and
1467 : * optional \p dof_map
1468 : * @param template_rm The relationship manager template from which we will clone
1469 : * @param moose_mesh The moose mesh to use for initialization
1470 : * @param mesh The mesh to use for initialization
1471 : * @param dof_map An optional parameter that, if provided, will be used to help init the cloned
1472 : * relationship manager
1473 : * @return a reference to the cloned and initialized relationship manager
1474 : */
1475 : RelationshipManager & createRMFromTemplateAndInit(const RelationshipManager & template_rm,
1476 : MooseMesh & moose_mesh,
1477 : MeshBase & mesh,
1478 : const libMesh::DofMap * dof_map = nullptr);
1479 :
1480 : /**
1481 : * Creates a recoverable PerfGraph.
1482 : *
1483 : * This is a separate method so that it can be used in the constructor (multiple calls
1484 : * are required to declare it).
1485 : */
1486 : PerfGraph & createRecoverablePerfGraph();
1487 :
1488 : /**
1489 : * Creates a recoverable SolutionInvalidity.
1490 : *
1491 : * This is a separate method so that it can be used in the constructor (multiple calls
1492 : * are required to declare it).
1493 : */
1494 : SolutionInvalidity & createRecoverableSolutionInvalidity();
1495 :
1496 : /**
1497 : * Prints a message showing the installable inputs for a given application (if
1498 : * getInstallableInputs has been overridden for an application).
1499 : */
1500 : bool showInputs() const;
1501 :
1502 : /**
1503 : * Method to retrieve the installable inputs from a given applications <app>Revision.h file.
1504 : */
1505 : virtual std::string getInstallableInputs() const;
1506 :
1507 : /**
1508 : * Handles the copy_inputs input parameter logic: Checks to see whether the passed argument is
1509 : * valid (a readable installed directory) and recursively copies those files into a
1510 : * read/writable location for the user.
1511 : * @return a Boolean value used to indicate whether the application should exit early
1512 : */
1513 : bool copyInputs();
1514 :
1515 : /**
1516 : * Handles the run input parameter logic: Checks to see whether a directory exists in user space
1517 : * and launches the TestHarness to process the given directory.
1518 : * @return a Boolean value used to indicate whether the application should exit early
1519 : */
1520 : bool runInputs();
1521 :
1522 : /**
1523 : * Helper that reports an error if the given capability is reserved and
1524 : * should not be added via addCapability().
1525 : */
1526 : static void checkReservedCapability(const std::string & capability);
1527 :
1528 : /// General storage for custom RestartableData that can be added to from outside applications
1529 : std::unordered_map<RestartableDataMapName, std::pair<RestartableDataMap, std::string>>
1530 : _restartable_meta_data;
1531 :
1532 : /// Enumeration for holding the valid types of dynamic registrations allowed
1533 : enum RegistrationType
1534 : {
1535 : APPLICATION,
1536 : REGALL
1537 : };
1538 :
1539 : /// The combined warehouse for storing any MooseObject based object
1540 : std::unique_ptr<TheWarehouse> _the_warehouse;
1541 :
1542 : /// Level of multiapp, the master is level 0. This used by the Console to indent output
1543 : unsigned int _multiapp_level;
1544 :
1545 : /// Numbering in all the sub-apps on the same level
1546 : unsigned int _multiapp_number;
1547 :
1548 : /// Whether to use the parent app mesh for this app
1549 : const bool _use_master_mesh;
1550 :
1551 : /// The mesh from master app
1552 : const MooseMesh * const _master_mesh;
1553 :
1554 : /// The displaced mesh from master app
1555 : const MooseMesh * const _master_displaced_mesh;
1556 :
1557 : /// The system that manages the MeshGenerators
1558 : MeshGeneratorSystem _mesh_generator_system;
1559 :
1560 : /// The system that manages the ChainControls
1561 : ChainControlDataSystem _chain_control_system;
1562 :
1563 : RestartableDataReader _rd_reader;
1564 :
1565 : /**
1566 : * Execution flags for this App. Note: These are copied on purpose instead of maintaining a
1567 : * reference to the ExecFlagRegistry registry. In the Multiapp case, the registry may be
1568 : * augmented, changing the flags "known" to the application in the middle of executing the setup.
1569 : * This causes issues with the application having to process flags that aren't specifically
1570 : * registered.
1571 : */
1572 : const ExecFlagEnum _execute_flags;
1573 :
1574 : /// Cache output buffer so the language server can turn it off then back on
1575 : std::streambuf * _output_buffer_cache;
1576 :
1577 : /// Whether to turn on automatic scaling by default
1578 : const bool _automatic_automatic_scaling;
1579 :
1580 : /// CPU profiling
1581 : bool _cpu_profiling = false;
1582 :
1583 : /// Memory profiling
1584 : bool _heap_profiling = false;
1585 :
1586 : /// Map from a template relationship manager to a map in which the key-value pairs represent the \p
1587 : /// MeshBase object and the clone of the template relationship manager, e.g. the top-level map key
1588 : std::map<const RelationshipManager *,
1589 : std::map<const MeshBase *, std::unique_ptr<RelationshipManager>>>
1590 : _template_to_clones;
1591 :
1592 : /// Registration for interface objects
1593 : std::map<std::type_index, std::unique_ptr<InterfaceRegistryObjectsBase>> _interface_registry;
1594 :
1595 : /// The backup for use in initial setup; this will get set from the _initial_backup
1596 : /// input parameter that typically gets set from a MultiApp that has a backup
1597 : /// This is a pointer to a pointer because at the time of construction of the app,
1598 : /// the backup will not be filled yet.
1599 : std::unique_ptr<Backup> * const _initial_backup;
1600 :
1601 : #ifdef MOOSE_LIBTORCH_ENABLED
1602 : /// The libtorch device this app is using (converted from compute_device)
1603 : const torch::DeviceType _libtorch_device;
1604 : #endif
1605 :
1606 : #ifdef MOOSE_MFEM_ENABLED
1607 : /// The MFEM Device object
1608 : std::shared_ptr<mfem::Device> _mfem_device;
1609 :
1610 : /// MFEM supported devices based on user-provided config
1611 : std::set<std::string> _mfem_devices;
1612 : #endif
1613 :
1614 : // Allow FEProblemBase to set the recover/restart state, so make it a friend
1615 : friend class FEProblemBase;
1616 : friend class Restartable;
1617 : friend class SubProblem;
1618 : };
1619 :
1620 : template <typename T>
1621 : const T &
1622 3165943 : MooseApp::getParam(const std::string & name)
1623 : {
1624 3165943 : return InputParameters::getParamHelper(name, _pars, static_cast<T *>(0));
1625 : }
1626 :
1627 : template <typename T>
1628 : const T &
1629 122653 : MooseApp::getParam(const std::string & name) const
1630 : {
1631 122653 : return InputParameters::getParamHelper(name, _pars, static_cast<T *>(0), this);
1632 : }
1633 :
1634 : template <typename T>
1635 : const T &
1636 : MooseApp::getRenamedParam(const std::string & old_name, const std::string & new_name) const
1637 : {
1638 : // this enables having a default on the new parameter but bypassing it with the old one
1639 : // Most important: accept new parameter
1640 : if (isParamSetByUser(new_name) && !isParamValid(old_name))
1641 : return InputParameters::getParamHelper(new_name, _pars, static_cast<T *>(0), this);
1642 : // Second most: accept old parameter
1643 : else if (isParamValid(old_name) && !isParamSetByUser(new_name))
1644 : return InputParameters::getParamHelper(old_name, _pars, static_cast<T *>(0), this);
1645 : // Third most: accept default for new parameter
1646 : else if (isParamValid(new_name) && !isParamValid(old_name))
1647 : return InputParameters::getParamHelper(new_name, _pars, static_cast<T *>(0), this);
1648 : // Refuse: no default, no value passed
1649 : else if (!isParamValid(old_name) && !isParamValid(new_name))
1650 : mooseError(_pars.blockFullpath() + ": parameter '" + new_name +
1651 : "' is being retrieved without being set.\n"
1652 : "Did you mispell it?");
1653 : // Refuse: both old and new parameters set by user
1654 : else
1655 : mooseError(_pars.blockFullpath() + ": parameter '" + new_name +
1656 : "' may not be provided alongside former parameter '" + old_name + "'");
1657 : }
1658 :
1659 : template <class T>
1660 : void
1661 954532 : MooseApp::registerInterfaceObject(T & interface)
1662 : {
1663 : static_assert(!std::is_base_of<MooseObject, T>::value, "T is not an interface");
1664 :
1665 954532 : InterfaceRegistryObjects<T> * registry = nullptr;
1666 954532 : auto it = _interface_registry.find(typeid(T));
1667 954532 : if (it == _interface_registry.end())
1668 : {
1669 239063 : auto new_registry = std::make_unique<InterfaceRegistryObjects<T>>();
1670 239063 : registry = new_registry.get();
1671 239063 : _interface_registry.emplace(typeid(T), std::move(new_registry));
1672 239063 : }
1673 : else
1674 715469 : registry = static_cast<InterfaceRegistryObjects<T> *>(it->second.get());
1675 :
1676 : mooseAssert(std::count(registry->_objects.begin(), registry->_objects.end(), &interface) == 0,
1677 : "Interface already registered");
1678 954532 : registry->_objects.push_back(&interface);
1679 954532 : }
1680 :
1681 : template <class T>
1682 : const std::vector<T *> &
1683 4530720 : MooseApp::getInterfaceObjects() const
1684 : {
1685 : static_assert(!std::is_base_of<MooseObject, T>::value, "T is not an interface");
1686 :
1687 4530720 : const auto it = _interface_registry.find(typeid(T));
1688 4530720 : if (it != _interface_registry.end())
1689 4529139 : return static_cast<InterfaceRegistryObjects<T> *>(it->second.get())->_objects;
1690 1581 : const static std::vector<T *> empty;
1691 1581 : return empty;
1692 : }
1693 :
1694 : #ifdef MOOSE_MFEM_ENABLED
1695 : inline const std::set<std::string> &
1696 8271 : MooseApp::getMFEMDevices(Moose::PassKey<MultiApp>) const
1697 : {
1698 8271 : return _mfem_devices;
1699 : }
1700 : #endif
|