https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseApp.C
Go to the documentation of this file.
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#ifdef HAVE_GPERFTOOLS
11#include "gperftools/profiler.h"
12#include "gperftools/heap-profiler.h"
13#endif
14
15// MOOSE includes
16#include "MooseRevision.h"
17#include "AppFactory.h"
18#include "DisplacedProblem.h"
19#include "NonlinearSystemBase.h"
20#include "AuxiliarySystem.h"
21#include "MooseSyntax.h"
22#include "MooseInit.h"
23#include "Executioner.h"
24#include "Executor.h"
25#include "PetscSupport.h"
26#include "Conversion.h"
27#include "CommandLine.h"
28#include "InfixIterator.h"
29#include "MultiApp.h"
30#include "MooseUtils.h"
31#include "MooseObjectAction.h"
33#include "SystemInfo.h"
34#include "MooseMesh.h"
35#include "FileOutput.h"
36#include "ConsoleUtils.h"
37#include "JsonSyntaxTree.h"
39#include "RelationshipManager.h"
41#include "Registry.h"
42#include "SerializerGuard.h"
43#include "PerfGraphInterface.h" // For TIME_SECTION
45#include "Attributes.h"
46#include "MooseApp.h"
47#include "CommonOutputAction.h"
48#include "CastUniquePointer.h"
49#include "NullExecutor.h"
50#include "ExecFlagRegistry.h"
51#include "SolutionInvalidity.h"
52#include "MooseServer.h"
54#include "StringInputStream.h"
55#include "MooseMain.h"
56#include "FEProblemBase.h"
57#include "Parser.h"
58#include "CSGBase.h"
59#include "Capabilities.h"
60
61// Regular expression includes
62#include "pcrecpp.h"
63
64#include "libmesh/exodusII_io.h"
65#include "libmesh/mesh_refinement.h"
66#include "libmesh/string_to_enum.h"
67#include "libmesh/checkpoint_io.h"
68#include "libmesh/mesh_base.h"
69#include "libmesh/petsc_solver_exception.h"
70
71// System include for dynamic library methods
72#ifdef LIBMESH_HAVE_DLOPEN
73#include <dlfcn.h>
74#include <sys/utsname.h> // utsname
75#endif
76
77#if __has_include(<torch/xpu.h>)
78#include <torch/xpu.h>
79#define MOOSE_HAVE_XPU 1
80#endif
81
82// C++ includes
83#include <numeric> // std::accumulate
84#include <fstream>
85#include <iterator>
86#include <sys/types.h>
87#include <unistd.h>
88#include <cstdlib> // for system()
89#include <chrono>
90#include <thread>
91#include <filesystem>
92
93namespace
94{
109std::filesystem::path
110temporaryBackupMeshPath(const MooseApp & app, const std::string & purpose)
111{
112 return std::filesystem::path(app.getOutputFileBase() + "_" + purpose + "_mesh") / "mesh.cpr";
113}
114
115std::string
116readBackupMeshFile(const std::filesystem::path & path)
117{
118 std::ifstream file(path, std::ios::in | std::ios::binary);
119 if (!file.is_open())
120 mooseError("Unable to open temporary mesh backup file ",
121 std::filesystem::absolute(path),
122 " for reading");
123
124 return std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
125}
126
127void
128writeBackupMeshFile(const std::filesystem::path & path, const std::string & contents)
129{
130 std::error_code err;
131 if (!std::filesystem::create_directories(path.parent_path(), err) && err)
132 mooseError("Unable to create temporary mesh backup directory ",
133 std::filesystem::absolute(path.parent_path()),
134 ": ",
135 err.message());
136
137 std::ofstream file(path, std::ios::out | std::ios::binary);
138 if (!file.is_open())
139 mooseError("Unable to open temporary mesh backup file ",
140 std::filesystem::absolute(path),
141 " for writing");
142
143 file.write(contents.data(), contents.size());
144}
145
151void
152resetBackupMeshDir(const std::filesystem::path & mesh_path)
153{
154 std::error_code err;
155 std::filesystem::remove_all(mesh_path.parent_path(), err);
156
157 err.clear();
158 if (!std::filesystem::create_directories(mesh_path.parent_path(), err) && err)
159 mooseError("Unable to create temporary mesh backup directory ",
160 std::filesystem::absolute(mesh_path.parent_path()),
161 ": ",
162 err.message());
163}
164
165void
166packMeshBackup(const MooseApp & app, Backup & backup)
167{
168 backup.mesh_files.clear();
169
170 if (!app.getExecutioner())
171 return;
172
173 if (!app.meshChangedForBackup())
174 return;
175
176 const auto mesh_path = temporaryBackupMeshPath(app, "backup");
177
178 if (app.processor_id() == 0)
179 resetBackupMeshDir(mesh_path);
180
181 // Wait for rank 0 to (re)create the checkpoint directory before every rank collectively writes
182 // into it via CheckpointIO::write().
183 app.comm().barrier();
184
185 {
186 libMesh::CheckpointIO io(app.feProblem().mesh().getMesh(), false);
187 io.write(mesh_path.string());
188 }
189
190 // CheckpointIO::write() is collective; wait until all ranks have finished writing split files
191 // before each rank packs the checkpoint tree into its Backup.
192 app.comm().barrier();
193
194 for (const auto & entry : std::filesystem::recursive_directory_iterator(mesh_path))
195 if (entry.is_regular_file())
196 {
197 const auto relative_path =
198 std::filesystem::relative(entry.path(), mesh_path).generic_string();
199 backup.mesh_files.emplace_back(relative_path, readBackupMeshFile(entry.path()));
200 }
201
202 // Keep the checkpoint tree alive until all ranks have finished reading from it.
203 app.comm().barrier();
204
205 if (app.processor_id() == 0)
206 {
207 std::error_code err;
208 std::filesystem::remove_all(mesh_path.parent_path(), err);
209 }
210}
211
212bool
213restoreMeshBackup(const MooseApp & app, Backup & backup, MooseMesh & mesh)
214{
215 if (backup.mesh_files.empty())
216 return false;
217
218 const auto mesh_path = temporaryBackupMeshPath(app, "restore");
219 if (app.processor_id() == 0)
220 {
221 resetBackupMeshDir(mesh_path);
222 for (const auto & [relative_path, contents] : backup.mesh_files)
223 writeBackupMeshFile(mesh_path / relative_path, contents);
224 }
225
226 // Rank 0 recreates the checkpoint tree, then all ranks collectively read their pieces.
227 app.comm().barrier();
228
229 auto & mesh_base = mesh.getMesh();
230 mesh_base.clear();
231
232 {
233 libMesh::CheckpointIO io(mesh_base, false);
234 io.read(mesh_path.string());
235 }
236
237 // This checkpoint is used only to restore mesh topology. The restored equation-system data is
238 // loaded from the Backup stream after the mesh is prepared, so discard any DOF indices that
239 // CheckpointIO carried with the mesh and let the systems own the final numbering.
240 for (auto & node : mesh_base.node_ptr_range())
241 node->clear_dofs();
242 for (auto & elem : mesh_base.element_ptr_range())
243 elem->clear_dofs();
244
245 backup.mesh_files.clear();
246
247 // Keep the checkpoint tree alive until every rank has completed CheckpointIO::read().
248 app.comm().barrier();
249
250 if (app.processor_id() == 0)
251 {
252 std::error_code err;
253 std::filesystem::remove_all(mesh_path.parent_path(), err);
254 }
255
256 return true;
257}
258}
259
260void
262{
263 params.addCommandLineParam<std::string>(
264 "app_to_run", "--app <type>", "Specify the application type to run (case-sensitive)");
265}
266
267void
269{
270 params.addCommandLineParam<std::vector<std::string>>(
271 "input_file", "-i <input file(s)>", "Specify input file(s); multiple files are merged");
272}
273
276{
278
279 MooseApp::addAppParam(params);
281
282 params.addCommandLineParam<bool>("display_version", "-v --version", "Print application version");
283
284 params.addOptionalValuedCommandLineParam<std::string>(
285 "mesh_only",
286 "--mesh-only <optional path>",
287 "",
288 "Build and output the mesh only (Default: \"<input_file_name>_in.e\")");
289 params.addOptionalValuedCommandLineParam<std::string>(
290 "csg_only",
291 "--csg-only <optional path>",
292 "",
293 "Setup and output the input mesh in CSG format only (Default: "
294 "\"<input_file_name>_out_csg.json\")");
295 params.addCommandLineParam<bool>(
296 "show_actions",
297 "--show-actions",
298 "Shows the list of Actions as they execute, in order of execution");
299 params.setGlobalCommandLineParam("show_actions");
300 params.addCommandLineParam<bool>(
301 "show_input", "--show-input", "Shows the parsed input file before running the simulation");
302 params.setGlobalCommandLineParam("show_input");
303 params.addCommandLineParam<bool>(
304 "show_outputs", "--show-outputs", "Shows the output execution time information");
305 params.setGlobalCommandLineParam("show_outputs");
306 params.addCommandLineParam<bool>(
307 "show_controls", "--show-controls", "Shows the Control logic available and executed");
308 params.setGlobalCommandLineParam("show_controls");
309
310 params.addCommandLineParam<bool>(
311 "no_color", "--no-color", "Disable coloring of all Console outputs");
312 params.setGlobalCommandLineParam("no_color");
313
314 MooseEnum colors("auto on off", "on");
316 "color", "--color <auto,on,off=on>", colors, "Whether to use color in console output");
317 params.setGlobalCommandLineParam("color");
318
319 params.addCommandLineParam<bool>("help", "-h --help", "Displays CLI usage statement");
320 params.addCommandLineParam<bool>(
321 "minimal",
322 "--minimal",
323 "Ignore input file and build a minimal application with Transient executioner");
324
325 params.addCommandLineParam<bool>(
326 "language_server",
327 "--language-server",
328 "Starts a process to communicate with development tools using the language server protocol");
329
330 params.addCommandLineParam<bool>("dump", "--dump", "Shows a dump of available input file syntax");
331 params.addCommandLineParam<std::string>(
332 "dump_search",
333 "--dump-search <search>",
334 "Shows a dump of available input syntax matching a search");
335 params.addCommandLineParam<bool>("registry", "--registry", "Lists all known objects and actions");
336 params.addCommandLineParam<bool>(
337 "registry_hit", "--registry-hit", "Lists all known objects and actions in hit format");
338 params.addCommandLineParam<bool>(
339 "use_executor", "--executor", "Use the new Executor system instead of Executioners");
340
341 params.addCommandLineParam<bool>(
342 "show_type", "--show-type", "Return the name of the application object");
343 params.addCommandLineParam<bool>("yaml", "--yaml", "Dumps all input file syntax in YAML format");
344 params.addCommandLineParam<std::string>(
345 "yaml_search", "--yaml-search", "Dumps input file syntax matching a search in YAML format");
346 params.addCommandLineParam<bool>("json", "--json", "Dumps all input file syntax in JSON format");
347 params.addCommandLineParam<std::string>(
348 "json_search", "--json-search", "Dumps input file syntax matching a search in JSON format");
349 params.addCommandLineParam<bool>(
350 "syntax", "--syntax", "Dumps the associated Action syntax paths ONLY");
351 params.addCommandLineParam<bool>(
352 "show_docs", "--docs", "Print url/path to the documentation website");
353 params.addCommandLineParam<bool>(
354 "show_capabilities", "--show-capabilities", "Dumps the capability registry in JSON format.");
355 params.addCommandLineParam<std::string>(
356 "required_capabilities",
357 "--required-capabilities",
358 "A list of conditions that is checked against the registered capabilities (see "
359 "--show-capabilities). The executable will terminate early if the conditions are not met.");
360 params.addCommandLineParam<std::string>(
361 "testharness_capabilities",
362 "--testharness-capabilities",
363 "Path to JSON from the TestHarness that contains capabilities to be appended.");
364
365 params.addCommandLineParam<std::string>(
366 "check_capabilities",
367 "--check-capabilities",
368 "A list of conditions that is checked against the registered capabilities. Will exit based "
369 "on whether or not the capaiblities are fulfilled. Does not check dynamically loaded apps.");
370 params.addCommandLineParam<bool>("check_input",
371 "--check-input",
372 "Check the input file (i.e. requires -i <filename>) and quit");
373 params.setGlobalCommandLineParam("check_input");
374 params.addCommandLineParam<bool>(
375 "show_inputs",
376 "--show-copyable-inputs",
377 "Shows the directories able to be copied into a user-writable location");
378
379 params.addCommandLineParam<std::string>(
380 "copy_inputs",
381 "--copy-inputs <dir>",
382 "Copies installed inputs (e.g. tests, examples, etc.) to a directory <appname>_<dir>");
383 // TODO: Should this remain a bool? It can't be a regular argument because it contains
384 // values that have dashes in it, so it'll get treated as another arg
385 params.addOptionalValuedCommandLineParam<std::string>(
386 "run",
387 "--run <test harness args>",
388 "",
389 "Runs the inputs in the current directory copied to a "
390 "user-writable location by \"--copy-inputs\"");
391
392 params.addCommandLineParam<bool>(
393 "list_constructed_objects",
394 "--list-constructed-objects",
395 "List all moose object type names constructed by the master app factory");
396
397 params.addOptionalValuedCommandLineParam<std::string>(
398 "citations",
399 "--citations [file]",
400 "",
401 "List the papers (in BibTeX format) that should be cited for the framework, PETSc, and the "
402 "modules and objects used in this simulation; optionally write them to [file] instead of the "
403 "console");
404
405 params.addCommandLineParam<unsigned int>(
406 "n_threads",
407 "--n-threads=<n>",
408 "Sets the numbers of threads if Application/num_threads is not passed. Else, specifies the "
409 "maximum number of threads and sets the OpenMP number of threads");
410 // This probably shouldn't be global, but the implications of removing this are currently
411 // unknown and we need to manage it with libmesh better
412 params.setGlobalCommandLineParam("n_threads");
413
414 params.addCommandLineParam<bool>("allow_unused",
415 "-w --allow-unused",
416 "Warn about unused input file options instead of erroring");
417 params.setGlobalCommandLineParam("allow_unused");
418 params.addCommandLineParam<bool>(
419 "error_unused", "-e --error-unused", "Error when encountering unused input file options");
420 params.setGlobalCommandLineParam("error_unused");
421 params.addCommandLineParam<bool>(
422 "error_deprecated", "--error-deprecated", "Turn deprecated code messages into Errors");
423 params.setGlobalCommandLineParam("error_deprecated");
424
425 params.addCommandLineParam<bool>("distributed_mesh",
426 "--distributed-mesh",
427 "Forces the use of a distributed finite element mesh");
428 // Would prefer that this parameter isn't global, but we rely on it too much
429 // in tests to be able to go back on that decision now
430 params.setGlobalCommandLineParam("distributed_mesh");
431
432 params.addCommandLineParam<std::string>(
433 "split_mesh",
434 "--split-mesh <splits>",
435 "Comma-separated list of numbers of chunks to split the mesh into");
436
437 // TODO: remove the logic now that this is global
438 params.addCommandLineParam<std::string>(
439 "split_file", "--split-file <filename>", "Name of split mesh file(s) to write/read");
440
441 params.addCommandLineParam<bool>("use_split", "--use-split", "Use split distributed mesh files");
442
443 params.addCommandLineParam<unsigned int>(
444 "refinements", "-r <num refinements>", "Specify additional initial uniform mesh refinements");
445
446 params.addOptionalValuedCommandLineParam<std::string>(
447 "recover",
448 "--recover <optional file base>",
449 "",
450 "Continue the calculation. Without <file base>, the most recent recovery file will be used");
451 params.setGlobalCommandLineParam("recover");
452 params.addCommandLineParam<bool>(
453 "force_restart",
454 "--force-restart",
455 "Forcefully load checkpoints despite possible incompatibilities");
456 params.setGlobalCommandLineParam("force_restart");
457
458 params.addCommandLineParam<bool>("suppress_header",
459 "--suppress-header",
460 false,
461 "Disables the output of the application header.");
462 params.setGlobalCommandLineParam("suppress_header");
463
464 params.addCommandLineParam<bool>(
465 "test_checkpoint_half_transient",
466 "--test-checkpoint-half-transient",
467 "Run half of a transient with checkpoints enabled; used by the TestHarness");
468 params.setGlobalCommandLineParam("test_checkpoint_half_transient");
469
470 params.addCommandLineParam<bool>("test_restep",
471 "--test-restep",
472 "Test re-running the middle timestep; used by the TestHarness");
473
474 params.addCommandLineParam<bool>(
475 "trap_fpe",
476 "--trap-fpe",
477 "Enable floating point exception handling in critical sections of code"
478#ifdef DEBUG
479 " (automatic due to debug build)"
480#endif
481 );
482 params.setGlobalCommandLineParam("trap_fpe");
483
484 params.addCommandLineParam<bool>(
485 "no_trap_fpe",
486 "--no-trap-fpe",
487 "Disable floating point exception handling in critical sections of code"
488#ifndef DEBUG
489 " (unused due to non-debug build)"
490#endif
491 );
492
493 params.setGlobalCommandLineParam("no_trap_fpe");
494
495 params.addCommandLineParam<bool>(
496 "no_gdb_backtrace", "--no-gdb-backtrace", "Disables gdb backtraces.");
497 params.setGlobalCommandLineParam("no_gdb_backtrace");
498
499 params.addCommandLineParam<bool>("error", "--error", "Turn all warnings into errors");
500 params.setGlobalCommandLineParam("error");
501
502 params.addCommandLineParam<bool>("timing",
503 "-t --timing",
504 "Enable all performance logging for timing; disables screen "
505 "output of performance logs for all Console objects");
506 params.setGlobalCommandLineParam("timing");
507 params.addCommandLineParam<bool>(
508 "no_timing", "--no-timing", "Disabled performance logging; overrides -t or --timing");
509 params.setGlobalCommandLineParam("no_timing");
510
511 params.addCommandLineParam<bool>(
512 "allow_test_objects", "--allow-test-objects", "Register test objects and syntax");
513 params.setGlobalCommandLineParam("allow_test_objects");
514
515 // Options ignored by MOOSE but picked up by libMesh, these are here so that they are displayed in
516 // the application help
517 params.addCommandLineParam<bool>(
518 "keep_cout",
519 "--keep-cout",
520 "Keep standard output from all processors when running in parallel");
521 params.setGlobalCommandLineParam("keep_cout");
522 params.addCommandLineParam<bool>(
523 "redirect_stdout",
524 "--redirect-stdout",
525 "Keep standard output from all processors when running in parallel");
526 params.setGlobalCommandLineParam("redirect_stdout");
527
528 params.addCommandLineParam<std::string>(
529 "timpi_sync",
530 "--timpi-sync <type=nbx>",
531 "nbx",
532 "Changes the sync type used in spare parallel communitations within TIMPI");
533 params.setGlobalCommandLineParam("timpi_sync");
534
535 // Options for debugging
536 params.addCommandLineParam<std::string>("start_in_debugger",
537 "--start-in-debugger <debugger>",
538 "Start the application and attach a debugger; this will "
539 "launch xterm windows using <debugger>");
540
541 params.addCommandLineParam<unsigned int>(
542 "stop_for_debugger",
543 "--stop-for-debugger <seconds>",
544 "Pauses the application during startup for <seconds> to allow for connection of debuggers");
545
546 params.addCommandLineParam<bool>(
547 "perf_graph_live_all", "--perf-graph-live-all", "Forces printing of ALL progress messages");
548 params.setGlobalCommandLineParam("perf_graph_live_all");
549
550 params.addCommandLineParam<bool>(
551 "disable_perf_graph_live", "--disable-perf-graph-live", "Disables PerfGraph live printing");
552 params.setGlobalCommandLineParam("disable_perf_graph_live");
553
554 params.addParam<bool>(
555 "automatic_automatic_scaling", false, "Whether to turn on automatic scaling by default");
556
557 const MooseEnum compute_device_type("cpu cuda mps hip ceed-cpu ceed-cuda ceed-hip xpu", "cpu");
559 "compute_device",
560 "--compute-device",
561 compute_device_type,
562 "The device type we want to run accelerated (libtorch, MFEM) computations on.");
563
564#ifdef HAVE_GPERFTOOLS
565 params.addCommandLineParam<std::string>(
566 "gperf_profiler_on",
567 "--gperf-profiler-on <ranks>",
568 "To generate profiling report only on comma-separated list of MPI ranks");
569#endif
570
571 params.addCommandLineParam<bool>(
572 "show_data_params",
573 "--show-data-params",
574 false,
575 "Show found paths for all DataFileName parameters in the header");
576 params.addCommandLineParam<bool>("show_data_paths",
577 "--show-data-paths",
578 false,
579 "Show registered data paths for searching in the header");
580
581 params.addPrivateParam<std::shared_ptr<CommandLine>>("_command_line");
582 params.addPrivateParam<std::shared_ptr<Parallel::Communicator>>("_comm");
583 params.addPrivateParam<unsigned int>("_multiapp_level");
584 params.addPrivateParam<unsigned int>("_multiapp_number");
585 params.addPrivateParam<bool>("_use_master_mesh", false);
586 params.addPrivateParam<const MooseMesh *>("_master_mesh");
587 params.addPrivateParam<const MooseMesh *>("_master_displaced_mesh");
588 params.addPrivateParam<std::unique_ptr<Backup> *>("_initial_backup", nullptr);
589 params.addPrivateParam<std::shared_ptr<Parser>>("_parser");
590
591 params.addParam<bool>(
592 "use_legacy_material_output",
593 true,
594 "Set false to allow material properties to be output on INITIAL, not just TIMESTEP_END.");
595 params.addParam<bool>(
596 "use_legacy_initial_residual_evaluation_behavior",
597 true,
598 "The legacy behavior performs an often times redundant residual evaluation before the "
599 "solution modifying objects are executed prior to the initial (0th nonlinear iteration) "
600 "residual evaluation. The new behavior skips that redundant residual evaluation unless the "
601 "parameter Executioner/use_pre_SMO_residual is set to true.");
602
603 params.addParam<bool>(
605 false,
606 "Set true to enable data-driven mesh generation, which is an experimental feature");
607
608 params.addCommandLineParam<bool>(
609 "parse_neml2_only",
610 "--parse-neml2-only",
611 "Executes the [NEML2] block to parse the input file and terminate.");
612
613 MooseApp::addAppParam(params);
614
615 params.registerBase("Application");
616
617 return params;
618}
619
620std::optional<THREAD_ID>
622{
623 // Read straight from the parsed input tree: the [Application] block is not applied to the app's
624 // InputParameters, and this runs at construction, well before the create_application_block task.
625 const hit::Node * const root = _parser ? _parser->queryRoot() : nullptr;
626 if (!root)
627 return std::nullopt;
628 const hit::Node * const node = root->find("Application/num_threads");
629 if (!node || node->type() != hit::NodeType::Field)
630 return std::nullopt;
631 return node->param<THREAD_ID>();
632}
633
636{
637 const THREAD_ID max_threads = libMesh::n_threads();
638 // A per-application count can only cap down from the process-wide count (the thread pool is
639 // sized once at launch), and a request of zero (or less) is meaningless, so treat it as a single
640 // thread. An over-request is warned about later during setup, where the console is available.
641 return std::clamp(requestedNumThreads().value_or(max_threads), THREAD_ID(1), max_threads);
642}
643
645 : PerfGraphInterface(*this, "MooseApp"),
646 ParallelObject(*parameters.get<std::shared_ptr<Parallel::Communicator>>(
647 "_comm")), // Can't call getParam() before pars is set
648 // The use of AppFactory::getAppParams() is atrocious. However, a long time ago
649 // we decided to copy construct parameters in each derived application...
650 // which means that the "parameters" we get if someone derives from MooseApp are
651 // actually a copy of the ones built by the factory. Because we have unique
652 // application names, this allows us to reference (using _pars and MooseBase)
653 // the actual const parameters that the AppFactory made for this application
654 MooseBase(*this, AppFactory::instance().getAppParams(parameters)),
655 _comm(getParam<std::shared_ptr<Parallel::Communicator>>("_comm")),
656 _file_base_set_by_user(false),
657 _output_position_set(false),
658 _start_time_set(false),
659 _start_time(0.0),
660 _global_time_offset(0.0),
661 // Sized to the process-wide thread count (not the app cap): this is constructed before _parser,
662 // so the [Application] num_threads is not yet available, and app-level per-thread storage is
663 // always safe at the larger size.
664 _input_parameter_warehouse(std::make_unique<InputParameterWarehouse>(libMesh::n_threads())),
665 _action_factory(*this),
666 _action_warehouse(*this, _syntax, _action_factory),
667 _output_warehouse(*this),
668 _parser(getCheckedPointerParam<std::shared_ptr<Parser>>("_parser")),
669 _command_line(getCheckedPointerParam<std::shared_ptr<CommandLine>>("_command_line")),
670 _builder(*this, _action_warehouse, *_parser),
671 _num_threads(determineNumThreads()),
672 _restartable_data(_num_threads),
673 _perf_graph(createRecoverablePerfGraph()),
674 _solution_invalidity(createRecoverableSolutionInvalidity()),
675 _rank_map(*_comm, _perf_graph),
676 _use_executor(getParam<bool>("use_executor")),
677 _null_executor(NULL),
678 _use_nonlinear(true),
679 _use_eigen_value(false),
680 _enable_unused_check(ERROR_UNUSED),
681 _factory(*this),
682 _error_overridden(false),
683 _early_exit_param(""),
684 _ready_to_exit(false),
685 _exit_code(0),
686 _initial_from_file(false),
687 _distributed_mesh_on_command_line(getParam<bool>("distributed_mesh")),
688 _recover(false),
689 _restart(false),
690 _split_mesh(false),
691 _use_split(getParam<bool>("use_split")),
692 _force_restart(getParam<bool>("force_restart")),
693#ifdef DEBUG
694 _trap_fpe(true),
695#else
696 _trap_fpe(false),
697#endif
698 _test_checkpoint_half_transient(parameters.get<bool>("test_checkpoint_half_transient")),
699 _test_restep(parameters.get<bool>("test_restep")),
700 _check_input(getParam<bool>("check_input")),
701 _multiapp_level(isParamValid("_multiapp_level") ? getParam<unsigned int>("_multiapp_level")
702 : 0),
703 _multiapp_number(isParamValid("_multiapp_number") ? getParam<unsigned int>("_multiapp_number")
704 : 0),
705 _use_master_mesh(getParam<bool>("_use_master_mesh")),
706 _master_mesh(isParamValid("_master_mesh") ? getParam<const MooseMesh *>("_master_mesh")
707 : nullptr),
708 _master_displaced_mesh(isParamValid("_master_displaced_mesh")
709 ? getParam<const MooseMesh *>("_master_displaced_mesh")
710 : nullptr),
711 _mesh_generator_system(*this),
712 _chain_control_system(*this),
713 _rd_reader(*this, _restartable_data, forceRestart()),
714 _execute_flags(moose::internal::ExecFlagRegistry::getExecFlagRegistry().getFlags()),
715 _output_buffer_cache(nullptr),
716 _automatic_automatic_scaling(getParam<bool>("automatic_automatic_scaling")),
717 _initial_backup(getParam<std::unique_ptr<Backup> *>("_initial_backup"))
718#ifdef MOOSE_LIBTORCH_ENABLED
719 ,
720 _libtorch_device(determineLibtorchDeviceType(getParam<MooseEnum>("compute_device")))
721#endif
722{
723 if (&parameters != &_pars)
724 {
725 const std::string bad_params = "(InputParameters parameters)";
726 const std::string good_params = "(const InputParameters & parameters)";
727 const std::string source_constructor = type() + "::" + type();
728 mooseDoOnce(
730 " copy-constructs its input parameters.\n\n",
731 "This is deprecated and will not be allowed in the future.\n\n",
732 "In ",
733 type(),
734 ".C, change:\n ",
735 source_constructor,
736 bad_params,
737 " -> ",
738 source_constructor,
739 good_params,
740 "\n\n",
741 "In ",
742 type(),
743 ".h, change:\n ",
744 type(),
745 bad_params,
746 "; -> ",
747 type(),
748 good_params,
749 ";"));
750 }
751
752 mooseAssert(_command_line->hasParsed(), "Command line has not parsed");
753 mooseAssert(_parser->queryRoot(), "Parser has not parsed");
754
755 // Set the TIMPI sync type via --timpi-sync
756 const auto & timpi_sync = getParam<std::string>("timpi_sync");
757 const_cast<Parallel::Communicator &>(comm()).sync_type(timpi_sync);
758
759#ifdef HAVE_GPERFTOOLS
760 if (isUltimateMaster())
761 {
762 bool has_cpu_profiling = false;
763 bool has_heap_profiling = false;
764 static std::string cpu_profile_file;
765 static std::string heap_profile_file;
766
767 // For CPU profiling, users need to have environment 'MOOSE_PROFILE_BASE'
768 if (std::getenv("MOOSE_PROFILE_BASE"))
769 {
770 has_cpu_profiling = true;
771 cpu_profile_file =
772 std::getenv("MOOSE_PROFILE_BASE") + std::to_string(_comm->rank()) + ".prof";
773 // create directory if needed
774 auto name = MooseUtils::splitFileName(cpu_profile_file);
775 if (!name.first.empty())
776 {
777 if (processor_id() == 0)
778 MooseUtils::makedirs(name.first.c_str());
779 _comm->barrier();
780 }
781 }
782
783 // For Heap profiling, users need to have 'MOOSE_HEAP_BASE'
784 if (std::getenv("MOOSE_HEAP_BASE"))
785 {
786 has_heap_profiling = true;
787 heap_profile_file = std::getenv("MOOSE_HEAP_BASE") + std::to_string(_comm->rank());
788 // create directory if needed
789 auto name = MooseUtils::splitFileName(heap_profile_file);
790 if (!name.first.empty())
791 {
792 if (processor_id() == 0)
793 MooseUtils::makedirs(name.first.c_str());
794 _comm->barrier();
795 }
796 }
797
798 // turn on profiling only on selected ranks
799 if (isParamSetByUser("gperf_profiler_on"))
800 {
801 auto rankstr = getParam<std::string>("gperf_profiler_on");
802 std::vector<processor_id_type> ranks;
803 bool success = MooseUtils::tokenizeAndConvert(rankstr, ranks, ", ");
804 if (!success)
805 mooseError("Invalid argument for --gperf-profiler-on: '", rankstr, "'");
806 for (auto & rank : ranks)
807 {
808 if (rank >= _comm->size())
809 mooseError("Invalid argument for --gperf-profiler-on: ",
810 rank,
811 " is greater than or equal to ",
812 _comm->size());
813 if (rank == _comm->rank())
814 {
815 _cpu_profiling = has_cpu_profiling;
816 _heap_profiling = has_heap_profiling;
817 }
818 }
819 }
820 else
821 {
822 _cpu_profiling = has_cpu_profiling;
823 _heap_profiling = has_heap_profiling;
824 }
825
826 if (_cpu_profiling)
827 if (!ProfilerStart(cpu_profile_file.c_str()))
828 mooseError("CPU profiler is not started properly");
829
830 if (_heap_profiling)
831 {
832 HeapProfilerStart(heap_profile_file.c_str());
833 if (!IsHeapProfilerRunning())
834 mooseError("Heap profiler is not started properly");
835 }
836 }
837#else
838 if (std::getenv("MOOSE_PROFILE_BASE") || std::getenv("MOOSE_HEAP_BASE"))
839 mooseError("gperftool is not available for CPU or heap profiling");
840#endif
841
842 // If this will be a language server then turn off output until that starts
843 if (isParamValid("language_server") && getParam<bool>("language_server"))
844 _output_buffer_cache = Moose::out.rdbuf(nullptr);
845
848
849 _the_warehouse = std::make_unique<TheWarehouse>();
850 _the_warehouse->registerAttribute<AttribMatrixTags>("matrix_tags", 0);
851 _the_warehouse->registerAttribute<AttribVectorTags>("vector_tags", 0);
852 _the_warehouse->registerAttribute<AttribExecOns>("exec_ons", 0);
853 _the_warehouse->registerAttribute<AttribSubdomains>("subdomains", 0);
854 _the_warehouse->registerAttribute<AttribBoundaries>("boundaries", 0);
855 _the_warehouse->registerAttribute<AttribThread>("thread", 0);
856 _the_warehouse->registerAttribute<AttribExecutionOrderGroup>("execution_order_group", 0);
857 _the_warehouse->registerAttribute<AttribPreIC>("pre_ic", 0);
858 _the_warehouse->registerAttribute<AttribPreAux>("pre_aux");
859 _the_warehouse->registerAttribute<AttribPostAux>("post_aux");
860 _the_warehouse->registerAttribute<AttribName>("name", "dummy");
861 _the_warehouse->registerAttribute<AttribSystem>("system", "dummy");
862 _the_warehouse->registerAttribute<AttribKokkos>("kokkos", false);
863 _the_warehouse->registerAttribute<AttribVar>("variable", -1);
864 _the_warehouse->registerAttribute<AttribInterfaces>("interfaces", 0);
865 _the_warehouse->registerAttribute<AttribSysNum>("sys_num", libMesh::invalid_uint);
866 _the_warehouse->registerAttribute<AttribResidualObject>("residual_object");
867 _the_warehouse->registerAttribute<AttribSorted>("sorted");
868 _the_warehouse->registerAttribute<AttribDisplaced>("displaced", -1);
869
871
872 if (_check_input && isParamSetByUser("recover"))
873 mooseError("Cannot run --check-input with --recover. Recover files might not exist");
874
875 if (isParamSetByUser("start_in_debugger") && isUltimateMaster())
876 {
877 auto command = getParam<std::string>("start_in_debugger");
878
879 Moose::out << "Starting in debugger using: " << command << std::endl;
880
881 auto hostname = MooseUtils::hostname();
882
883 std::stringstream command_stream;
884
885 // This will start XTerm and print out some info first... then run the debugger
886 command_stream << "xterm -e \"echo 'Rank: " << processor_id() << " Hostname: " << hostname
887 << " PID: " << getpid() << "'; echo ''; ";
888
889 // Figure out how to run the debugger
890 if (command.find("lldb") != std::string::npos || command.find("gdb") != std::string::npos)
891 command_stream << command << " -p " << getpid();
892 else
893 mooseError("Unknown debugger: ",
894 command,
895 "\nIf this is truly what you meant then contact moose-users to have a discussion "
896 "about adding your debugger.");
897
898 // Finish up the command
899 command_stream << "\"" << " & ";
900 std::string command_string = command_stream.str();
901 Moose::out << "Running: " << command_string << std::endl;
902
903 int ret = std::system(command_string.c_str());
904 libmesh_ignore(ret);
905
906 // Sleep to allow time for the debugger to attach
907 std::this_thread::sleep_for(std::chrono::seconds(10));
908 }
909
910 if (isParamSetByUser("stop_for_debugger") && isUltimateMaster())
911 {
912 Moose::out << "\nStopping for " << getParam<unsigned int>("stop_for_debugger")
913 << " seconds to allow attachment from a debugger.\n";
914
915 Moose::out << "\nAll of the processes you can connect to:\n";
916 Moose::out << "rank - hostname - pid\n";
917
918 auto hostname = MooseUtils::hostname();
919
920 {
921 // The 'false' turns off the serialization warning
922 SerializerGuard sg(_communicator, false); // Guarantees that the processors print in order
923 Moose::err << processor_id() << " - " << hostname << " - " << getpid() << "\n";
924 }
925
926 Moose::out << "\nWaiting...\n" << std::endl;
927
928 // Sleep to allow time for the debugger to attach
929 std::this_thread::sleep_for(std::chrono::seconds(getParam<unsigned int>("stop_for_debugger")));
930 }
931
932 if (isParamSetByUser("show_actions"))
934
936 mooseError("Mesh can be passed in only for sub-apps");
937
939 mooseError("_master_mesh should have been set when _master_displaced_mesh is set");
940
941 // Data specifically associated with the mesh (meta-data) that will read from the restart
942 // file early during the simulation setup so that they are available to Actions and other objects
943 // that need them during the setup process. Most of the restartable data isn't made available
944 // until all objects have been created and all Actions have been executed (i.e. initialSetup).
946
947 if (_pars.have_parameter<bool>("use_legacy_dirichlet_bc"))
948 mooseDeprecated("The parameter 'use_legacy_dirichlet_bc' is no longer valid.\n\n",
949 "All Dirichlet boundary conditions are preset by default.\n\n",
950 "Remove said parameter in ",
951 name(),
952 " to remove this deprecation warning.");
953
955 mooseError("Cannot use --test-restep and --test-checkpoint-half-transient together");
956
957 Moose::out << std::flush;
958
959#ifdef MOOSE_KOKKOS_ENABLED
960#ifdef MOOSE_ENABLE_KOKKOS_GPU
962#endif
963#endif
964}
965
967{
968#ifdef HAVE_GPERFTOOLS
969 // CPU profiling stop
970 if (_cpu_profiling)
971 ProfilerStop();
972 // Heap profiling stop
973 if (_heap_profiling)
974 HeapProfilerStop();
975#endif
977 _the_warehouse.reset();
978 _executioner.reset();
979
980 // Don't wait for implicit destruction of input parameter storage
982
983 // This is dirty, but I don't know what else to do. Obviously, others
984 // have had similar problems if you look above. In specific, the
985 // dlclose below on macs is destructing some data that does not
986 // belong to it in garbage collection. So... don't even give
987 // dlclose an option
988 _restartable_data.clear();
989
990 // Remove this app's parameters from the AppFactory. This allows
991 // for creating an app with this name again in the same execution,
992 // which needs to be done when resetting applications in MultiApp
994
995#ifdef LIBMESH_HAVE_DLOPEN
996 // Close any open dynamic libraries
997 for (const auto & lib_pair : _lib_handles)
998 dlclose(lib_pair.second.library_handle);
999#endif
1000
1001#ifdef MOOSE_KOKKOS_ENABLED
1003#endif
1004}
1005
1006std::string
1008{
1009 return MOOSE_VERSION;
1010}
1011
1012std::string
1014{
1015 return MOOSE_VERSION;
1016}
1017
1018std::string
1020{
1021 return getPrintableName() + " Version: " + getVersion();
1022}
1023
1024void
1026{
1027 TIME_SECTION("setupOptions", 5, "Setting Up Options");
1028
1029 // Print the header, this is as early as possible
1030 if (header().length() && !getParam<bool>("suppress_header"))
1031 _console << header() << std::endl;
1032
1033 if (getParam<bool>("error_unused"))
1034 setCheckUnusedFlag(true);
1035 else if (getParam<bool>("allow_unused"))
1036 setCheckUnusedFlag(false);
1037
1038 if (getParam<bool>("trap_fpe"))
1039 {
1040 _trap_fpe = true;
1041 _perf_graph.setActive(false);
1042 if (getParam<bool>("no_trap_fpe"))
1043 mooseError("Cannot use both \"--trap-fpe\" and \"--no-trap-fpe\" flags.");
1044 }
1045 else if (getParam<bool>("no_trap_fpe"))
1046 _trap_fpe = false;
1047
1048 // Turn all warnings in MOOSE to errors (almost see next logic block)
1049 Moose::_warnings_are_errors = getParam<bool>("error");
1050
1051 // Deprecated messages can be toggled to errors independently from everything else.
1052 Moose::_deprecated_is_error = getParam<bool>("error_deprecated");
1053
1054 if (isUltimateMaster()) // makes sure coloring isn't reset incorrectly in multi-app settings
1055 {
1056 // Set from command line
1057 auto color = getParam<MooseEnum>("color");
1058 if (!isParamSetByUser("color"))
1059 {
1060 // Set from deprecated --no-color
1061 if (getParam<bool>("no_color"))
1062 color = "off";
1063 // Set from environment
1064 else
1065 {
1066 char * c_color = std::getenv("MOOSE_COLOR");
1067 if (c_color)
1068 color.assign(std::string(c_color), "While assigning environment variable MOOSE_COLOR");
1069 }
1070 }
1071
1072 if (color == "auto")
1074 else if (color == "on")
1075 Moose::setColorConsole(true, true);
1076 else if (color == "off")
1078 else
1079 mooseAssert(false, "Should not hit");
1080
1081 // After setting color so that non-yellow deprecated is honored
1082 if (getParam<bool>("no_color"))
1083 mooseDeprecated("The --no-color flag is deprecated. Use '--color off' instead.");
1084 }
1085
1086// If there's no threading model active, but the user asked for
1087// --n-threads > 1 on the command line, throw a mooseError. This is
1088// intended to prevent situations where the user has potentially
1089// built MOOSE incorrectly (neither TBB nor pthreads found) and is
1090// asking for multiple threads, not knowing that there will never be
1091// any threads launched.
1092#if !LIBMESH_USING_THREADS
1093 if (libMesh::command_line_value("--n-threads", 1) > 1)
1094 mooseError("You specified --n-threads > 1, but there is no threading model active!");
1095#endif
1096
1097 // A per-application num_threads can only cap down from the process-wide --n-threads count; warn
1098 // (and cap, see determineNumThreads()) if the user asked for more than the process was launched
1099 // with.
1100 if (requestedNumThreads().value_or(0) > libMesh::n_threads())
1101 mooseWarning("[Application] num_threads=",
1103 " exceeds the process-wide thread count (--n-threads=",
1105 "); this application is capped to ",
1107 " threads.");
1108
1109 // Capability checking
1110 {
1111 // Augment capabilities from the TestHarness
1112 std::optional<std::set<std::string>> ignore_capabilities;
1113 if (isParamValid("testharness_capabilities"))
1114 {
1115 if (!isParamValid("required_capabilities"))
1116 mooseError(
1117 "--testharness-capabilities: Should not be specified without --required-capabilities");
1118
1119 const auto file_path = std::filesystem::absolute(
1120 std::filesystem::path(getParam<std::string>("testharness_capabilities")));
1121
1122 std::ifstream file(file_path);
1123 if (!file)
1124 mooseError("--testharness-capabilities: Could not open ", file_path);
1125
1126 nlohmann::json root;
1127 try
1128 {
1129 file >> root;
1130 if (const auto it = root.find("capabilities"); it != root.end())
1132 if (const auto it = root.find("ignore_capabilities"); it != root.end())
1133 ignore_capabilities = it->get<std::set<std::string>>();
1134 }
1135 catch (const std::exception & e)
1136 {
1137 mooseError(
1138 "--testharness-capabilities: Failed to load capabilities ", file_path, ":\n", e.what());
1139 }
1140 }
1141
1142 if (isParamValid("required_capabilities"))
1143 {
1145
1146 const auto & required_capabilities = getParam<std::string>("required_capabilities");
1147
1148 CapabilityRegistry::CheckOptions options;
1149 // Allowed to be unknown
1150 options.certain = false;
1151 // Add ignored capabilities, if any
1152 if (ignore_capabilities)
1153 options.ignore_capabilities = *ignore_capabilities;
1154
1155 CapabilityRegistry::CheckResult result;
1156 try
1157 {
1158 result = Moose::internal::Capabilities::getCapabilities({}).check(required_capabilities,
1159 options);
1160 }
1161 catch (const std::exception & e)
1162 {
1163 mooseError("--required-capablities: ", e.what());
1164 }
1165
1166 if (result.state < CapabilityRegistry::CheckState::UNKNOWN)
1167 {
1168 mooseInfo("Required capabilities '", required_capabilities, "' not fulfilled.");
1169 _ready_to_exit = true;
1170 // we use code 77 as "skip" in the Testharness
1171 _exit_code = 77;
1172 return;
1173 }
1174 if (result.state == CapabilityRegistry::CheckState::UNKNOWN)
1175 mooseError("Required capabilities '",
1176 required_capabilities,
1177 "' are not specific enough. A comparison test is performed on an undefined "
1178 "capability. Disambiguate this requirement by adding an existence/non-existence "
1179 "requirement. Example: 'unknown<1.2.3' should become 'unknown & unknown<1.2.3' "
1180 "or '!unknown | unknown<1.2.3'");
1181 }
1182 }
1183
1184 // Build a minimal running application, ignoring the input file.
1185 if (getParam<bool>("minimal"))
1187
1188 else if (getParam<bool>("display_version"))
1189 {
1190 Moose::out << getPrintableVersion() << std::endl;
1191 _early_exit_param = "--version";
1192 _ready_to_exit = true;
1193 return;
1194 }
1195 else if (getParam<bool>("help"))
1196 {
1197 _command_line->printUsage();
1198 _early_exit_param = "--help";
1199 _ready_to_exit = true;
1200 }
1201 else if (getParam<bool>("dump") || isParamSetByUser("dump_search"))
1202 {
1203 const std::string search =
1204 isParamSetByUser("dump_search") ? getParam<std::string>("dump_search") : "";
1205
1206 JsonSyntaxTree tree(search);
1207
1208 {
1209 TIME_SECTION("dump", 1, "Building Syntax Tree");
1211 }
1212
1213 // Check if second arg is valid or not
1214 if ((tree.getRoot()).is_object())
1215 {
1216 // Turn off live printing so that it doesn't mess with the dump
1218
1219 JsonInputFileFormatter formatter;
1220 Moose::out << "\n### START DUMP DATA ###\n"
1221 << formatter.toString(tree.getRoot()) << "\n### END DUMP DATA ###" << std::endl;
1222 _early_exit_param = "--dump";
1223 _ready_to_exit = true;
1224 }
1225 else
1226 mooseError("Search parameter '", search, "' was not found in the registered syntax.");
1227 }
1228 else if (getParam<bool>("registry"))
1229 {
1231
1232 Moose::out << "Label\tType\tName\tClass\tFile\n";
1233
1234 auto & objmap = Registry::allObjects();
1235 for (auto & entry : objmap)
1236 for (auto & obj : entry.second)
1237 Moose::out << entry.first << "\tobject\t" << obj->name() << "\t" << obj->_classname << "\t"
1238 << obj->_file << "\n";
1239
1240 auto & actmap = Registry::allActions();
1241 for (auto & entry : actmap)
1242 {
1243 for (auto & act : entry.second)
1244 Moose::out << entry.first << "\taction\t" << act->_name << "\t" << act->_classname << "\t"
1245 << act->_file << "\n";
1246 }
1247 _early_exit_param = "--registry";
1248 _ready_to_exit = true;
1249 }
1250 else if (getParam<bool>("registry_hit"))
1251 {
1253
1254 Moose::out << "### START REGISTRY DATA ###\n";
1255
1256 hit::Section root("");
1257 auto sec = new hit::Section("registry");
1258 root.addChild(sec);
1259 auto objsec = new hit::Section("objects");
1260 sec->addChild(objsec);
1261
1262 auto & objmap = Registry::allObjects();
1263 for (auto & entry : objmap)
1264 for (auto & obj : entry.second)
1265 {
1266 auto ent = new hit::Section("entry");
1267 objsec->addChild(ent);
1268 ent->addChild(new hit::Field("label", hit::Field::Kind::String, entry.first));
1269 ent->addChild(new hit::Field("type", hit::Field::Kind::String, "object"));
1270 ent->addChild(new hit::Field("name", hit::Field::Kind::String, obj->name()));
1271 ent->addChild(new hit::Field("class", hit::Field::Kind::String, obj->_classname));
1272 ent->addChild(new hit::Field("file", hit::Field::Kind::String, obj->_file));
1273 }
1274
1275 auto actsec = new hit::Section("actions");
1276 sec->addChild(actsec);
1277 auto & actmap = Registry::allActions();
1278 for (auto & entry : actmap)
1279 for (auto & act : entry.second)
1280 {
1281 auto ent = new hit::Section("entry");
1282 actsec->addChild(ent);
1283 ent->addChild(new hit::Field("label", hit::Field::Kind::String, entry.first));
1284 ent->addChild(new hit::Field("type", hit::Field::Kind::String, "action"));
1285 ent->addChild(new hit::Field("task", hit::Field::Kind::String, act->_name));
1286 ent->addChild(new hit::Field("class", hit::Field::Kind::String, act->_classname));
1287 ent->addChild(new hit::Field("file", hit::Field::Kind::String, act->_file));
1288 }
1289
1290 Moose::out << root.render();
1291
1292 Moose::out << "\n### END REGISTRY DATA ###\n";
1293 _early_exit_param = "--registry_hit";
1294 _ready_to_exit = true;
1295 }
1296 else if (getParam<bool>("yaml") || isParamSetByUser("yaml_search"))
1297 {
1298 const std::string search =
1299 isParamSetByUser("yaml_search") ? getParam<std::string>("yaml_search") : "";
1301
1303 _builder.buildFullTree(search);
1304
1305 _early_exit_param = "--yaml";
1306 _ready_to_exit = true;
1307 }
1308 else if (getParam<bool>("json") || isParamSetByUser("json_search"))
1309 {
1310 const std::string search =
1311 isParamSetByUser("json_search") ? getParam<std::string>("json_search") : "";
1313
1314 JsonSyntaxTree tree(search);
1316
1318 "json", "**START JSON DATA**\n", "\n**END JSON DATA**", tree.getRoot().dump(2));
1319 _early_exit_param = "--json";
1320 _ready_to_exit = true;
1321 }
1322 else if (getParam<bool>("syntax"))
1323 {
1325
1326 std::multimap<std::string, Syntax::ActionInfo> syntax = _syntax.getAssociatedActions();
1327 std::stringstream ss;
1328 for (const auto & it : syntax)
1329 ss << it.first << "\n";
1330 outputMachineReadableData("syntax", "**START SYNTAX DATA**\n", "**END SYNTAX DATA**", ss.str());
1331 _early_exit_param = "--syntax";
1332 _ready_to_exit = true;
1333 }
1334 else if (getParam<bool>("show_type"))
1335 {
1337
1338 Moose::out << "MooseApp Type: " << type() << std::endl;
1339 _early_exit_param = "--show-type";
1340 _ready_to_exit = true;
1341 }
1342 else if (getParam<bool>("show_capabilities"))
1343 {
1345 outputMachineReadableData("show_capabilities",
1346 "**START JSON DATA**\n",
1347 "\n**END JSON DATA**",
1349 _ready_to_exit = true;
1350 }
1351 else if (isParamValid("check_capabilities"))
1352 {
1354
1356 const auto & capabilities = getParam<std::string>("check_capabilities");
1357
1358 CapabilityRegistry::CheckResult result;
1359 try
1360 {
1361 result = Moose::internal::Capabilities::getCapabilities({}).check(capabilities);
1362 }
1363 catch (const std::exception & e)
1364 {
1365 mooseError("--check-capablities: ", e.what());
1366 }
1367
1368 const bool pass = result.state == CapabilityRegistry::CheckState::CERTAIN_PASS;
1369 _console << "Capabilities '" << capabilities << "' are " << (pass ? "" : "not ") << "fulfilled."
1370 << std::endl;
1371 _ready_to_exit = true;
1372 if (!pass)
1373 _exit_code = 77;
1374 return;
1375 }
1376 else if (!getInputFileNames().empty())
1377 {
1378 if (isParamSetByUser("recover"))
1379 {
1380 // We need to set the flag manually here since the recover parameter is a string type (takes
1381 // an optional filename)
1382 _recover = true;
1383 const auto & recover = getParam<std::string>("recover");
1384 if (recover.size())
1385 _restart_recover_base = recover;
1386 }
1387
1388 _builder.build();
1389
1390 // Lambda to check for mutually exclusive parameters
1391 auto isExclusiveParamSetByUser =
1392 [this](const std::vector<std::string> & group, const std::string & param)
1393 {
1394 auto is_set = isParamSetByUser(param);
1395 if (is_set)
1396 for (const auto & p : group)
1397 if (p != param && isParamSetByUser(p))
1398 mooseError("Parameters '" + p + "' and '" + param +
1399 "' are mutually exclusive. Please choose only one of them.");
1400 return is_set;
1401 };
1402
1403 // The following parameters set the final task and so are mutually exclusive.
1404 const std::vector<std::string> final_task_params = {
1405 "csg_only", "mesh_only", "split_mesh", "parse_neml2_only"};
1406 if (isExclusiveParamSetByUser(final_task_params, "csg_only"))
1407 {
1408 // Error checking on incompatible command line options
1410 mooseError("--csg-only cannot be used in conjunction with --distributed-mesh");
1411 const bool has_mesh_split = isParamSetByUser("split_file") || _use_split;
1412 if (has_mesh_split)
1413 mooseError("--csg-only is not compatible with any mesh splitting options");
1414 if (isParamSetByUser("refinements"))
1415 mooseError("--csg-only cannot be used in conjunction with -r refinements option");
1416 if (!isUltimateMaster())
1417 mooseError("--csg-only option cannot be used as a Subapp");
1418 if (_recover)
1419 mooseError("--csg-only option cannot be used in recovery mode");
1420
1421 _syntax.registerTaskName("execute_csg_generators", true);
1422 _syntax.addDependency("execute_csg_generators", "execute_mesh_generators");
1423 _syntax.addDependency("recover_meta_data", "execute_csg_generators");
1424
1425 _syntax.registerTaskName("csg_only", true);
1426 _syntax.addDependency("csg_only", "recover_meta_data");
1427 _syntax.addDependency("set_mesh_base", "csg_only");
1428 _action_warehouse.setFinalTask("csg_only");
1429 }
1430 else if (isExclusiveParamSetByUser(final_task_params, "mesh_only"))
1431 {
1432 // If we are looking to just check the input, there is no need to
1433 // call MeshOnlyAction and generate a mesh
1434 if (_check_input)
1435 _action_warehouse.setFinalTask("setup_mesh_complete");
1436 else
1437 {
1438 _syntax.registerTaskName("mesh_only", true);
1439 _syntax.addDependency("mesh_only", "setup_mesh_complete");
1440 _syntax.addDependency("determine_system_type", "mesh_only");
1441 _action_warehouse.setFinalTask("mesh_only");
1442 }
1443 }
1444 else if (isExclusiveParamSetByUser(final_task_params, "split_mesh"))
1445 {
1446 _split_mesh = true;
1447 _syntax.registerTaskName("split_mesh", true);
1448 _syntax.addDependency("split_mesh", "setup_mesh_complete");
1449 _syntax.addDependency("determine_system_type", "split_mesh");
1450 _action_warehouse.setFinalTask("split_mesh");
1451 }
1452 else if (isExclusiveParamSetByUser(final_task_params, "parse_neml2_only"))
1453 {
1454 _syntax.registerTaskName("parse_neml2");
1455 _syntax.addDependency("determine_system_type", "parse_neml2");
1456 _action_warehouse.setFinalTask("parse_neml2");
1457 }
1459
1460 // Setup the AppFileBase for use by the Outputs or other systems that need output file info
1461 {
1462 // Extract the CommonOutputAction
1463 const auto common_actions = _action_warehouse.getActions<CommonOutputAction>();
1464 mooseAssert(common_actions.size() <= 1, "Should not be more than one CommonOutputAction");
1465 const Action * common = common_actions.empty() ? nullptr : *common_actions.begin();
1466
1467 // If file_base is set in CommonOutputAction through parsing input, obtain the file_base
1468 if (common && common->isParamValid("file_base"))
1469 {
1470 _output_file_base = common->getParam<std::string>("file_base");
1472 }
1473 else if (isUltimateMaster())
1474 {
1475 // if this app is a master, we use the first input file name as the default file base.
1476 // use proximate here because the input file is an absolute path
1477 const auto & base = getLastInputFileName();
1478 size_t pos = base.find_last_of('.');
1479 _output_file_base = base.substr(0, pos);
1480 // Note: we did not append "_out" in the file base here because we do not want to
1481 // have it in between the input file name and the object name for Output/*
1482 // syntax.
1483 }
1484 // default file base for multiapps is set by MultiApp
1485 }
1486 }
1487 // No input file provided but we have other arguments (so don't just show print usage)
1488 else if (!isParamSetByUser("input_file") && _command_line->getArguments().size() > 2)
1489 {
1490 mooseAssert(getInputFileNames().empty(), "Should be empty");
1491
1492 if (_check_input)
1493 mooseError("You specified --check-input, but did not provide an input file. Add -i "
1494 "<inputfile> to your command line.");
1495
1496 mooseError("No input files specified. Add -i <inputfile> to your command line.");
1497 }
1498 else if (isParamValid("language_server") && getParam<bool>("language_server"))
1499 {
1501
1502 // Reset output to the buffer what was cached before it was turned it off
1503 if (!Moose::out.rdbuf() && _output_buffer_cache)
1504 Moose::out.rdbuf(_output_buffer_cache);
1505
1506 // Start a language server that communicates using an iostream connection
1507 MooseServer moose_server(*this);
1508
1509 moose_server.run();
1510
1511 _early_exit_param = "--language-server";
1512 _ready_to_exit = true;
1513 }
1514
1515 else /* The catch-all case for bad options or missing options, etc. */
1516 {
1517 _command_line->printUsage();
1518 _early_exit_param = "bad or missing";
1519 _ready_to_exit = true;
1520 _exit_code = 1;
1521 }
1522
1523 Moose::out << std::flush;
1524}
1525
1526const std::vector<std::string> &
1528{
1529 mooseAssert(_parser, "Parser is not set");
1530 return _parser->getInputFileNames();
1531}
1532
1533const std::string &
1535{
1536 mooseAssert(_parser, "Parser is not set");
1537 return _parser->getLastInputFileName();
1538}
1539
1540std::string
1541MooseApp::getOutputFileBase(bool for_non_moose_build_output) const
1542{
1543 if (_file_base_set_by_user || for_non_moose_build_output || _multiapp_level)
1544 return _output_file_base;
1545 else
1546 return _output_file_base + "_out";
1547}
1548
1549void
1550MooseApp::setOutputFileBase(const std::string & output_file_base)
1551{
1552 _output_file_base = output_file_base;
1553
1554 // Reset the file base in the outputs
1556
1557 // Reset the file base in multiapps (if they have been constructed yet)
1558 if (getExecutioner())
1559 for (auto & multi_app : feProblem().getMultiAppWarehouse().getObjects())
1560 multi_app->setAppOutputFileBase();
1561
1563}
1564
1565void
1567{
1568 TIME_SECTION("runInputFile", 3);
1569
1570 // If early exit param has been set, then just return
1571 if (_ready_to_exit)
1572 return;
1573
1575
1576 if (isParamSetByUser("csg_only"))
1577 {
1578 _early_exit_param = "--csg-only";
1579 _ready_to_exit = true;
1580 }
1581 else if (isParamSetByUser("mesh_only"))
1582 {
1583 _early_exit_param = "--mesh-only";
1584 _ready_to_exit = true;
1585 }
1586 else if (isParamSetByUser("split_mesh"))
1587 {
1588 _early_exit_param = "--split-mesh";
1589 _ready_to_exit = true;
1590 }
1591 else if (isParamSetByUser("parse_neml2_only"))
1592 {
1593 _early_exit_param = "--parse-neml2-only";
1594 _ready_to_exit = true;
1595 }
1596 else if (getParam<bool>("list_constructed_objects"))
1597 {
1598 // TODO: ask multiapps for their constructed objects
1599 _early_exit_param = "--list-constructed-objects";
1600 _ready_to_exit = true;
1601 std::stringstream ss;
1602 for (const auto & obj : _factory.getConstructedObjects())
1603 ss << obj << '\n';
1605 "list_constructed_objects", "**START OBJECT DATA**\n", "\n**END OBJECT DATA**", ss.str());
1606 }
1607}
1608
1609void
1611{
1612 bool warn = _enable_unused_check == WARN_UNUSED;
1613 bool err = _enable_unused_check == ERROR_UNUSED;
1614
1615 _builder.errorCheck(*_comm, warn, err);
1616
1617 // Return early for mesh only mode, since we want error checking to run even though
1618 // an executor is not created for this case
1619 if (isParamSetByUser("mesh_only"))
1620 return;
1621
1622 if (!_executor.get() && !_executioner.get())
1623 {
1624 if (!_early_exit_param.empty())
1625 {
1626 mooseAssert(_check_input,
1627 "Something went wrong, we should only get here if _check_input is true.");
1628 mooseError(
1629 "Incompatible command line arguments provided. --check-input cannot be called with ",
1631 ".");
1632 }
1633 // We should never get here
1634 mooseError("The Executor is being called without being initialized. This is likely "
1635 "caused by "
1636 "incompatible command line arguments");
1637 }
1638
1639 auto apps = feProblem().getMultiAppWarehouse().getObjects();
1640 for (auto app : apps)
1641 for (unsigned int i = 0; i < app->numLocalApps(); i++)
1642 app->localApp(i)->errorCheck();
1643}
1644
1645void
1647{
1648 TIME_SECTION("executeExecutioner", 3);
1649
1650 // If ready to exit has been set, then just return
1651 if (_ready_to_exit)
1652 return;
1653
1654 // run the simulation
1655 if (_use_executor && _executor)
1656 {
1658 _executor->init();
1659 errorCheck();
1660 auto result = _executor->exec();
1661 if (!result.convergedAll())
1662 mooseError(result.str());
1663 }
1664 else if (_executioner)
1665 {
1667 _executioner->init();
1668 errorCheck();
1669 _executioner->execute();
1670 if (!_executioner->lastSolveConverged())
1671 setExitCode(1);
1672 }
1673 else
1674 mooseError("No executioner was specified (go fix your input file)");
1675}
1676
1677bool
1679{
1680 return _recover;
1681}
1682
1683bool
1685{
1686 return _restart;
1687}
1688
1689bool
1691{
1692 return _split_mesh;
1693}
1694
1695bool
1697{
1698 return !_restart_recover_base.empty();
1699}
1700
1701bool
1703{
1704 mooseDeprecated("MooseApp::hasRecoverFileBase is deprecated, use "
1705 "MooseApp::hasRestartRecoverFileBase() instead.");
1706 return !_restart_recover_base.empty();
1707}
1708
1709void
1712{
1714 switch (filter)
1715 {
1716 case RESTARTABLE_FILTER::RECOVERABLE:
1718 break;
1719 default:
1720 mooseError("Unknown filter");
1721 }
1722}
1723
1724std::vector<std::filesystem::path>
1725MooseApp::backup(const std::filesystem::path & folder_base)
1726{
1727 TIME_SECTION("backup", 2, "Backing Up Application to File");
1728
1729 preBackup();
1730
1732 return writer.write(folder_base);
1733}
1734
1735std::unique_ptr<Backup>
1737{
1738 TIME_SECTION("backup", 2, "Backing Up Application");
1739
1741
1742 preBackup();
1743
1744 auto backup = std::make_unique<Backup>();
1745 packMeshBackup(*this, *backup);
1746 writer.write(*backup->header, *backup->data);
1747
1748 return backup;
1749}
1750
1751bool
1753{
1754 return hasInitialBackup() && !(*_initial_backup)->mesh_files.empty();
1755}
1756
1757void
1759{
1760 mooseAssert(hasInitialBackup(), "Missing initial backup");
1761 _restored_initial_backup_mesh = restoreMeshBackup(*this, **_initial_backup, mesh);
1762}
1763
1764void
1765MooseApp::restore(const std::filesystem::path & folder_base, const bool for_restart)
1766{
1767 TIME_SECTION("restore", 2, "Restoring Application from File");
1768
1769 const DataNames filter_names = for_restart ? getRecoverableData() : DataNames{};
1770
1771 _rd_reader.setInput(folder_base);
1772 _rd_reader.restore(filter_names);
1773
1774 postRestore(for_restart);
1775}
1776
1777void
1778MooseApp::restore(std::unique_ptr<Backup> backup, const bool for_restart)
1779{
1780 TIME_SECTION("restore", 2, "Restoring Application");
1781
1782 const DataNames filter_names = for_restart ? getRecoverableData() : DataNames{};
1783
1784 if (!backup)
1785 mooseError("MooseApp::restore(): Provided backup is not initialized");
1786
1787 auto header = std::move(backup->header);
1788 mooseAssert(header, "Header not available");
1789
1790 auto data = std::move(backup->data);
1791 mooseAssert(data, "Data not available");
1792
1793 if (restoreMeshBackup(*this, *backup, feProblem().mesh()))
1794 {
1796 feProblem().mesh().prepare();
1797 feProblem().meshChanged(/*intermediate_change=*/false,
1798 /*contract_mesh=*/false,
1799 /*clean_refinement_flags=*/false);
1800 }
1801
1802 _rd_reader.setInput(std::move(header), std::move(data));
1803 _rd_reader.restore(filter_names);
1804
1805 postRestore(for_restart);
1806}
1807
1808void
1810{
1811 mooseAssert(hasInitialBackup(), "Missing initial backup");
1812 restore(std::move(*_initial_backup), for_restart);
1813}
1814
1815std::unique_ptr<Backup>
1817{
1818 if (!_rd_reader.isRestoring())
1819 mooseError("MooseApp::finalizeRestore(): Not currently restoring");
1820
1821 // This gives us access to the underlying streams so that we can return it if needed
1822 auto input_streams = _rd_reader.clear();
1823
1824 std::unique_ptr<Backup> backup;
1825
1826 // Give them back a backup if this restore started from a Backup, in which case
1827 // the two streams in the Backup are formed into StringInputStreams
1828 if (auto header_string_input = dynamic_cast<StringInputStream *>(input_streams.header.get()))
1829 {
1830 auto data_string_input = dynamic_cast<StringInputStream *>(input_streams.data.get());
1831 mooseAssert(data_string_input, "Should also be a string input");
1832
1833 auto header_sstream = header_string_input->release();
1834 mooseAssert(header_sstream, "Header not available");
1835
1836 auto data_sstream = data_string_input->release();
1837 mooseAssert(data_sstream, "Data not available");
1838
1839 backup = std::make_unique<Backup>();
1840 backup->header = std::move(header_sstream);
1841 backup->data = std::move(data_sstream);
1842 packMeshBackup(*this, *backup);
1843 }
1844
1845 return backup;
1846}
1847
1848void
1850{
1851 _enable_unused_check = warn_is_error ? ERROR_UNUSED : WARN_UNUSED;
1852}
1853
1854void
1859
1862{
1863 mooseAssert(_executor.get() || _executioner.get(), "No executioner yet, calling too early!");
1864 return _executor.get() ? _executor->feProblem() : _executioner->feProblem();
1865}
1866
1867void
1868MooseApp::addExecutor(const std::string & type,
1869 const std::string & name,
1870 const InputParameters & params)
1871{
1872 std::shared_ptr<Executor> executor = _factory.create<Executor>(type, name, params);
1873
1874 if (_executors.count(executor->name()) > 0)
1875 mooseError("an executor with name '", executor->name(), "' already exists");
1876 _executors[executor->name()] = executor;
1877}
1878
1879void
1880MooseApp::addExecutorParams(const std::string & type,
1881 const std::string & name,
1882 const InputParameters & params)
1883{
1884 _executor_params[name] = std::make_pair(type, std::make_unique<InputParameters>(params));
1885}
1886
1887const Parser &
1889{
1890 mooseAssert(_parser, "Not set");
1891 return *_parser;
1892}
1893
1894Parser &
1896{
1897 return const_cast<Parser &>(std::as_const(*this).parser());
1898}
1899
1900void
1901MooseApp::recursivelyCreateExecutors(const std::string & current_executor_name,
1902 std::list<std::string> & possible_roots,
1903 std::list<std::string> & current_branch)
1904{
1905 // Did we already make this one?
1906 if (_executors.find(current_executor_name) != _executors.end())
1907 return;
1908
1909 // Is this one already on the current branch (i.e. there is a cycle)
1910 if (std::find(current_branch.begin(), current_branch.end(), current_executor_name) !=
1911 current_branch.end())
1912 {
1913 std::stringstream exec_names_string;
1914
1915 auto branch_it = current_branch.begin();
1916
1917 exec_names_string << *branch_it++;
1918
1919 for (; branch_it != current_branch.end(); ++branch_it)
1920 exec_names_string << ", " << *branch_it;
1921
1922 exec_names_string << ", " << current_executor_name;
1923
1924 mooseError("Executor cycle detected: ", exec_names_string.str());
1925 }
1926
1927 current_branch.push_back(current_executor_name);
1928
1929 // Build the dependencies first
1930 const auto & params = *_executor_params[current_executor_name].second;
1931
1932 for (const auto & param : params)
1933 {
1934 if (params.have_parameter<ExecutorName>(param.first))
1935 {
1936 const auto & dependency_name = params.get<ExecutorName>(param.first);
1937
1938 possible_roots.remove(dependency_name);
1939
1940 if (!dependency_name.empty())
1941 recursivelyCreateExecutors(dependency_name, possible_roots, current_branch);
1942 }
1943 }
1944
1945 // Add this Executor
1946 const auto & type = _executor_params[current_executor_name].first;
1947 addExecutor(type, current_executor_name, params);
1948
1949 current_branch.pop_back();
1950}
1951
1952void
1954{
1955 // Do we have any?
1956 if (_executor_params.empty())
1957 return;
1958
1959 // Holds the names of Executors that may be the root executor
1960 std::list<std::string> possibly_root;
1961
1962 // What is already built
1963 std::map<std::string, bool> already_built;
1964
1965 // The Executors that are currently candidates for being roots
1966 std::list<std::string> possible_roots;
1967
1968 // The current line of dependencies - used for finding cycles
1969 std::list<std::string> current_branch;
1970
1971 // Build the NullExecutor
1972 {
1973 auto params = _factory.getValidParams("NullExecutor");
1974 _null_executor = _factory.create<NullExecutor>("NullExecutor", "_null_executor", params);
1975 }
1976
1977 for (const auto & params_entry : _executor_params)
1978 {
1979 const auto & name = params_entry.first;
1980
1981 // Did we already make this one?
1982 if (_executors.find(name) != _executors.end())
1983 continue;
1984
1985 possible_roots.emplace_back(name);
1986
1987 recursivelyCreateExecutors(name, possible_roots, current_branch);
1988 }
1989
1990 // If there is more than one possible root - error
1991 if (possible_roots.size() > 1)
1992 {
1993 auto root_string_it = possible_roots.begin();
1994
1995 std::stringstream roots_string;
1996
1997 roots_string << *root_string_it++;
1998
1999 for (; root_string_it != possible_roots.end(); ++root_string_it)
2000 roots_string << ", " << *root_string_it;
2001
2002 mooseError("Multiple Executor roots found: ", roots_string.str());
2003 }
2004
2005 // Set the root executor
2006 _executor = _executors[possible_roots.front()];
2007}
2008
2009Executor &
2010MooseApp::getExecutor(const std::string & name, bool fail_if_not_found)
2011{
2012 auto it = _executors.find(name);
2013
2014 if (it != _executors.end())
2015 return *it->second;
2016
2017 if (fail_if_not_found)
2018 mooseError("Executor not found: ", name);
2019
2020 return *_null_executor;
2021}
2022
2025{
2026 return _executioner.get() ? _executioner.get() : _executor.get();
2027}
2028
2029void
2034
2035void
2037{
2038 TIME_SECTION("run", 3);
2039 if (getParam<bool>("show_docs"))
2040 {
2041 auto binname = appBinaryName();
2042 if (binname == "")
2043 mooseError("could not locate installed tests to run (unresolved binary/app name)");
2044 auto docspath = MooseUtils::docsDir(binname);
2045 if (docspath == "")
2046 mooseError("no installed documentation found");
2047
2048 auto docmsgfile = MooseUtils::pathjoin(docspath, "docmsg.txt");
2049 std::string docmsg = "file://" + MooseUtils::realpath(docspath) + "/index.html";
2050 if (MooseUtils::pathExists(docmsgfile) && MooseUtils::checkFileReadable(docmsgfile))
2051 {
2052 std::ifstream ifs(docmsgfile);
2053 std::string content((std::istreambuf_iterator<char>(ifs)),
2054 (std::istreambuf_iterator<char>()));
2055 content.replace(content.find("$LOCAL_SITE_HOME"), content.length(), docmsg);
2056 docmsg = content;
2057 }
2058
2059 Moose::out << docmsg << "\n";
2060 _early_exit_param = "--docs";
2061 _ready_to_exit = true;
2062 return;
2063 }
2064
2065 if (showInputs() || copyInputs() || runInputs())
2066 {
2067 _early_exit_param = "--show-input, --copy-inputs, or --run";
2068 _ready_to_exit = true;
2069 return;
2070 }
2071
2072 try
2073 {
2074 TIME_SECTION("setup", 2, "Setting Up");
2075 setupOptions();
2076 runInputFile();
2077 }
2078 catch (Parser::Error & err)
2079 {
2080 mooseAssert(_parser->getThrowOnError(), "Should be true");
2081 throw;
2082 }
2083 catch (MooseRuntimeError & err)
2084 {
2085 mooseAssert(Moose::_throw_on_error, "Should be true");
2086 throw;
2087 }
2088 catch (std::exception & err)
2089 {
2090 mooseError(err.what());
2091 }
2092
2093 if (!_check_input)
2094 {
2095 TIME_SECTION("execute", 2, "Executing");
2097 }
2098 else
2099 {
2100 errorCheck();
2101 // Output to stderr, so it is easier for peacock to get the result
2102 Moose::err << "Syntax OK" << std::endl;
2103 }
2104
2105 if (isParamSetByUser("citations"))
2107}
2108
2109void
2110MooseApp::collectCitations(std::map<std::string, std::string> & citations) const
2111{
2112 // Gather the citations that apply to this app: for every object type actually constructed, the
2113 // citations registered for its owning app/module. The framework paper is tied to "MooseApp", so
2114 // it is gathered whenever a MooseApp object is used; apps composed of MooseApp inherit it. The
2115 // map is keyed by BibTeX key so a citation shared across apps is folded in only once.
2116 for (const auto & objname : _factory.getConstructedObjects())
2117 {
2118 mooseAssert(Registry::isRegisteredObj(objname),
2119 "Constructed object '" + objname + "' is not registered");
2120 const auto & app_citations = Registry::getCitations(Registry::objData(objname)._label);
2121 citations.insert(app_citations.begin(), app_citations.end());
2122 }
2123
2124 // Credit the finite element backend actually used in the run. These are mutually exclusive, so
2125 // only the backend in use is cited.
2126 std::string backend = "libMesh";
2127#ifdef MOOSE_MFEM_ENABLED
2128 if ((_executor || _executioner) && feProblem().feBackend() == Moose::FEBackend::MFEM)
2129 backend = "MFEM";
2130#endif
2131 const auto & backend_citations = Registry::getCitations(backend);
2132 citations.insert(backend_citations.begin(), backend_citations.end());
2133
2134 // Recurse into the MultiApp subapps so that objects/modules used only inside subapps are still
2135 // attributed. Each subapp is a separate MooseApp whose run() (and thus requestCitations()) is
2136 // never called, so the master gathers their citations here. feProblem() asserts when there is no
2137 // executioner, so only descend once one exists; nested MultiApps are handled by the recursion.
2138 if (_executor || _executioner)
2139 for (const auto & multi_app : feProblem().getMultiAppWarehouse().getObjects())
2140 for (const auto i : make_range(multi_app->numLocalApps()))
2141 multi_app->localApp(i)->collectCitations(citations);
2142}
2143
2144void
2146{
2147 // Collect the de-duplicated citations across this app and, recursively, every MultiApp subapp.
2148 std::map<std::string, std::string> citations;
2149 collectCitations(citations);
2150
2151 // MultiApp subapps are distributed across the MPI ranks, so each rank has collected citations
2152 // only for the subapps it owns. PETSc prints the citation list from rank 0 alone, so gather every
2153 // rank's citations onto all ranks; otherwise a module used only by a subapp that lives off rank 0
2154 // would be omitted.
2155 std::vector<std::string> flattened;
2156 flattened.reserve(citations.size() * 2);
2157 for (const auto & [key, bibtex] : citations)
2158 {
2159 flattened.push_back(key);
2160 flattened.push_back(bibtex);
2161 }
2162 _comm->allgather(flattened);
2163 for (std::size_t i = 0; i + 1 < flattened.size(); i += 2)
2164 {
2165 [[maybe_unused]] const auto [it, inserted] = citations.emplace(flattened[i], flattened[i + 1]);
2166 mooseAssert(inserted || it->second == flattened[i + 1],
2167 "The same citation key was registered with different BibTeX entries");
2168 }
2169
2170 // Register the resolved BibTeX entries with PETSc and enable its -citations option. PETSc prints
2171 // them, together with the run-specific citations from any PETSc solvers/preconditioners actually
2172 // used, at PetscFinalize (to the console or, if a file name was given, to that file).
2173 for (const auto & citation : citations)
2175
2176 Moose::PetscSupport::setSinglePetscOption("-citations", getParam<std::string>("citations"));
2177}
2178
2179bool
2181{
2182 if (getParam<bool>("show_inputs"))
2183 {
2184 const auto show_inputs_syntax = _pars.getCommandLineMetadata("show_inputs").switches;
2185 std::vector<std::string> dirs;
2186 const auto installable_inputs = getInstallableInputs();
2187
2188 if (installable_inputs == "")
2189 {
2190 Moose::out
2191 << "Show inputs has not been overriden in this application.\nContact the developers of "
2192 "this appication and request that they override \"MooseApp::getInstallableInputs\".\n";
2193 }
2194 else
2195 {
2196 mooseAssert(!show_inputs_syntax.empty(), "show_inputs sytnax should not be empty");
2197
2198 MooseUtils::tokenize(installable_inputs, dirs, 1, " ");
2199 Moose::out << "The following directories are installable into a user-writeable directory:\n\n"
2200 << installable_inputs << '\n'
2201 << "\nTo install one or more directories of inputs, execute the binary with the \""
2202 << show_inputs_syntax[0] << "\" flag. e.g.:\n$ "
2203 << _command_line->getExecutableName() << ' ' << show_inputs_syntax[0] << ' '
2204 << dirs[0] << '\n';
2205 }
2206 return true;
2207 }
2208 return false;
2209}
2210
2211std::string
2213{
2214 return "tests";
2215}
2216
2217bool
2219{
2220 if (isParamSetByUser("copy_inputs"))
2221 {
2222 if (comm().size() > 1)
2223 mooseError("The --copy-inputs option should not be ran in parallel");
2224
2225 // Get command line argument following --copy-inputs on command line
2226 auto dir_to_copy = getParam<std::string>("copy_inputs");
2227
2228 if (dir_to_copy.empty())
2229 mooseError("Error retrieving directory to copy");
2230 if (dir_to_copy.back() != '/')
2231 dir_to_copy += '/';
2232
2233 // This binary name is the actual binary. That is, if we called a symlink it'll
2234 // be the name of what the symlink points to
2235 auto binname = appBinaryName();
2236 if (binname == "")
2237 mooseError("could not locate installed tests to run (unresolved binary/app name)");
2238
2239 auto src_dir = MooseUtils::installedInputsDir(
2240 binname,
2241 dir_to_copy,
2242 "Rerun binary with " + _pars.getCommandLineMetadata("show_inputs").switches[0] +
2243 " to get a list of installable directories.");
2244
2245 // Use the command line here because if we have a symlink to another binary,
2246 // we want to dump into a directory that is named after the symlink not the true binary
2247 auto dst_dir = _command_line->getExecutableNameBase() + "/" + dir_to_copy;
2248 auto cmdname = _command_line->getExecutableName();
2249 if (cmdname.find_first_of("/") != std::string::npos)
2250 cmdname = cmdname.substr(cmdname.find_first_of("/") + 1, std::string::npos);
2251
2252 if (MooseUtils::pathExists(dst_dir))
2253 mooseError(
2254 "The directory \"./",
2255 dst_dir,
2256 "\" already exists.\nTo update/recopy the contents of this directory, rename (\"mv ",
2257 dst_dir,
2258 " new_dir_name\") or remove (\"rm -r ",
2259 dst_dir,
2260 "\") the existing directory.\nThen re-run \"",
2261 cmdname,
2262 " --copy-inputs ",
2263 dir_to_copy,
2264 "\".");
2265
2266 std::string cmd = "mkdir -p " + dst_dir + "; rsync -av " + src_dir + " " + dst_dir;
2267
2268 TIME_SECTION("copy_inputs", 2, "Copying Inputs");
2269
2270 mooseAssert(comm().size() == 1, "Should be run in serial");
2271 const auto return_value = system(cmd.c_str());
2272 if (!WIFEXITED(return_value))
2273 mooseError("Process exited unexpectedly");
2274 setExitCode(WEXITSTATUS(return_value));
2275 if (exitCode() == 0)
2276 Moose::out << "Directory successfully copied into ./" << dst_dir << '\n';
2277 return true;
2278 }
2279 return false;
2280}
2281
2282bool
2284{
2285 if (isParamSetByUser("run"))
2286 {
2287 if (comm().size() > 1)
2288 mooseError("The --run option should not be ran in parallel");
2289
2290 // Pass everything after --run on the cli to the TestHarness
2291 const auto find_run_it = std::as_const(*_command_line).findCommandLineParam("run");
2292 const auto & cl_entries = std::as_const(*_command_line).getEntries();
2293 mooseAssert(find_run_it != cl_entries.end(), "Didn't find the option");
2294 std::string test_args;
2295 for (auto it = std::next(find_run_it); it != cl_entries.end(); ++it)
2296 for (const auto & arg : it->raw_args)
2297 {
2298 test_args += " " + arg;
2300 }
2301
2302 auto working_dir = MooseUtils::getCurrentWorkingDir();
2303 if (MooseUtils::findTestRoot() == "")
2304 {
2305 auto bin_name = appBinaryName();
2306 if (bin_name == "")
2307 mooseError("Could not locate binary name relative to installed location");
2308
2309 auto cmd_name = Moose::getExecutableName();
2310 mooseError(
2311 "Could not locate installed tests from the current working directory:",
2312 working_dir,
2313 ".\nMake sure you are executing this command from within a writable installed inputs ",
2314 "directory.\nRun \"",
2315 cmd_name,
2316 " --copy-inputs <dir>\" to copy the contents of <dir> to a \"./",
2317 bin_name,
2318 "_<dir>\" directory.\nChange into that directory and try \"",
2319 cmd_name,
2320 " --run <dir>\" again.");
2321 }
2322
2323 // Set this application as the app name for the moose_test_runner script that we're running
2324 setenv("MOOSE_TEST_RUNNER_APP_NAME", appBinaryName().c_str(), true);
2325
2326 const std::string cmd = MooseUtils::runTestsExecutable() + test_args;
2327 Moose::out << "Working Directory: " << working_dir << "\nRunning Command: " << cmd << std::endl;
2328 mooseAssert(comm().size() == 1, "Should be run in serial");
2329 const auto return_value = system(cmd.c_str());
2330 if (!WIFEXITED(return_value))
2331 mooseError("Process exited unexpectedly");
2332 setExitCode(WEXITSTATUS(return_value));
2333 return true;
2334 }
2335
2336 return false;
2337}
2338
2340MooseApp::addCapabilityInternal(const std::string_view capability,
2341 const Moose::Capability::Value & value,
2342 const std::string_view doc)
2343{
2344 try
2345 {
2346 return Moose::internal::Capabilities::getCapabilities({}).add(capability, value, doc);
2347 }
2348 catch (const std::exception & e)
2349 {
2350 ::mooseError(e.what());
2351 }
2352}
2353
2354void
2356{
2357 _output_position_set = true;
2358 _output_position = p;
2360
2361 if (_executioner.get())
2362 _executioner->parentOutputPositionChanged();
2363}
2364
2365std::list<std::string>
2367{
2368 // Storage for the directory names
2369 std::list<std::string> checkpoint_dirs;
2370
2371 // Add the directories added with Outputs/checkpoint=true input syntax
2372 checkpoint_dirs.push_back(getOutputFileBase() + "_cp");
2373
2374 // Add the directories from any existing checkpoint output objects
2375 const auto & actions = _action_warehouse.getActionListByName("add_output");
2376 for (const auto & action : actions)
2377 {
2378 // Get the parameters from the MooseObjectAction
2379 MooseObjectAction * moose_object_action = dynamic_cast<MooseObjectAction *>(action);
2380 if (!moose_object_action)
2381 continue;
2382
2383 const InputParameters & params = moose_object_action->getObjectParams();
2384 if (moose_object_action->getParam<std::string>("type") == "Checkpoint")
2385 {
2386 // Unless file_base was explicitly set by user, we cannot rely on it, as it will be changed
2387 // later
2388 const std::string cp_dir =
2389 _file_base_set_by_user ? params.get<std::string>("file_base")
2390 : (getOutputFileBase(true) + "_" + moose_object_action->name());
2391 checkpoint_dirs.push_back(cp_dir + "_cp");
2392 }
2393 }
2394 return checkpoint_dirs;
2395}
2396
2397std::list<std::string>
2399{
2400 auto checkpoint_dirs = getCheckpointDirectories();
2401 return MooseUtils::getFilesInDirs(checkpoint_dirs, false);
2402}
2403
2404void
2406{
2407 _start_time_set = true;
2408 _start_time = time;
2409}
2410
2411std::string
2412MooseApp::getFileName(bool stripLeadingPath) const
2413{
2414 return _builder.getPrimaryFileName(stripLeadingPath);
2415}
2416
2422
2423const OutputWarehouse &
2425{
2426 return _output_warehouse;
2427}
2428
2429std::string
2430MooseApp::appNameToLibName(const std::string & app_name) const
2431{
2432 std::string library_name(app_name);
2433
2434 // Strip off the App part (should always be the last 3 letters of the name)
2435 size_t pos = library_name.find("App");
2436 if (pos != library_name.length() - 3)
2437 mooseError("Invalid application name: ", library_name);
2438 library_name.erase(pos);
2439
2440 // Now get rid of the camel case, prepend lib, and append the method and suffix
2441 return std::string("lib") + MooseUtils::camelCaseToUnderscore(library_name) + '-' +
2442 QUOTE(METHOD) + ".la";
2443}
2444
2445std::string
2446MooseApp::libNameToAppName(const std::string & library_name) const
2447{
2448 std::string app_name(library_name);
2449
2450 // Strip off the leading "lib" and trailing ".la"
2451 if (pcrecpp::RE("lib(.+?)(?:-\\w+)?\\.la").Replace("\\1", &app_name) == 0)
2452 mooseError("Invalid library name: ", app_name);
2453
2454 return MooseUtils::underscoreToCamelCase(app_name, true);
2455}
2456
2458MooseApp::registerRestartableData(std::unique_ptr<RestartableDataValue> data,
2459 THREAD_ID tid,
2460 bool read_only,
2461 const RestartableDataMapName & metaname)
2462{
2463 if (!metaname.empty() && tid != 0)
2464 mooseError(
2465 "The meta data storage for '", metaname, "' is not threaded, so the tid must be zero.");
2466
2467 mooseAssert(metaname.empty() ||
2468 _restartable_meta_data.find(metaname) != _restartable_meta_data.end(),
2469 "The desired meta data name does not exist: " + metaname);
2470
2471 // Select the data store for saving this piece of restartable data (mesh or everything else)
2472 auto & data_map =
2473 metaname.empty() ? _restartable_data[tid] : _restartable_meta_data[metaname].first;
2474
2475 RestartableDataValue * stored_data = data_map.findData(data->name());
2476 if (stored_data)
2477 {
2478 if (data->typeId() != stored_data->typeId())
2479 mooseError("Type mismatch found in RestartableData registration of '",
2480 data->name(),
2481 "'\n\n Stored type: ",
2482 stored_data->type(),
2483 "\n New type: ",
2484 data->type());
2485 }
2486 else
2487 stored_data = &data_map.addData(std::move(data));
2488
2489 if (!read_only)
2490 stored_data->setDeclared({});
2491
2492 return *stored_data;
2493}
2494
2496MooseApp::registerRestartableData(const std::string & libmesh_dbg_var(name),
2497 std::unique_ptr<RestartableDataValue> data,
2498 THREAD_ID tid,
2499 bool read_only,
2500 const RestartableDataMapName & metaname)
2501{
2502 mooseDeprecated("The use of MooseApp::registerRestartableData with a data name is "
2503 "deprecated.\n\nUse the call without a name instead.");
2504
2505 mooseAssert(name == data->name(), "Inconsistent name");
2506 return registerRestartableData(std::move(data), tid, read_only, metaname);
2507}
2508
2509bool
2510MooseApp::hasRestartableMetaData(const std::string & name,
2511 const RestartableDataMapName & metaname) const
2512{
2513 auto it = _restartable_meta_data.find(metaname);
2514 if (it == _restartable_meta_data.end())
2515 return false;
2516 return it->second.first.hasData(name);
2517}
2518
2520MooseApp::getRestartableMetaData(const std::string & name,
2521 const RestartableDataMapName & metaname,
2522 THREAD_ID tid)
2523{
2524 if (tid != 0)
2525 mooseError(
2526 "The meta data storage for '", metaname, "' is not threaded, so the tid must be zero.");
2527
2528 // Get metadata reference from RestartableDataMap and return a (non-const) reference to its value
2529 auto & restartable_data_map = getRestartableDataMap(metaname);
2530 RestartableDataValue * const data = restartable_data_map.findData(name);
2531 if (!data)
2532 mooseError("Unable to find RestartableDataValue object with name " + name +
2533 " in RestartableDataMap");
2534
2535 return *data;
2536}
2537
2538void
2540 const std::filesystem::path & folder_base)
2541{
2542 const auto & map_name = getRestartableDataMapName(name);
2543 const auto meta_data_folder_base = metaDataFolderBase(folder_base, map_name);
2544 if (RestartableDataReader::isAvailable(meta_data_folder_base))
2545 {
2548 reader.setInput(meta_data_folder_base);
2549 reader.restore();
2550 }
2551}
2552
2553void
2554MooseApp::loadRestartableMetaData(const std::filesystem::path & folder_base)
2555{
2556 for (const auto & name_map_pair : _restartable_meta_data)
2557 possiblyLoadRestartableMetaData(name_map_pair.first, folder_base);
2558}
2559
2560std::vector<std::filesystem::path>
2562 const std::filesystem::path & folder_base)
2563{
2564 if (processor_id() != 0)
2565 mooseError("MooseApp::writeRestartableMetaData(): Should only run on processor 0");
2566
2567 const auto & map_name = getRestartableDataMapName(name);
2568 const auto meta_data_folder_base = metaDataFolderBase(folder_base, map_name);
2569
2571 return writer.write(meta_data_folder_base);
2572}
2573
2574std::vector<std::filesystem::path>
2575MooseApp::writeRestartableMetaData(const std::filesystem::path & folder_base)
2576{
2577 std::vector<std::filesystem::path> paths;
2578
2579 if (processor_id() == 0)
2580 for (const auto & name_map_pair : _restartable_meta_data)
2581 {
2582 const auto map_paths = writeRestartableMetaData(name_map_pair.first, folder_base);
2583 paths.insert(paths.end(), map_paths.begin(), map_paths.end());
2584 }
2585
2586 return paths;
2587}
2588
2589void
2590MooseApp::dynamicAppRegistration(const std::string & app_name,
2591 std::string library_path,
2592 const std::string & library_name,
2593 bool lib_load_deps)
2594{
2595#ifdef LIBMESH_HAVE_DLOPEN
2596 libMesh::Parameters params;
2597 params.set<std::string>("app_name") = app_name;
2598 params.set<RegistrationType>("reg_type") = APPLICATION;
2599 params.set<std::string>("registration_method") = app_name + "__registerApps";
2600 params.set<std::string>("library_path") = library_path;
2601
2602 const auto effective_library_name =
2603 library_name.empty() ? appNameToLibName(app_name) : library_name;
2604 params.set<std::string>("library_name") = effective_library_name;
2605 params.set<bool>("library_load_dependencies") = lib_load_deps;
2606
2607 const auto paths = getLibrarySearchPaths(library_path);
2608 std::ostringstream oss;
2609
2610 auto successfully_loaded = false;
2611 if (paths.empty())
2612 oss << '"' << app_name << "\" is not a registered application name.\n"
2613 << "No search paths were set. We made no attempts to locate the corresponding library "
2614 "file.\n";
2615 else
2616 {
2617 dynamicRegistration(params);
2618
2619 // At this point the application should be registered so check it
2620 if (!AppFactory::instance().isRegistered(app_name))
2621 {
2622 oss << '"' << app_name << "\" is not a registered application name.\n"
2623 << "Unable to locate library archive for \"" << app_name
2624 << "\".\nWe attempted to locate the library archive \"" << effective_library_name
2625 << "\" in the following paths:\n\t";
2626 std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
2627 }
2628 else
2629 successfully_loaded = true;
2630 }
2631
2632 if (!successfully_loaded)
2633 {
2634 oss << "\nMake sure you have compiled the library and either set the \"library_path\" "
2635 "variable in your input file or exported \"MOOSE_LIBRARY_PATH\".\n";
2636
2637 mooseError(oss.str());
2638 }
2639
2640#else
2641 libmesh_ignore(app_name, library_path, library_name, lib_load_deps);
2642 mooseError("Dynamic Loading is either not supported or was not detected by libMesh configure.");
2643#endif
2644}
2645
2646void
2647MooseApp::dynamicAllRegistration(const std::string & app_name,
2648 Factory * factory,
2649 ActionFactory * action_factory,
2650 Syntax * syntax,
2651 std::string library_path,
2652 const std::string & library_name)
2653{
2654#ifdef LIBMESH_HAVE_DLOPEN
2655 libMesh::Parameters params;
2656 params.set<std::string>("app_name") = app_name;
2657 params.set<RegistrationType>("reg_type") = REGALL;
2658 params.set<std::string>("registration_method") = app_name + "__registerAll";
2659 params.set<std::string>("library_path") = library_path;
2660 params.set<std::string>("library_name") =
2661 library_name.empty() ? appNameToLibName(app_name) : library_name;
2662
2663 params.set<Factory *>("factory") = factory;
2664 params.set<Syntax *>("syntax") = syntax;
2665 params.set<ActionFactory *>("action_factory") = action_factory;
2666 params.set<bool>("library_load_dependencies") = false;
2667
2668 dynamicRegistration(params);
2669#else
2670 libmesh_ignore(app_name, factory, action_factory, syntax, library_path, library_name);
2671 mooseError("Dynamic Loading is either not supported or was not detected by libMesh configure.");
2672#endif
2673}
2674
2675void
2677{
2678 const auto paths = getLibrarySearchPaths(params.get<std::string>("library_path"));
2679 const auto library_name = params.get<std::string>("library_name");
2680
2681 // Attempt to dynamically load the library
2682 for (const auto & path : paths)
2683 if (MooseUtils::checkFileReadable(path + '/' + library_name, false, false))
2685 path + '/' + library_name, params, params.get<bool>("library_load_dependencies"));
2686}
2687
2688void
2689MooseApp::loadLibraryAndDependencies(const std::string & library_filename,
2690 const libMesh::Parameters & params,
2691 const bool load_dependencies)
2692{
2693 std::string line;
2694 std::string dl_lib_filename;
2695
2696 // This RE looks for absolute path libtool filenames (i.e. begins with a slash and ends with a
2697 // .la)
2698 pcrecpp::RE re_deps("(/\\S*\\.la)");
2699
2700 std::ifstream la_handle(library_filename.c_str());
2701 if (la_handle.is_open())
2702 {
2703 while (std::getline(la_handle, line))
2704 {
2705 // Look for the system dependent dynamic library filename to open
2706 if (line.find("dlname=") != std::string::npos)
2707 // Magic numbers are computed from length of this string "dlname=' and line minus that
2708 // string plus quotes"
2709 dl_lib_filename = line.substr(8, line.size() - 9);
2710
2711 if (line.find("dependency_libs=") != std::string::npos)
2712 {
2713 if (load_dependencies)
2714 {
2715 pcrecpp::StringPiece input(line);
2716 pcrecpp::StringPiece depend_library;
2717 while (re_deps.FindAndConsume(&input, &depend_library))
2718 // Recurse here to load dependent libraries in depth-first order
2719 loadLibraryAndDependencies(depend_library.as_string(), params, load_dependencies);
2720 }
2721
2722 // There's only one line in the .la file containing the dependency libs so break after
2723 // finding it
2724 break;
2725 }
2726 }
2727 la_handle.close();
2728 }
2729
2730 // This should only occur if we have static linkage.
2731 if (dl_lib_filename.empty())
2732 return;
2733
2734 const auto & [dir, file_name] = MooseUtils::splitFileName(library_filename);
2735
2736 // Time to load the library, First see if we've already loaded this particular dynamic library
2737 // 1) make sure we haven't already loaded this library
2738 // AND 2) make sure we have a library name (we won't for static linkage)
2739 // Note: Here was are going to assume uniqueness based on the filename alone. This has significant
2740 // implications for applications that have "diamond" inheritance of libraries (usually
2741 // modules). We will only load one of those libraries, versions be damned.
2742 auto dyn_lib_it = _lib_handles.find(file_name);
2743 if (dyn_lib_it == _lib_handles.end())
2744 {
2745 // Assemble the actual filename using the base path of the *.la file and the dl_lib_filename
2746 const auto dl_lib_full_path = MooseUtils::pathjoin(dir, dl_lib_filename);
2747
2748 MooseUtils::checkFileReadable(dl_lib_full_path, false, /*throw_on_unreadable=*/true);
2749
2750#ifdef LIBMESH_HAVE_DLOPEN
2751 void * const lib_handle = dlopen(dl_lib_full_path.c_str(), RTLD_LAZY);
2752#else
2753 void * const lib_handle = nullptr;
2754#endif
2755
2756 if (!lib_handle)
2757 mooseError("The library file \"",
2758 dl_lib_full_path,
2759 "\" exists and has proper permissions, but cannot by dynamically loaded.\nThis "
2760 "generally means that the loader was unable to load one or more of the "
2761 "dependencies listed in the supplied library (see otool or ldd).\n",
2762 dlerror());
2763
2764 DynamicLibraryInfo lib_info;
2765 lib_info.library_handle = lib_handle;
2766 lib_info.full_path = library_filename;
2767
2768 auto insert_ret = _lib_handles.insert(std::make_pair(file_name, lib_info));
2769 mooseAssert(insert_ret.second == true, "Error inserting into lib_handles map");
2770
2771 dyn_lib_it = insert_ret.first;
2772 }
2773
2774 // Library has been loaded, check to see if we've called the requested registration method
2775 const auto registration_method = params.get<std::string>("registration_method");
2776 auto & entry_sym_from_curr_lib = dyn_lib_it->second.entry_symbols;
2777
2778 if (entry_sym_from_curr_lib.find(registration_method) == entry_sym_from_curr_lib.end())
2779 {
2780 // get the pointer to the method in the library. The dlsym()
2781 // function returns a null pointer if the symbol cannot be found,
2782 // we also explicitly set the pointer to NULL if dlsym is not
2783 // available.
2784#ifdef LIBMESH_HAVE_DLOPEN
2785 void * registration_handle =
2786 dlsym(dyn_lib_it->second.library_handle, registration_method.c_str());
2787#else
2788 void * registration_handle = nullptr;
2789#endif
2790
2791 if (registration_handle)
2792 {
2793 switch (params.get<RegistrationType>("reg_type"))
2794 {
2795 case APPLICATION:
2796 {
2797 using register_app_t = void (*)();
2798 register_app_t * const reg_ptr = reinterpret_cast<register_app_t *>(&registration_handle);
2799 (*reg_ptr)();
2800 break;
2801 }
2802 case REGALL:
2803 {
2804 using register_app_t = void (*)(Factory *, ActionFactory *, Syntax *);
2805 register_app_t * const reg_ptr = reinterpret_cast<register_app_t *>(&registration_handle);
2806 (*reg_ptr)(params.get<Factory *>("factory"),
2807 params.get<ActionFactory *>("action_factory"),
2808 params.get<Syntax *>("syntax"));
2809 break;
2810 }
2811 default:
2812 mooseError("Unhandled RegistrationType");
2813 }
2814
2815 entry_sym_from_curr_lib.insert(registration_method);
2816 }
2817 else
2818 {
2819
2820#if defined(DEBUG) && defined(LIBMESH_HAVE_DLOPEN)
2821 // We found a dynamic library that doesn't have a dynamic
2822 // registration method in it. This shouldn't be an error, so
2823 // we'll just move on.
2824 if (!registration_handle)
2825 mooseWarning("Unable to find extern \"C\" method \"",
2826 registration_method,
2827 "\" in library: ",
2828 dyn_lib_it->first,
2829 ".\n",
2830 "This doesn't necessarily indicate an error condition unless you believe that "
2831 "the method should exist in that library.\n",
2832 dlerror());
2833#endif
2834 }
2835 }
2836}
2837
2838std::set<std::string>
2840{
2841 // Return the paths but not the open file handles
2842 std::set<std::string> paths;
2843 for (const auto & it : _lib_handles)
2844 paths.insert(it.first);
2845
2846 return paths;
2847}
2848
2849std::set<std::string>
2850MooseApp::getLibrarySearchPaths(const std::string & library_path) const
2851{
2852 std::set<std::string> paths;
2853
2854 if (!library_path.empty())
2855 {
2856 std::vector<std::string> tmp_paths;
2857 MooseUtils::tokenize(library_path, tmp_paths, 1, ":");
2858
2859 paths.insert(tmp_paths.begin(), tmp_paths.end());
2860 }
2861
2862 char * moose_lib_path_env = std::getenv("MOOSE_LIBRARY_PATH");
2863 if (moose_lib_path_env)
2864 {
2865 std::string moose_lib_path(moose_lib_path_env);
2866 std::vector<std::string> tmp_paths;
2867 MooseUtils::tokenize(moose_lib_path, tmp_paths, 1, ":");
2868
2869 paths.insert(tmp_paths.begin(), tmp_paths.end());
2870 }
2871
2872 return paths;
2873}
2874
2880
2881std::string
2883{
2884 return std::string("");
2885}
2886
2887void
2889{
2890 _restart = value;
2891}
2892
2893void
2895{
2896 _recover = value;
2897}
2898
2899void
2901{
2902 TIME_SECTION("createMinimalApp", 3, "Creating Minimal App");
2903
2904 // SetupMeshAction
2905 {
2906 // Build the Action parameters
2907 InputParameters action_params = _action_factory.getValidParams("SetupMeshAction");
2908 action_params.set<std::string>("type") = "GeneratedMesh";
2909
2910 // Create The Action
2911 std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
2912 _action_factory.create("SetupMeshAction", "Mesh", action_params));
2913
2914 // Set the object parameters
2915 InputParameters & params = action->getObjectParams();
2916 params.set<MooseEnum>("dim") = "1";
2917 params.set<unsigned int>("nx") = 1;
2918
2919 // Add Action to the warehouse
2921 }
2922
2923 // Executioner
2924 {
2925 // Build the Action parameters
2926 InputParameters action_params = _action_factory.getValidParams("CreateExecutionerAction");
2927 action_params.set<std::string>("type") = "Transient";
2928
2929 // Create the action
2930 std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
2931 _action_factory.create("CreateExecutionerAction", "Executioner", action_params));
2932
2933 // Set the object parameters
2934 InputParameters & params = action->getObjectParams();
2935 params.set<unsigned int>("num_steps") = 1;
2936 params.set<Real>("dt") = 1;
2937
2938 // Add Action to the warehouse
2940 }
2941
2942 // Problem
2943 {
2944 // Build the Action parameters
2945 InputParameters action_params = _action_factory.getValidParams("CreateProblemDefaultAction");
2946 action_params.set<bool>("_solve") = false;
2947
2948 // Create the action
2949 std::shared_ptr<Action> action = std::static_pointer_cast<Action>(
2950 _action_factory.create("CreateProblemDefaultAction", "Problem", action_params));
2951
2952 // Add Action to the warehouse
2954 }
2955
2956 // Outputs
2957 {
2958 // Build the Action parameters
2959 InputParameters action_params = _action_factory.getValidParams("CommonOutputAction");
2960 action_params.set<bool>("console") = false;
2961
2962 // Create action
2963 std::shared_ptr<Action> action =
2964 _action_factory.create("CommonOutputAction", "Outputs", action_params);
2965
2966 // Add Action to the warehouse
2968 }
2969
2971}
2972
2973bool
2974MooseApp::hasRelationshipManager(const std::string & name) const
2975{
2976 return std::find_if(_relationship_managers.begin(),
2978 [&name](const std::shared_ptr<RelationshipManager> & rm)
2979 { return rm->name() == name; }) != _relationship_managers.end();
2980}
2981
2982namespace
2983{
2984void
2985donateForWhom(const RelationshipManager & donor, RelationshipManager & acceptor)
2986{
2987 auto & existing_for_whom = acceptor.forWhom();
2988
2989 // Take all the for_whoms from the donor, and give them to the acceptor
2990 for (auto & fw : donor.forWhom())
2991 {
2992 if (std::find(existing_for_whom.begin(), existing_for_whom.end(), fw) ==
2993 existing_for_whom.end())
2994 acceptor.addForWhom(fw);
2995 }
2996}
2997}
2998
2999bool
3000MooseApp::addRelationshipManager(std::shared_ptr<RelationshipManager> new_rm)
3001{
3002 // We prefer to always add geometric RMs. There is no hurt to add RMs for replicated mesh
3003 // since MeshBase::delete_remote_elements{} is a no-op (empty) for replicated mesh.
3004 // The motivation here is that MooseMesh::_use_distributed_mesh may not be properly set
3005 // at the time we are adding geometric relationship managers. We deleted the following
3006 // old logic to add all geometric RMs regardless of there is a distributed mesh or not.
3007 // Otherwise, all geometric RMs will be improperly ignored for a distributed mesh generator.
3008
3009 // if (!_action_warehouse.mesh()->isDistributedMesh() && !_split_mesh &&
3010 // (relationship_manager->isType(Moose::RelationshipManagerType::GEOMETRIC) &&
3011 // !(relationship_manager->isType(Moose::RelationshipManagerType::ALGEBRAIC) ||
3012 // relationship_manager->isType(Moose::RelationshipManagerType::COUPLING))))
3013 // return false;
3014
3015 bool add = true;
3016
3017 std::set<std::shared_ptr<RelationshipManager>> rms_to_erase;
3018
3019 for (const auto & existing_rm : _relationship_managers)
3020 {
3021 if (*existing_rm >= *new_rm)
3022 {
3023 add = false;
3024 donateForWhom(*new_rm, *existing_rm);
3025 break;
3026 }
3027 // The new rm did not provide less or the same amount/type of ghosting as the existing rm, but
3028 // what about the other way around?
3029 else if (*new_rm >= *existing_rm)
3030 rms_to_erase.emplace(existing_rm);
3031 }
3032
3033 if (add)
3034 {
3035 _relationship_managers.emplace(new_rm);
3036 for (const auto & rm_to_erase : rms_to_erase)
3037 {
3038 donateForWhom(*rm_to_erase, *new_rm);
3039 removeRelationshipManager(rm_to_erase);
3040 }
3041 }
3042
3043 // Inform the caller whether the object was added or not
3044 return add;
3045}
3046
3047const std::string &
3049{
3050 static const std::string suffix = "-mesh.cpa.gz";
3051 return suffix;
3052}
3053
3054std::filesystem::path
3055MooseApp::metaDataFolderBase(const std::filesystem::path & folder_base,
3056 const std::string & map_suffix)
3057{
3058 return RestartableDataIO::restartableDataFolder(folder_base /
3059 std::filesystem::path("meta_data" + map_suffix));
3060}
3061
3062std::filesystem::path
3063MooseApp::restartFolderBase(const std::filesystem::path & folder_base) const
3064{
3065 auto folder = folder_base;
3066 folder += "-restart-" + std::to_string(processor_id());
3068}
3069
3070const hit::Node *
3072{
3073 if (const auto action = _action_warehouse.getCurrentAction())
3074 return action->parameters().getHitNode();
3075 return nullptr;
3076}
3077
3078bool
3079MooseApp::hasRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const
3080{
3081 auto it = _template_to_clones.find(&template_rm);
3082 // C++ does short circuiting so we're safe here
3083 return (it != _template_to_clones.end()) && (it->second.find(&mesh) != it->second.end());
3084}
3085
3087MooseApp::getRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const
3088{
3089 auto outer_it = _template_to_clones.find(&template_rm);
3090 if (outer_it == _template_to_clones.end())
3091 mooseError("The template rm does not exist in our _template_to_clones map");
3092
3093 auto & mesh_to_clone_map = outer_it->second;
3094 auto inner_it = mesh_to_clone_map.find(&mesh);
3095 if (inner_it == mesh_to_clone_map.end())
3096 mooseError("We should have the mesh key in our mesh");
3097
3098 return *inner_it->second;
3099}
3100
3101void
3102MooseApp::removeRelationshipManager(std::shared_ptr<RelationshipManager> rm)
3103{
3104 auto * const mesh = _action_warehouse.mesh().get();
3105 if (!mesh)
3106 mooseError("The MooseMesh should exist");
3107
3108 const MeshBase * const undisp_lm_mesh = mesh->getMeshPtr();
3109 RelationshipManager * undisp_clone = nullptr;
3110 if (undisp_lm_mesh && hasRMClone(*rm, *undisp_lm_mesh))
3111 {
3112 undisp_clone = &getRMClone(*rm, *undisp_lm_mesh);
3113 const_cast<MeshBase *>(undisp_lm_mesh)->remove_ghosting_functor(*undisp_clone);
3114 }
3115
3116 auto & displaced_mesh = _action_warehouse.displacedMesh();
3117 MeshBase * const disp_lm_mesh = displaced_mesh ? &displaced_mesh->getMesh() : nullptr;
3118 RelationshipManager * disp_clone = nullptr;
3119 if (disp_lm_mesh && hasRMClone(*rm, *disp_lm_mesh))
3120 {
3121 disp_clone = &getRMClone(*rm, *disp_lm_mesh);
3122 disp_lm_mesh->remove_ghosting_functor(*disp_clone);
3123 }
3124
3125 if (_executioner)
3126 {
3127 auto & problem = feProblem();
3128 if (undisp_clone)
3129 {
3130 problem.removeAlgebraicGhostingFunctor(*undisp_clone);
3131 problem.removeCouplingGhostingFunctor(*undisp_clone);
3132 }
3133
3134 auto * dp = problem.getDisplacedProblem().get();
3135 if (dp && disp_clone)
3136 dp->removeAlgebraicGhostingFunctor(*disp_clone);
3137 }
3138
3140 _relationship_managers.erase(rm);
3141}
3142
3145 MooseMesh & moose_mesh,
3146 MeshBase & mesh,
3147 const DofMap * const dof_map)
3148{
3149 auto & mesh_to_clone = _template_to_clones[&template_rm];
3150 auto it = mesh_to_clone.find(&mesh);
3151 if (it != mesh_to_clone.end())
3152 {
3153 // We've already created a clone for this mesh
3154 auto & clone_rm = *it->second;
3155 if (!clone_rm.dofMap() && dof_map)
3156 // We didn't have a DofMap before, but now we do, so we should re-init
3157 clone_rm.init(moose_mesh, mesh, dof_map);
3158 else if (clone_rm.dofMap() && dof_map && (clone_rm.dofMap() != dof_map))
3159 mooseError("Attempting to create and initialize an existing clone with a different DofMap. "
3160 "This should not happen.");
3161
3162 return clone_rm;
3163 }
3164
3165 // It's possible that this method is going to get called for multiple different MeshBase
3166 // objects. If that happens, then we *cannot* risk having a MeshBase object with a ghosting
3167 // functor that is init'd with another MeshBase object. So the safe thing to do is to make a
3168 // different RM for every MeshBase object that gets called here. Then the
3169 // RelationshipManagers stored here in MooseApp are serving as a template only
3170 auto pr = mesh_to_clone.emplace(
3171 std::make_pair(&const_cast<const MeshBase &>(mesh),
3172 dynamic_pointer_cast<RelationshipManager>(template_rm.clone())));
3173 mooseAssert(pr.second, "An insertion should have happened");
3174 auto & clone_rm = *pr.first->second;
3175 clone_rm.init(moose_mesh, mesh, dof_map);
3176 return clone_rm;
3177}
3178
3179void
3181{
3182 for (auto & rm : _relationship_managers)
3183 {
3185 {
3186 if (rm->attachGeometricEarly())
3187 {
3188 mesh.add_ghosting_functor(createRMFromTemplateAndInit(*rm, moose_mesh, mesh));
3190 }
3191 else
3192 {
3193 // If we have a geometric ghosting functor that can't be attached early, then we have to
3194 // prevent the mesh from deleting remote elements
3195 moose_mesh.allowRemoteElementRemoval(false);
3196
3197 if (const MeshBase * const moose_mesh_base = moose_mesh.getMeshPtr())
3198 {
3199 if (moose_mesh_base != &mesh)
3200 mooseError("The MooseMesh MeshBase and the MeshBase we're trying to attach "
3201 "relationship managers to are different");
3202 }
3203 else
3204 // The MeshBase isn't attached to the MooseMesh yet, so have to tell it not to remove
3205 // remote elements independently
3206 mesh.allow_remote_element_removal(false);
3207 }
3208 }
3209 }
3210}
3211
3212void
3214 bool attach_geometric_rm_final)
3215{
3216 for (auto & rm : _relationship_managers)
3217 {
3218 if (!rm->isType(rm_type))
3219 continue;
3220
3221 // RM is already attached (this also handles the geometric early case)
3222 if (_attached_relationship_managers[rm_type].count(rm.get()))
3223 continue;
3224
3226 {
3227 // The problem is not built yet - so the ActionWarehouse currently owns the mesh
3228 MooseMesh * const mesh = _action_warehouse.mesh().get();
3229
3230 // "attach_geometric_rm_final = true" inidicate that it is the last chance to attach
3231 // geometric RMs. Therefore, we need to attach them.
3232 if (!rm->attachGeometricEarly() && !attach_geometric_rm_final)
3233 // Will attach them later (during algebraic). But also, we need to tell the mesh that we
3234 // shouldn't be deleting remote elements yet
3235 mesh->allowRemoteElementRemoval(false);
3236 else
3237 {
3238 MeshBase & undisp_mesh_base = mesh->getMesh();
3239 const DofMap * const undisp_sys_dof_map =
3240 _executioner ? &feProblem().getSolverSystem(0).dofMap() : nullptr;
3241 undisp_mesh_base.add_ghosting_functor(
3242 createRMFromTemplateAndInit(*rm, *mesh, undisp_mesh_base, undisp_sys_dof_map));
3243
3244 // In the final stage, if there is a displaced mesh, we need to
3245 // clone ghosting functors for displacedMesh
3246 if (auto & disp_moose_mesh = _action_warehouse.displacedMesh();
3247 attach_geometric_rm_final && disp_moose_mesh)
3248 {
3249 MeshBase & disp_mesh_base = _action_warehouse.displacedMesh()->getMesh();
3250 const DofMap * disp_sys_dof_map = nullptr;
3252 disp_sys_dof_map = &feProblem().getDisplacedProblem()->solverSys(0).dofMap();
3253 disp_mesh_base.add_ghosting_functor(
3254 createRMFromTemplateAndInit(*rm, *disp_moose_mesh, disp_mesh_base, disp_sys_dof_map));
3255 }
3257 mooseError("The displaced mesh should not yet exist at the time that we are attaching "
3258 "early geometric relationship managers.");
3259
3260 // Mark this RM as attached
3261 mooseAssert(!_attached_relationship_managers[rm_type].count(rm.get()), "Already attached");
3262 _attached_relationship_managers[rm_type].insert(rm.get());
3263 }
3264 }
3265 else // rm_type is algebraic or coupling
3266 {
3267 if (!_executioner && !_executor)
3268 mooseError("We must have an executioner by now or else we do not have to data to add "
3269 "algebraic or coupling functors to in MooseApp::attachRelationshipManagers");
3270
3271 // Now we've built the problem, so we can use it
3272 auto & problem = feProblem();
3273 auto & undisp_moose_mesh = problem.mesh();
3274 auto & undisp_sys = feProblem().getSolverSystem(0);
3275 auto & undisp_sys_dof_map = undisp_sys.dofMap();
3276 auto & undisp_mesh = undisp_moose_mesh.getMesh();
3277
3278 if (rm->useDisplacedMesh() && problem.getDisplacedProblem())
3279 {
3281 // We actually need to add this to the FEProblemBase NonlinearSystemBase's DofMap
3282 // because the DisplacedProblem "nonlinear" DisplacedSystem doesn't have any matrices
3283 // for which to do coupling. It's actually horrifying to me that we are adding a
3284 // coupling functor, that is going to determine its couplings based on a displaced
3285 // MeshBase object, to a System associated with the undisplaced MeshBase object (there
3286 // is only ever one EquationSystems object per MeshBase object and visa versa). So here
3287 // I'm left with the choice of whether to pass in a MeshBase object that is *not* the
3288 // MeshBase object that will actually determine the couplings or to pass in the MeshBase
3289 // object that is inconsistent with the System DofMap that we are adding the coupling
3290 // functor for! Let's err on the side of *libMesh* consistency and pass properly paired
3291 // MeshBase-DofMap
3292 problem.addCouplingGhostingFunctor(
3293 createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
3294 /*to_mesh = */ false);
3295
3297 {
3298 auto & displaced_problem = *problem.getDisplacedProblem();
3299 auto & disp_moose_mesh = displaced_problem.mesh();
3300 auto & disp_mesh = disp_moose_mesh.getMesh();
3301 const DofMap * const disp_nl_dof_map = &displaced_problem.solverSys(0).dofMap();
3302 displaced_problem.addAlgebraicGhostingFunctor(
3303 createRMFromTemplateAndInit(*rm, disp_moose_mesh, disp_mesh, disp_nl_dof_map),
3304 /*to_mesh = */ false);
3305 }
3306 }
3307 else // undisplaced
3308 {
3310 problem.addCouplingGhostingFunctor(
3311 createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
3312 /*to_mesh = */ false);
3313
3315 problem.addAlgebraicGhostingFunctor(
3316 createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
3317 /*to_mesh = */ false);
3318 }
3319
3320 // Mark this RM as attached
3321 mooseAssert(!_attached_relationship_managers[rm_type].count(rm.get()), "Already attached");
3322 _attached_relationship_managers[rm_type].insert(rm.get());
3323 }
3324 }
3325}
3326
3327std::vector<std::pair<std::string, std::string>>
3329{
3330 std::vector<std::pair<std::string, std::string>> info_strings;
3331 info_strings.reserve(_relationship_managers.size());
3332
3333 for (const auto & rm : _relationship_managers)
3334 {
3335 std::stringstream oss;
3336 oss << rm->getInfo();
3337
3338 auto & for_whom = rm->forWhom();
3339
3340 if (!for_whom.empty())
3341 {
3342 oss << " for ";
3343
3344 std::copy(for_whom.begin(), for_whom.end(), infix_ostream_iterator<std::string>(oss, ", "));
3345 }
3346
3347 info_strings.emplace_back(std::make_pair(Moose::stringify(rm->getType()), oss.str()));
3348 }
3349
3350 // List the libMesh GhostingFunctors - Not that in libMesh all of the algebraic and coupling
3351 // Ghosting Functors are also attached to the mesh. This should catch them all.
3352 const auto & mesh = _action_warehouse.getMesh();
3353 if (mesh)
3354 {
3355 // Let us use an ordered map to avoid stochastic console behaviors.
3356 // I believe we won't have many RMs, and there is no performance issue.
3357 // Deterministic behaviors are good for setting up regression tests
3358 std::map<std::string, unsigned int> counts;
3359
3360 for (auto & gf : as_range(mesh->getMesh().ghosting_functors_begin(),
3361 mesh->getMesh().ghosting_functors_end()))
3362 {
3363 const auto * gf_ptr = dynamic_cast<const RelationshipManager *>(gf);
3364 if (!gf_ptr)
3365 // Count how many occurences of the same Ghosting Functor types we are encountering
3366 counts[demangle(typeid(*gf).name())]++;
3367 }
3368
3369 for (const auto & pair : counts)
3370 info_strings.emplace_back(std::make_pair(
3371 "Default", pair.first + (pair.second > 1 ? " x " + std::to_string(pair.second) : "")));
3372 }
3373
3374 // List the libMesh GhostingFunctors - Not that in libMesh all of the algebraic and coupling
3375 // Ghosting Functors are also attached to the mesh. This should catch them all.
3376 const auto & d_mesh = _action_warehouse.getDisplacedMesh();
3377 if (d_mesh)
3378 {
3379 // Let us use an ordered map to avoid stochastic console behaviors.
3380 // I believe we won't have many RMs, and there is no performance issue.
3381 // Deterministic behaviors are good for setting up regression tests
3382 std::map<std::string, unsigned int> counts;
3383
3384 for (auto & gf : as_range(d_mesh->getMesh().ghosting_functors_begin(),
3385 d_mesh->getMesh().ghosting_functors_end()))
3386 {
3387 const auto * gf_ptr = dynamic_cast<const RelationshipManager *>(gf);
3388 if (!gf_ptr)
3389 // Count how many occurences of the same Ghosting Functor types we are encountering
3390 counts[demangle(typeid(*gf).name())]++;
3391 }
3392
3393 for (const auto & pair : counts)
3394 info_strings.emplace_back(
3395 std::make_pair("Default",
3396 pair.first + (pair.second > 1 ? " x " + std::to_string(pair.second) : "") +
3397 " for DisplacedMesh"));
3398 }
3399
3400 return info_strings;
3401}
3402
3403void
3405{
3406 for (auto map_iter = _restartable_meta_data.begin(); map_iter != _restartable_meta_data.end();
3407 ++map_iter)
3408 {
3409 const RestartableDataMapName & name = map_iter->first;
3410 const RestartableDataMap & meta_data = map_iter->second.first;
3411
3412 std::vector<std::string> not_declared;
3413
3414 for (const auto & data : meta_data)
3415 if (!data.declared())
3416 not_declared.push_back(data.name());
3417
3418 if (!not_declared.empty())
3419 {
3420 std::ostringstream oss;
3421 std::copy(
3422 not_declared.begin(), not_declared.end(), infix_ostream_iterator<std::string>(oss, ", "));
3423
3424 mooseError("The following '",
3425 name,
3426 "' meta-data properties were retrieved but never declared: ",
3427 oss.str());
3428 }
3429 }
3430}
3431
3434
3437{
3438 auto iter = _restartable_meta_data.find(name);
3439 if (iter == _restartable_meta_data.end())
3440 mooseError("Unable to find RestartableDataMap object for the supplied name '",
3441 name,
3442 "', did you call registerRestartableDataMapName in the application constructor?");
3443 return iter->second.first;
3444}
3445
3446bool
3448{
3449 return _restartable_meta_data.count(name);
3450}
3451
3452void
3454{
3455 if (!suffix.empty())
3456 std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
3457 suffix.insert(0, "_");
3458 _restartable_meta_data.emplace(
3459 std::make_pair(name, std::make_pair(RestartableDataMap(), suffix)));
3460}
3461
3462const std::string &
3464{
3465 const auto it = _restartable_meta_data.find(name);
3466 if (it == _restartable_meta_data.end())
3467 mooseError("MooseApp::getRestartableDataMapName: The name '", name, "' is not registered");
3468 return it->second.second;
3469}
3470
3471PerfGraph &
3473{
3475
3476 auto perf_graph =
3477 std::make_unique<RestartableData<PerfGraph>>("perf_graph",
3478 this,
3479 type() + " (" + name() + ')',
3480 *this,
3481 getParam<bool>("perf_graph_live_all"),
3482 !getParam<bool>("disable_perf_graph_live"));
3483
3484 return dynamic_cast<RestartableData<PerfGraph> &>(
3485 registerRestartableData(std::move(perf_graph), 0, false))
3486 .set();
3487}
3488
3491{
3493
3494 auto solution_invalidity =
3495 std::make_unique<RestartableData<SolutionInvalidity>>("solution_invalidity", nullptr, *this);
3496
3497 return dynamic_cast<RestartableData<SolutionInvalidity> &>(
3498 registerRestartableData(std::move(solution_invalidity), 0, false))
3499 .set();
3500}
3501
3502bool
3504{
3505 return _action_warehouse.getCurrentTaskName() == "create_added_mesh_generators" ||
3507}
3508
3509#ifdef MOOSE_LIBTORCH_ENABLED
3510torch::DeviceType
3512{
3513 const auto pname = "--compute-device";
3514 if (device_enum == "cuda")
3515 {
3516#ifdef __linux__
3517 if (!torch::cuda::is_available())
3518 mooseError(pname, "=cuda: CUDA support is not available in the linked libtorch library");
3519 return torch::kCUDA;
3520#else
3521 mooseError(pname, "=cuda: CUDA is not supported on your platform");
3522#endif
3523 }
3524 else if (device_enum == "mps")
3525 {
3526#ifdef __APPLE__
3527 if (!torch::mps::is_available())
3528 mooseError(pname, "=mps: MPS support is not available in the linked libtorch library");
3529 return torch::kMPS;
3530#else
3531 mooseError(pname, "=mps: MPS is not supported on your platform");
3532#endif
3533 }
3534 else if (device_enum == "xpu")
3535 {
3536#ifdef MOOSE_HAVE_XPU
3537 if (!torch::xpu::is_available())
3538 mooseError(pname, "=xpu: XPU support is not available in the linked libtorch library");
3539 return torch::kXPU;
3540#else
3541 mooseError(pname, "=xpu: XPU is not supported in the current application");
3542#endif
3543 }
3544 else if (device_enum != "cpu")
3545 mooseError("The device '",
3546 device_enum,
3547 "' is not currently supported by the MOOSE libtorch integration.");
3548 return torch::kCPU;
3549}
3550#endif
3551
3552void
3553MooseApp::outputMachineReadableData(const std::string & param,
3554 const std::string & start_marker,
3555 const std::string & end_marker,
3556 const std::string & data) const
3557{
3558 // Bool parameter, just to screen
3559 if (_pars.have_parameter<bool>(param))
3560 {
3561 Moose::out << start_marker << data << end_marker << std::endl;
3562 return;
3563 }
3564
3565 // String parameter, to file
3566 const auto & filename = getParam<std::string>(param);
3567 // write to file
3568 std::ofstream out(filename.c_str());
3569 if (out.is_open())
3570 {
3571 std::ofstream out(filename.c_str());
3572 out << data << std::flush;
3573 out.close();
3574 }
3575 else
3576 mooseError("Unable to open file `", filename, "` for writing ", param, " data to it.");
3577}
3578
3580MooseApp::addBoolCapability(const std::string_view capability,
3581 const bool value,
3582 const std::string_view doc)
3583{
3584 return addCapabilityInternal(capability, value, doc);
3585}
3586
3588MooseApp::addIntCapability(const std::string_view capability,
3589 const int value,
3590 const std::string_view doc)
3591{
3592 return addCapabilityInternal(capability, value, doc);
3593}
3594
3596MooseApp::addStringCapability(const std::string_view capability,
3597 const std::string_view value,
3598 const std::string_view doc)
3599{
3600 return addCapabilityInternal(capability, std::string(value), doc);
3601}
3602
3604MooseApp::addCapability(const std::string_view capability,
3605 const Moose::Capability::Value & value,
3606 const std::string_view doc)
3607{
3608
3609 // Warn deprecation on the first time this is added so that we
3610 // don't get multiple warnings if the app is registered more
3611 // than once
3612 if (!Moose::internal::Capabilities::getCapabilities({}).query(std::string(capability)))
3613 ::mooseDeprecated("MooseApp::addCapability() is deprecated (adding capability '",
3614 capability,
3615 "'); use one of MooseApp::add[Bool,Int,String]Capability instead.");
3616
3617 return addCapabilityInternal(capability, value, doc);
3618}
3619
3620bool
3625
3626bool
3631
3632#ifdef MOOSE_MFEM_ENABLED
3633void
3634MooseApp::setMFEMDevice(const std::string & executioner_device, const bool & gpu_aware_mpi)
3635{
3636 // Static for lifetime purposes only, otherwise unneeded
3637 static mfem::Device device;
3638 // Static so multiapps can error when configured with a different device, otherwise unneeded
3639 static std::string configured_device;
3640
3641 std::string selected_device;
3642 if (isParamSetByUser("compute_device"))
3643 selected_device = static_cast<std::string>(getParam<MooseEnum>("compute_device"));
3644 else if (!executioner_device.empty())
3645 selected_device = executioner_device;
3646 else if (!mfem::Device::IsConfigured())
3647 selected_device = "cpu";
3648
3649 if (!mfem::Device::IsConfigured())
3650 {
3651 device.Configure(selected_device);
3652 device.SetGPUAwareMPI(mfem::GetEnv("MFEM_GPU_AWARE_MPI") ? true : gpu_aware_mpi);
3653 device.Print(Moose::out);
3654 configured_device = selected_device;
3655 }
3656 else if (!selected_device.empty() && selected_device != configured_device)
3657 mooseError("Attempted to configure with MFEM devices '",
3658 selected_device,
3659 "', but we have already configured the MFEM device object with the devices '",
3660 configured_device,
3661 "'");
3662}
3663#endif
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
std::string RestartableDataMapName
Definition MooseTypes.h:242
unsigned int THREAD_ID
Definition MooseTypes.h:237
unsigned int count
Definition MortarUtils.C:53
std::shared_ptr< DisplacedProblem > displaced_problem
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
std::unordered_set< std::string > DataNames
void ErrorVector unsigned int
Specialized factory for generic Action System objects.
std::shared_ptr< Action > create(const std::string &action, const std::string &action_name, InputParameters &parameters)
InputParameters getValidParams(const std::string &name)
const std::shared_ptr< MooseMesh > & getDisplacedMesh() const
void setFinalTask(const std::string &task)
std::shared_ptr< MooseMesh > & mesh()
const Action * getCurrentAction() const
void clear()
This method deletes all of the Actions in the warehouse.
const std::string & getCurrentTaskName() const
const std::shared_ptr< MooseMesh > & getMesh() const
std::vector< const T * > getActions()
Retrieve all actions in a specific type ordered by their names.
std::shared_ptr< MooseMesh > & displacedMesh()
void build()
Builds all auto-buildable tasks.
void showActions(bool state=true)
This method sets a Boolean which is used to show information about action execution of various wareho...
const std::list< Action * > & getActionListByName(const std::string &task) const
Retrieve a constant list of Action pointers associated with the passed in task.
void executeAllActions()
This method loops over all actions in the warehouse and executes them.
void addActionBlock(std::shared_ptr< Action > blk)
This method add an Action instance to the warehouse.
Base class for actions.
Definition Action.h:38
Generic AppFactory class for building Application objects.
Definition AppFactory.h:55
static AppFactory & instance()
Get the instance of the AppFactory.
Definition AppFactory.C:20
void clearAppParams(const InputParameters &params, const ClearAppParamsKey)
Clears the stored parameters for the given application parameteres.
Definition AppFactory.C:53
AttribBoundaries tracks all boundary IDs associated with an object.
Definition Attributes.h:190
Tracks whether the object is on the displaced mesh.
Definition Attributes.h:501
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition Attributes.h:346
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition Attributes.h:315
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition Attributes.h:296
Residual objects have this attribute.
Definition Attributes.h:431
This attribute describes sorting state.
Tracks the libmesh system number that a MooseObject is associated with.
Definition Attributes.h:277
This class wraps provides and tracks access to command line parameters.
Definition CommandLine.h:30
Meta-action for creating common output object parameters This action serves two purpose,...
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
Executioners are objects that do the actual work of solving your problem.
Definition Executioner.h:37
The Executor class directs the execution flow of simulations.
Definition Executor.h:27
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
ExecuteMooseObjectWarehouse< MultiApp > & getMultiAppWarehouse()
virtual MooseMesh & mesh() override
SolverSystem & getSolverSystem(unsigned int sys_num)
Get non-constant reference to a solver system.
virtual void meshChanged(bool intermediate_change, bool contract_mesh, bool clean_refinement_flags)
Update data after a mesh change.
Generic factory class for build all sorts of objects.
Definition Factory.h:29
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition Factory.C:142
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition Factory.C:68
std::vector< std::string > getConstructedObjects() const
Get a list of all constructed Moose Object types.
Definition Factory.C:269
void releaseSharedObjects(const MooseObject &moose_object, THREAD_ID tid=0)
Releases any shared resources created as a side effect of creating an object through the Factory::cre...
Definition Factory.C:156
Storage container for all InputParamter objects.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addOptionalValuedCommandLineParam(const std::string &name, const std::string &syntax, const T &value, const std::string &doc_string)
Add a command line parameter with an optional value.
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
void addCommandLineParam(const std::string &name, const std::string &syntax, const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void setGlobalCommandLineParam(const std::string &name)
Sets the command line parameter with name as global.
const InputParameters::CommandLineMetadata & getCommandLineMetadata(const std::string &name) const
This class produces produces a dump of the InputParameters that appears like the normal input file sy...
std::string toString(const nlohmann::json &root)
Returns a string representation of the tree in input file format.
Holds the syntax in a Json::Value tree.
const nlohmann::json & getRoot() const
Get the root of the tree.
static const std::string allow_data_driven_param
The name of the boolean parameter on the MooseApp that will enable data driven generation.
bool appendingMeshGenerators() const
Whether or not mesh generators are currently being appended (append_mesh_generator task)
Base class for MOOSE-based applications.
Definition MooseApp.h:110
const bool _distributed_mesh_on_command_line
This variable indicates that DistributedMesh should be used for the libMesh mesh underlying MooseMesh...
Definition MooseApp.h:1416
bool _heap_profiling
Memory profiling.
Definition MooseApp.h:1729
void loadRestartableMetaData(const std::filesystem::path &folder_base)
Loads all available restartable meta data if it is available with the folder base folder_base.
Definition MooseApp.C:2554
const bool _use_split
Whether or not we are using a (pre-)split mesh (automatically DistributedMesh)
Definition MooseApp.h:1428
const std::vector< std::string > & getInputFileNames() const
Definition MooseApp.C:1527
const MooseMesh *const _master_mesh
The mesh from master app.
Definition MooseApp.h:1697
static void addAppParam(InputParameters &params)
Definition MooseApp.C:261
processor_id_type processor_id() const
Returns the MPI processor ID of the current processor.
Definition MooseApp.h:414
void attachRelationshipManagers(Moose::RelationshipManagerType rm_type, bool attach_geometric_rm_final=false)
Attach the relationship managers of the given type Note: Geometric relationship managers that are sup...
Definition MooseApp.C:3213
bool hasRestartableDataMap(const RestartableDataMapName &name) const
Definition MooseApp.C:3447
void possiblyLoadRestartableMetaData(const RestartableDataMapName &name, const std::filesystem::path &folder_base)
Loads the restartable meta data for name if it is available with the folder base folder_base.
Definition MooseApp.C:2539
void restoreMeshFromInitialBackup(MooseMesh &mesh)
Restore mesh from this app's initial Backup object and consume the mesh checkpoint entries.
Definition MooseApp.C:1758
const std::shared_ptr< CommandLine > _command_line
The CommandLine object.
Definition MooseApp.h:1331
Syntax & syntax()
Returns a writable reference to the syntax object.
Definition MooseApp.h:228
bool isSplitMesh() const
Whether or not this is a split mesh operation.
Definition MooseApp.C:1690
void requestCitations()
Handles the –citations command-line option: registers with PETSc the BibTeX entries that should be ci...
Definition MooseApp.C:2145
void registerRestartableNameWithFilter(const std::string &name, Moose::RESTARTABLE_FILTER filter)
NOTE: This is an internal function meant for MOOSE use only!
Definition MooseApp.C:1710
std::string getPrintableVersion() const
Non-virtual method for printing out the version string in a consistent format.
Definition MooseApp.C:1019
void registerRestartableDataMapName(const RestartableDataMapName &name, std::string suffix="")
Reserve a location for storing custom RestartableDataMap objects.
Definition MooseApp.C:3453
std::set< std::string > getLibrarySearchPaths(const std::string &library_path_from_param) const
Return the paths searched by MOOSE when loading libraries.
Definition MooseApp.C:2850
MeshGeneratorSystem _mesh_generator_system
The system that manages the MeshGenerators.
Definition MooseApp.h:1703
void restoreFromInitialBackup(const bool for_restart)
Restores from a "initial" backup, that is, one set in _initial_backup.
Definition MooseApp.C:1809
const DataNames & getRecoverableData() const
Return a reference to the recoverable data object.
Definition MooseApp.h:731
void queryKokkosGPUs()
Query the Kokkos GPUs in the system and check whether every process has an associated GPU.
DataNames _recoverable_data_names
Data names that will only be read from the restart file during RECOVERY.
Definition MooseApp.h:1349
void setStartTime(Real time)
Set the starting time for the simulation.
Definition MooseApp.C:2405
std::shared_ptr< Executioner > _executioner
Pointer to the executioner of this run (typically build by actions)
Definition MooseApp.h:1361
bool hasRelationshipManager(const std::string &name) const
Returns a Boolean indicating whether a RelationshipManater exists with the same name.
Definition MooseApp.C:2974
void setOutputPosition(const Point &p)
Tell the app to output in a specific position.
Definition MooseApp.C:2355
void setOutputFileBase(const std::string &output_file_base)
Override the selection of the output file base name.
Definition MooseApp.C:1550
bool hasRestartRecoverFileBase() const
Return true if the recovery file base is set.
Definition MooseApp.C:1696
static void addInputParam(InputParameters &params)
Definition MooseApp.C:268
bool forceRestart() const
Whether or not we are forcefully restarting (allowing the load of potentially incompatibie checkpoint...
Definition MooseApp.h:1118
bool _start_time_set
Whether or not an start time has been set.
Definition MooseApp.h:1303
std::set< std::shared_ptr< RelationshipManager > > _relationship_managers
The relationship managers that have been added.
Definition MooseApp.h:1451
std::vector< RestartableDataMap > _restartable_data
Where the restartable data is held (indexed on tid)
Definition MooseApp.h:1343
void dynamicAllRegistration(const std::string &app_name, Factory *factory, ActionFactory *action_factory, Syntax *syntax, std::string library_path, const std::string &library_name)
Thes methods are called to register applications or objects on demand.
Definition MooseApp.C:2647
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition MooseApp.C:3000
bool hasRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname) const
Definition MooseApp.C:2510
virtual std::string header() const
Returns a string to be printed at the beginning of a simulation.
Definition MooseApp.C:2882
@ WARN_UNUSED
Definition MooseApp.h:1395
@ ERROR_UNUSED
Definition MooseApp.h:1396
std::string getOutputFileBase(bool for_non_moose_build_output=false) const
Get the output file base name.
Definition MooseApp.C:1541
const std::shared_ptr< libMesh::Parallel::Communicator > _comm
The MPI communicator this App is going to use.
Definition MooseApp.h:1288
std::unique_ptr< TheWarehouse > _the_warehouse
The combined warehouse for storing any MooseObject based object.
Definition MooseApp.h:1685
bool hasRecoverFileBase() const
Definition MooseApp.C:1702
virtual void executeExecutioner()
Execute the Executioner that was built.
Definition MooseApp.C:1646
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
Definition MooseApp.C:2418
static std::filesystem::path metaDataFolderBase(const std::filesystem::path &folder_base, const std::string &map_suffix)
The file suffix for meta data (header and data)
Definition MooseApp.C:3055
THREAD_ID determineNumThreads() const
Determines the number of threads this application should use from the [Application] block's num_threa...
Definition MooseApp.C:635
std::map< std::string, std::shared_ptr< Executor > > _executors
Pointers to all of the Executors for this run.
Definition MooseApp.h:1367
static Moose::Capability & addBoolCapability(const std::string_view capability, const bool value, const std::string_view doc)
Register a boolean capability.
Definition MooseApp.C:3580
bool runInputs()
Handles the run input parameter logic: Checks to see whether a directory exists in user space and lau...
Definition MooseApp.C:2283
void setRestart(bool value)
Sets the restart/recover flags.
Definition MooseApp.C:2888
std::string getFileName(bool stripLeadingPath=true) const
Return the primary (first) filename that was parsed Note: When stripLeadingPath is false,...
Definition MooseApp.C:2412
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition MooseApp.C:1684
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Definition MooseApp.C:3503
void loadLibraryAndDependencies(const std::string &library_filename, const libMesh::Parameters &params, bool load_dependencies=true)
Recursively loads libraries and dependencies in the proper order to fully register a MOOSE applicatio...
Definition MooseApp.C:2689
torch::DeviceType determineLibtorchDeviceType(const MooseEnum &device) const
Function to determine the device which should be used by libtorch on this application.
Definition MooseApp.C:3511
std::unordered_map< std::string, DynamicLibraryInfo > _lib_handles
The library archive (name only), registration method and the handle to the method.
Definition MooseApp.h:1472
ActionFactory _action_factory
The Factory responsible for building Actions.
Definition MooseApp.h:1319
SolutionInvalidity & createRecoverableSolutionInvalidity()
Creates a recoverable SolutionInvalidity.
Definition MooseApp.C:3490
const std::string _type
The string representation of the type of this object as registered (see registerApp(AppName))
Definition MooseApp.h:1285
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition MooseApp.C:2024
virtual ~MooseApp()
void collectCitations(std::map< std::string, std::string > &citations) const
Collects the BibTeX citations for the modules/objects constructed in this app and the finite element ...
Definition MooseApp.C:2110
virtual void run()
Run the application.
Definition MooseApp.C:2036
Executor * getExecutor() const
Definition MooseApp.h:338
bool _output_position_set
Whether or not an output position has been set for this app.
Definition MooseApp.h:1297
std::unique_ptr< Backup > backup()
Backs up the application memory in a Backup.
Definition MooseApp.C:1736
std::map< Moose::RelationshipManagerType, std::set< const RelationshipManager * > > _attached_relationship_managers
The relationship managers that have been attached (type -> RMs)
Definition MooseApp.h:1455
Real _start_time
The time at which to start the simulation.
Definition MooseApp.h:1306
const Parser & parser() const
Definition MooseApp.C:1888
std::vector< std::pair< std::string, std::string > > getRelationshipManagerInfo() const
Returns the Relationship managers info suitable for printing.
Definition MooseApp.C:3328
bool _recover
Whether or not this is a recovery run.
Definition MooseApp.h:1419
std::unique_ptr< Backup > finalizeRestore()
Finalizes (closes) the restoration process done in restore().
Definition MooseApp.C:1816
std::unordered_map< RestartableDataMapName, std::pair< RestartableDataMap, std::string > > _restartable_meta_data
General storage for custom RestartableData that can be added to from outside applications.
Definition MooseApp.h:1675
void outputMachineReadableData(const std::string &param, const std::string &start_marker, const std::string &end_marker, const std::string &data) const
Outputs machine readable data (JSON, YAML, etc.) either to the screen (if no filename was provided as...
Definition MooseApp.C:3553
static bool isRelocated()
Definition MooseApp.C:3621
bool meshChangedForBackup() const
Whether this app requires mesh topology data in its next Backup object.
Definition MooseApp.h:764
ActionWarehouse _action_warehouse
Where built actions are stored.
Definition MooseApp.h:1322
static InputParameters validParams()
Definition MooseApp.C:275
void removeRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Purge this relationship manager from meshes and DofMaps and finally from us.
Definition MooseApp.C:3102
static const std::string & checkpointSuffix()
The file suffix for the checkpoint mesh.
Definition MooseApp.C:3048
const std::string & getRestartableDataMapName(const RestartableDataMapName &name) const
Definition MooseApp.C:3463
void addExecutor(const std::string &type, const std::string &name, const InputParameters &params)
Definition MooseApp.C:1868
void createExecutors()
After adding all of the Executor Params - this function will actually cause all of them to be built.
Definition MooseApp.C:1953
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition MooseApp.h:870
enum MooseApp::UNUSED_CHECK _enable_unused_check
bool _ready_to_exit
Definition MooseApp.h:1405
std::unique_ptr< InputParameterWarehouse > _input_parameter_warehouse
Input parameter storage structure; unique_ptr so we can control its destruction order.
Definition MooseApp.h:1316
Point _output_position
The output position.
Definition MooseApp.h:1300
OutputWarehouse _output_warehouse
OutputWarehouse object for this App.
Definition MooseApp.h:1325
std::list< std::string > getCheckpointDirectories() const
Get all checkpoint directories.
Definition MooseApp.C:2366
void createMinimalApp()
Method for creating the minimum required actions for an application (no input file)
Definition MooseApp.C:2900
bool _restored_initial_backup_mesh
Whether mesh topology has been restored from the initial Backup object.
Definition MooseApp.h:1747
bool hasInitialBackupMesh() const
Whether this app has an initial Backup object with mesh checkpoint entries.
Definition MooseApp.C:1752
virtual std::string appBinaryName() const
Definition MooseApp.h:147
Factory _factory
Definition MooseApp.h:1399
std::shared_ptr< NullExecutor > _null_executor
Used to return an executor that does nothing.
Definition MooseApp.h:1383
PerfGraph & createRecoverablePerfGraph()
Creates a recoverable PerfGraph.
Definition MooseApp.C:3472
void deallocateKokkosMemoryPool()
Deallocate Kokkos memory pool.
bool _restart
Whether or not this is a restart run.
Definition MooseApp.h:1422
void dynamicRegistration(const libMesh::Parameters &params)
Helper method for dynamic loading of objects.
Definition MooseApp.C:2676
const MooseMesh *const _master_displaced_mesh
The displaced mesh from master app.
Definition MooseApp.h:1700
std::unordered_map< std::string, std::pair< std::string, std::unique_ptr< InputParameters > > > _executor_params
Used in building the Executors Maps the name of the Executor block to the <type, params>
Definition MooseApp.h:1372
RestartableDataValue & registerRestartableData(std::unique_ptr< RestartableDataValue > data, THREAD_ID tid, bool read_only, const RestartableDataMapName &metaname="")
Definition MooseApp.C:2458
std::string _output_file_base
The output file basename.
Definition MooseApp.h:1291
const unsigned int _multiapp_level
Level of multiapp, the master is level 0. This used by the Console to indent output.
Definition MooseApp.h:1688
void checkMetaDataIntegrity() const
Function to check the integrity of the restartable meta data structure.
Definition MooseApp.C:3404
void errorCheck()
Runs post-initialization error checking that cannot be run correctly unless the simulation has been f...
Definition MooseApp.C:1610
RelationshipManager & createRMFromTemplateAndInit(const RelationshipManager &template_rm, MooseMesh &moose_mesh, MeshBase &mesh, const libMesh::DofMap *dof_map=nullptr)
Take an input relationship manager, clone it, and then initialize it with provided mesh and optional ...
Definition MooseApp.C:3144
const std::string & getLastInputFileName() const
Definition MooseApp.C:1534
Moose::Builder _builder
Builder for building app related parser tree.
Definition MooseApp.h:1337
static bool isInTree()
Definition MooseApp.C:3627
bool _cpu_profiling
CPU profiling.
Definition MooseApp.h:1726
void dynamicAppRegistration(const std::string &app_name, std::string library_path, const std::string &library_name, bool lib_load_deps)
Definition MooseApp.C:2590
FEProblemBase & feProblem() const
Definition MooseApp.C:1861
MooseApp(const InputParameters &parameters)
Constructor is protected so that this object is constructed through the AppFactory object.
Definition MooseApp.C:644
void restore(const std::filesystem::path &folder_base, const bool for_restart)
Restore an application from file.
Definition MooseApp.C:1765
virtual void preBackup()
Insertion point for other apps that is called before backup()
Definition MooseApp.h:774
virtual std::string getInstallableInputs() const
Method to retrieve the installable inputs from a given applications <app>Revision....
Definition MooseApp.C:2212
std::vector< std::filesystem::path > writeRestartableMetaData(const RestartableDataMapName &name, const std::filesystem::path &folder_base)
Writes the restartable meta data for name with a folder base of folder_base.
Definition MooseApp.C:2561
RelationshipManager & getRMClone(const RelationshipManager &template_rm, const MeshBase &mesh) const
Return the relationship manager clone originally created from the provided template relationship mana...
Definition MooseApp.C:3087
std::shared_ptr< Executor > _executor
Pointer to the Executor of this run.
Definition MooseApp.h:1364
void recursivelyCreateExecutors(const std::string &current_executor_name, std::list< std::string > &possible_roots, std::list< std::string > &current_branch)
Internal function used to recursively create the executor objects.
Definition MooseApp.C:1901
const bool _test_restep
Whether or not this simulation should fail its middle timestep and repeat (for testing)
Definition MooseApp.h:1442
void setExitCode(const int exit_code)
Sets the exit code that the application will exit with.
Definition MooseApp.h:165
bool hasRMClone(const RelationshipManager &template_rm, const MeshBase &mesh) const
Definition MooseApp.C:3079
bool _trap_fpe
Whether or not FPE trapping should be turned on.
Definition MooseApp.h:1434
void setRecover(bool value)
Definition MooseApp.C:2894
bool _error_overridden
Indicates whether warnings or errors are displayed when overridden parameters are detected.
Definition MooseApp.h:1402
std::string getFrameworkVersion() const
Returns the framework version.
Definition MooseApp.C:1007
void setMFEMDevice(const std::string &executioner_device, const bool &gpu_aware_mpi)
Create/configure the MFEM device.
Definition MooseApp.C:3634
const bool _check_input
true if we want to just check the input file
Definition MooseApp.h:1448
const bool _test_checkpoint_half_transient
Whether or not this simulation should only run half its transient (useful for testing recovery)
Definition MooseApp.h:1440
static Moose::Capability & addCapabilityInternal(const std::string_view capability, const Moose::Capability::Value &value, const std::string_view doc)
Internal method for adding a capability.
Definition MooseApp.C:2340
RestartableDataMap & getRestartableDataMap(const RestartableDataMapName &name)
Return a reference to restartable data for the specific type flag.
Definition MooseApp.C:3436
void setErrorOverridden()
Set a flag so that the parser will throw an error if overridden parameters are detected.
Definition MooseApp.C:2030
RestartableDataValue & getRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname, THREAD_ID tid)
Definition MooseApp.C:2520
bool showInputs() const
Prints a message showing the installable inputs for a given application (if getInstallableInputs has ...
Definition MooseApp.C:2180
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition MooseApp.C:1678
PerfGraph & _perf_graph
The PerfGraph object for this application (recoverable)
Definition MooseApp.h:1352
std::optional< THREAD_ID > requestedNumThreads() const
Definition MooseApp.C:621
virtual void postRestore(const bool)
Insertion point for other apps that is called after restore()
Definition MooseApp.h:808
static const std::string MESH_META_DATA_SUFFIX
Definition MooseApp.h:134
bool _file_base_set_by_user
Whether or not file base is set through input or setOutputFileBase by MultiApp.
Definition MooseApp.h:1294
virtual std::string getPrintableName() const
Get printable name of the application.
Definition MooseApp.h:145
const std::shared_ptr< Parser > _parser
Parser for parsing the input file (owns the root hit node)
Definition MooseApp.h:1328
std::string _restart_recover_base
The base name to restart/recover from. If blank then we will find the newest checkpoint file.
Definition MooseApp.h:1437
RegistrationType
Enumeration for holding the valid types of dynamic registrations allowed.
Definition MooseApp.h:1679
@ APPLICATION
Definition MooseApp.h:1680
std::string appNameToLibName(const std::string &app_name) const
Converts an application name to a library name: Examples: AnimalApp -> libanimal-oprof....
Definition MooseApp.C:2430
bool _split_mesh
Whether or not we are performing a split mesh operation (–split-mesh)
Definition MooseApp.h:1425
std::list< std::string > getCheckpointFiles() const
Extract all possible checkpoint file names.
Definition MooseApp.C:2398
int exitCode() const
Get the shell exit code for the application.
Definition MooseApp.h:160
virtual void setupOptions()
Setup options based on InputParameters.
Definition MooseApp.C:1025
static Moose::Capability & addIntCapability(const std::string_view capability, const int value, const std::string_view doc)
Register an integer capability.
Definition MooseApp.C:3588
std::streambuf * _output_buffer_cache
Cache output buffer so the language server can turn it off then back on.
Definition MooseApp.h:1720
Syntax _syntax
Syntax of the input file.
Definition MooseApp.h:1312
bool hasInitialBackup() const
Definition MooseApp.h:1051
RestartableDataReader _rd_reader
Definition MooseApp.h:1708
const hit::Node * getCurrentActionHitNode() const
Definition MooseApp.C:3071
void disableCheckUnusedFlag()
Removes warnings and error checks for unrecognized variables in the input file.
Definition MooseApp.C:1855
std::string libNameToAppName(const std::string &library_name) const
Converts a library name to an application name:
Definition MooseApp.C:2446
std::set< std::string > getLoadedLibraryPaths() const
Return the paths of loaded libraries.
Definition MooseApp.C:2839
void setCheckUnusedFlag(bool warn_is_error=false)
Set a flag so that the parser will either warn or error when unused variables are seen after parsing ...
Definition MooseApp.C:1849
std::map< const RelationshipManager *, std::map< const MeshBase *, std::unique_ptr< RelationshipManager > > > _template_to_clones
Map from a template relationship manager to a map in which the key-value pairs represent the MeshBase...
Definition MooseApp.h:1735
std::filesystem::path restartFolderBase(const std::filesystem::path &folder_base) const
The file suffix for restartable data.
Definition MooseApp.C:3063
std::unique_ptr< Backup > *const _initial_backup
The backup for use in initial setup; this will get set from the _initial_backup input parameter that ...
Definition MooseApp.h:1744
void addExecutorParams(const std::string &type, const std::string &name, const InputParameters &params)
Adds the parameters for an Executor to the list of parameters.
Definition MooseApp.C:1880
bool copyInputs()
Handles the copy_inputs input parameter logic: Checks to see whether the passed argument is valid (a ...
Definition MooseApp.C:2218
static Moose::Capability & addStringCapability(const std::string_view capability, const std::string_view value, const std::string_view doc)
Register a string capability.
Definition MooseApp.C:3596
static const RestartableDataMapName MESH_META_DATA
Definition MooseApp.h:133
virtual void runInputFile()
Actually build everything in the input file.
Definition MooseApp.C:1566
std::string _early_exit_param
Indicates if simulation is ready to exit, and keeps track of which param caused it to exit.
Definition MooseApp.h:1404
static Moose::Capability & addCapability(const std::string_view capability, const Moose::Capability::Value &value, const std::string_view doc)
Deprecated method for adding a capability.
Definition MooseApp.C:3604
virtual std::string getVersion() const
Returns the current version of the framework or application (default: framework version).
Definition MooseApp.C:1013
int _exit_code
The exit code.
Definition MooseApp.h:1407
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition MooseApp.C:2876
const bool _use_executor
Indicates whether we are operating in the new/experimental executor mode instead of using the legacy ...
Definition MooseApp.h:1380
Base class for everything in MOOSE with a name and a type.
Definition MooseBase.h:50
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
const std::string & type() const
Get the type of this class.
Definition MooseBase.h:93
static InputParameters validParams()
Definition MooseBase.C:28
void mooseDeprecated(Args &&... args) const
Emits a deprecation warning prefixed with the object name and type, and a stack trace.
Definition MooseBase.h:317
void mooseDeprecatedNoTrace(Args &&... args) const
Emits a deprecation warning prefixed with the object name and type, and no stack trace.
Definition MooseBase.h:327
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition MooseBase.h:205
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
Definition MooseBase.h:299
const InputParameters & _pars
The object's parameters.
Definition MooseBase.h:384
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition MooseBase.h:406
void mooseInfo(Args &&... args) const
Definition MooseBase.h:334
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3512
void prepare()
Calls prepare_for_use() if the underlying MeshBase object isn't prepared, then communicates various b...
Definition MooseMesh.C:399
const MeshBase * getMeshPtr() const
Definition MooseMesh.C:3506
void allowRemoteElementRemoval(bool allow_removal)
Set whether to allow remote element removal.
Definition MooseMesh.C:3999
InputParameters & getObjectParams()
Retrieve the parameters of the object to be created by this action.
const std::vector< std::shared_ptr< T > > & getObjects(THREAD_ID tid=0) const
Retrieve complete vector to the all/block/boundary restricted objects for a given thread.
Exception to be thrown whenever we have _throw_on_error set and a mooseError() is emitted.
Definition MooseError.h:118
std::string getPrimaryFileName(bool stripLeadingPath=true) const
Return the primary (first) filename that was parsed.
Definition Builder.C:179
void build()
Parse an input file (or text string if provided) consisting of hit syntax and setup objects in the MO...
Definition Builder.C:300
void buildJsonSyntaxTree(JsonSyntaxTree &tree) const
Use MOOSE Factories to construct a parameter tree for documentation or echoing input.
Definition Builder.C:417
void errorCheck(const libMesh::Parallel::Communicator &comm, bool warn_unused, bool err_unused)
Definition Builder.C:358
void initSyntaxFormatter(SyntaxFormatterType type, bool dump_mode)
Creates a syntax formatter for printing.
Definition Builder.C:400
void buildFullTree(const std::string &search_string)
Use MOOSE Factories to construct a full parse tree for documentation or echoing input.
Definition Builder.C:577
An entry for a single capability.
Definition Capability.h:30
std::variant< bool, int, std::string > Value
A capability can have a bool, int, or string value.
Definition Capability.h:33
static Capabilities & getCapabilities(const GetCapabilitiesPassKey)
Get the singleton Capabilities.
Registry of capabilities that checks capability requirements.
const Capability & get(const std::string &capability) const
Get a capability.
Class for storing and utilizing output objects.
void meshChanged()
Calls the meshChanged method for every output object.
void resetFileBase()
Resets the file base for all FileOutput objects.
Class for parsing input files.
Definition Parser.h:109
Interface for objects interacting with the PerfGraph.
The PerfGraph will hold the master list of all registered performance segments and the head PerfNode.
Definition PerfGraph.h:44
void enableLivePrint()
Enables Live Print.
Definition PerfGraph.C:58
void setActive(bool active)
Turn on or off timing.
Definition PerfGraph.h:129
void disableLivePrint()
Completely disables Live Print (cannot be restarted)
Definition PerfGraph.C:68
static const RegistryEntryBase & objData(const std::string &name)
Definition Registry.C:58
static const std::map< std::string, std::vector< std::shared_ptr< RegistryEntryBase > > > & allObjects()
Returns a per-label keyed map of all MooseObjects in the registry.
Definition Registry.h:250
static const std::map< std::string, std::vector< std::shared_ptr< RegistryEntryBase > > > & allActions()
Returns a per-label keyed map of all Actions in the registry.
Definition Registry.h:255
static bool isRegisteredObj(const std::string &name)
Definition Registry.h:265
static const std::map< std::string, std::map< std::string, std::string > > & getCitations()
Returns the registered citations, keyed by app/module name and then by BibTeX key (app/module name ->...
Definition Registry.h:291
static char addKnownLabel(const std::string &label)
addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
Definition Registry.C:85
RelationshipManagers are used for describing what kinds of non-local resources are needed for an obje...
virtual const std::vector< std::string > & forWhom() const
The object (or Action) this RelationshipManager was built for.
void addForWhom(const std::string &for_whom)
Add another name to for_whom.
void init(MooseMesh &moose_mesh, const MeshBase &mesh, const libMesh::DofMap *dof_map=nullptr)
Called before this RM is attached.
static std::filesystem::path restartableDataFolder(const std::filesystem::path &folder_base)
Storage for restartable data that is ordered based on insertion order.
Reader for restartable data written by the RestartableDataWriter.
void setErrorOnLoadWithDifferentNumberOfProcessors(bool value)
static bool isAvailable(const std::filesystem::path &folder_base)
InputStreams clear()
Clears the contents of the reader (header stream, data stream, header)
void restore(const DataNames &filter_names={})
Restores the restartable data.
void setInput(std::unique_ptr< std::stringstream > header_stream, std::unique_ptr< std::stringstream > data_stream)
Sets the input stream for reading from the stringstreams header_stream and data_stream for the header...
Abstract definition of a RestartableData value.
virtual const std::type_info & typeId() const =0
The type ID of the underlying data.
void setDeclared(const SetDeclaredKey)
Sets that this restartable value has been declared.
virtual std::string type() const =0
String identifying the type of parameter stored.
Writer for restartable data, to be read by the RestartableDataReader.
void write(std::ostream &header_stream, std::ostream &data_stream)
Writes the restartable data to header stream header_stream and data stream data_stream.
Concrete definition of a parameter value for a specified type.
A scope guard that guarantees that whatever happens between when it gets created and when it is destr...
The SolutionInvalidity will contain all the information about the occurrence(s) of solution invalidit...
Helper class that hands out input streams to a stringstream.
Holding syntax for parsing input files.
Definition Syntax.h:22
const std::multimap< std::string, ActionInfo > & getAssociatedActions() const
Return all Syntax to Action associations.
Definition Syntax.C:375
void registerTaskName(const std::string &task, bool should_auto_build=false)
Method to register a new task.
Definition Syntax.C:20
void addDependency(const std::string &task, const std::string &pre_req)
Definition Syntax.C:60
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
GCC9 currently hits a "no type named 'value_type'" error during build if this is removed and iterator...
virtual std::unique_ptr< GhostingFunctor > clone() const=0
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
T & set(const std::string &)
const T & get(std::string_view) const
query_obj query
MeshBase & mesh
std::string hostname()
Definition MooseUtils.C:687
std::string realpath(const std::string &path)
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition MooseUtils.C:122
std::string getCurrentWorkingDir()
Definition MooseUtils.C:499
std::string camelCaseToUnderscore(const std::string &camel_case_name)
Definition MooseUtils.C:631
void makedirs(const std::string &dir_name, bool throw_on_failure)
Definition MooseUtils.C:512
std::string installedInputsDir(const std::string &app_name, const std::string &dir_name, const std::string &extra_error_msg)
Definition MooseUtils.C:166
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
This function will split the passed in string on a set of delimiters appending the substrings to the ...
std::list< std::string > getFilesInDirs(const std::list< std::string > &directory_list, const bool files_only)
Definition MooseUtils.C:871
bool pathExists(const std::string &path)
Definition MooseUtils.C:310
std::string docsDir(const std::string &app_name)
Definition MooseUtils.C:188
std::string underscoreToCamelCase(const std::string &underscore_name, bool leading_upper_case)
Definition MooseUtils.C:643
bool tokenizeAndConvert(const std::string &str, std::vector< T > &tokenized_vector, const std::string &delimiter=" \t\n\v\f\r", bool throw_on_unreadable=false)
tokenizeAndConvert splits a string using delimiter and then converts to type T.
std::string findTestRoot()
Definition MooseUtils.C:138
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
Definition MooseUtils.C:317
std::string runTestsExecutable()
Definition MooseUtils.C:128
PetscErrorCode petscSetupOutput(CommandLine *cmd_line)
void registerPetscCitation(const std::string &bibtex)
Register a BibTeX entry with PETSc's citation list so that it is printed (alongside the run-specific ...
void setSinglePetscOption(const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
A wrapper function for dealing with different versions of PetscOptionsSetValue.
bool _deprecated_is_error
Variable to toggle only deprecated warnings as errors.
Definition Moose.C:925
bool _throw_on_error
Variable to turn on exceptions during mooseError(), should only be used within MOOSE unit tests or wh...
Definition Moose.C:926
std::string getExecutableName()
Gets the name of the running executable on Mac OS X and linux.
bool setColorConsole(bool use_color, bool force=false)
Turns color escape sequences on/off for info written to stdout.
Definition Moose.C:881
void registerAll(Factory &f, ActionFactory &af, Syntax &s)
Register objects that are in MOOSE.
Definition Moose.C:76
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
RelationshipManagerType
Main types of Relationship Managers.
RESTARTABLE_FILTER
The filter type applied to a particular piece of "restartable" data.
Definition MooseTypes.h:846
bool _warnings_are_errors
Variable to toggle any warning into an error (includes deprecated code warnings)
Definition Moose.C:924
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const unsigned int invalid_uint
OStreamProxy err(std::cerr)
void add_command_line_name(const std::string &name)
T command_line_value(const std::string &, T)
unsigned int n_threads()
Helper class to hold streams for Backup and Restore operations.
Definition Backup.h:26
std::vector< std::pair< std::string, std::string > > mesh_files
Pairs of checkpoint-relative entry names and binary payloads.
Definition Backup.h:32
std::vector< std::string > switches
The switches for the parameter (i.e., [-t, –timing])