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