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