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