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