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