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