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