https://mooseframework.inl.gov
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"
38 #include "JsonInputFileFormatter.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"
53 #include "RestartableDataWriter.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 
94 using namespace libMesh;
95 
96 namespace
97 {
109 std::filesystem::path
110 temporaryBackupMeshPath(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 
148 std::string
149 readBackupMeshFile(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 
160 void
161 writeBackupMeshFile(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 
179 void
180 packMeshBackup(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 
218 bool
219 restoreMeshBackup(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 
263 void
265 {
266  params.addCommandLineParam<std::string>(
267  "app_to_run", "--app <type>", "Specify the application type to run (case-sensitive)");
268 }
269 
270 void
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);
283  MooseApp::addInputParam(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(
713  mooseDeprecatedNoTrace(type(),
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<AttribVar>("variable", -1);
847  _the_warehouse->registerAttribute<AttribInterfaces>("interfaces", 0);
848  _the_warehouse->registerAttribute<AttribSysNum>("sys_num", libMesh::invalid_uint);
849  _the_warehouse->registerAttribute<AttribResidualObject>("residual_object");
850  _the_warehouse->registerAttribute<AttribSorted>("sorted");
851  _the_warehouse->registerAttribute<AttribDisplaced>("displaced", -1);
852 
853  _perf_graph.enableLivePrint();
854 
855  if (_check_input && isParamSetByUser("recover"))
856  mooseError("Cannot run --check-input with --recover. Recover files might not exist");
857 
858  if (isParamSetByUser("start_in_debugger") && isUltimateMaster())
859  {
860  auto command = getParam<std::string>("start_in_debugger");
861 
862  Moose::out << "Starting in debugger using: " << command << std::endl;
863 
865 
866  std::stringstream command_stream;
867 
868  // This will start XTerm and print out some info first... then run the debugger
869  command_stream << "xterm -e \"echo 'Rank: " << processor_id() << " Hostname: " << hostname
870  << " PID: " << getpid() << "'; echo ''; ";
871 
872  // Figure out how to run the debugger
873  if (command.find("lldb") != std::string::npos || command.find("gdb") != std::string::npos)
874  command_stream << command << " -p " << getpid();
875  else
876  mooseError("Unknown debugger: ",
877  command,
878  "\nIf this is truly what you meant then contact moose-users to have a discussion "
879  "about adding your debugger.");
880 
881  // Finish up the command
882  command_stream << "\"" << " & ";
883  std::string command_string = command_stream.str();
884  Moose::out << "Running: " << command_string << std::endl;
885 
886  int ret = std::system(command_string.c_str());
887  libmesh_ignore(ret);
888 
889  // Sleep to allow time for the debugger to attach
890  std::this_thread::sleep_for(std::chrono::seconds(10));
891  }
892 
893  if (isParamSetByUser("stop_for_debugger") && isUltimateMaster())
894  {
895  Moose::out << "\nStopping for " << getParam<unsigned int>("stop_for_debugger")
896  << " seconds to allow attachment from a debugger.\n";
897 
898  Moose::out << "\nAll of the processes you can connect to:\n";
899  Moose::out << "rank - hostname - pid\n";
900 
902 
903  {
904  // The 'false' turns off the serialization warning
905  SerializerGuard sg(_communicator, false); // Guarantees that the processors print in order
906  Moose::err << processor_id() << " - " << hostname << " - " << getpid() << "\n";
907  }
908 
909  Moose::out << "\nWaiting...\n" << std::endl;
910 
911  // Sleep to allow time for the debugger to attach
912  std::this_thread::sleep_for(std::chrono::seconds(getParam<unsigned int>("stop_for_debugger")));
913  }
914 
915  if (_master_mesh && isUltimateMaster())
916  mooseError("Mesh can be passed in only for sub-apps");
917 
918  if (_master_displaced_mesh && !_master_mesh)
919  mooseError("_master_mesh should have been set when _master_displaced_mesh is set");
920 
921 #ifdef MOOSE_MFEM_ENABLED
922  if (_mfem_device)
923  {
924  mooseAssert(!isUltimateMaster(),
925  "The MFEM device should only be auto-set for sub-applications");
926  mooseAssert(!_mfem_devices.empty(),
927  "If we are a sub-application and we have an MFEM device object, then we must know "
928  "its configuration string");
929  }
930 #endif
931 
932  // Data specifically associated with the mesh (meta-data) that will read from the restart
933  // file early during the simulation setup so that they are available to Actions and other objects
934  // that need them during the setup process. Most of the restartable data isn't made available
935  // until all objects have been created and all Actions have been executed (i.e. initialSetup).
936  registerRestartableDataMapName(MooseApp::MESH_META_DATA, MooseApp::MESH_META_DATA_SUFFIX);
937 
938  if (_pars.have_parameter<bool>("use_legacy_dirichlet_bc"))
939  mooseDeprecated("The parameter 'use_legacy_dirichlet_bc' is no longer valid.\n\n",
940  "All Dirichlet boundary conditions are preset by default.\n\n",
941  "Remove said parameter in ",
942  name(),
943  " to remove this deprecation warning.");
944 
945  if (_test_restep && _test_checkpoint_half_transient)
946  mooseError("Cannot use --test-restep and --test-checkpoint-half-transient together");
947 
948  Moose::out << std::flush;
949 
950 #ifdef MOOSE_KOKKOS_ENABLED
951 #ifdef MOOSE_ENABLE_KOKKOS_GPU
952  queryKokkosGPUs();
953 #endif
954 #endif
955 }
956 
957 std::optional<MooseEnum>
959 {
960  if (isParamSetByUser("compute_device"))
961  return getParam<MooseEnum>("compute_device");
962  return {};
963 }
964 
966 {
967 #ifdef HAVE_GPERFTOOLS
968  // CPU profiling stop
969  if (_cpu_profiling)
970  ProfilerStop();
971  // Heap profiling stop
972  if (_heap_profiling)
973  HeapProfilerStop();
974 #endif
976  _the_warehouse.reset();
977  _executioner.reset();
978 
979  // Don't wait for implicit destruction of input parameter storage
981 
982  // This is dirty, but I don't know what else to do. Obviously, others
983  // have had similar problems if you look above. In specific, the
984  // dlclose below on macs is destructing some data that does not
985  // belong to it in garbage collection. So... don't even give
986  // dlclose an option
987  _restartable_data.clear();
988 
989  // Remove this app's parameters from the AppFactory. This allows
990  // for creating an app with this name again in the same execution,
991  // which needs to be done when resetting applications in MultiApp
993 
994 #ifdef LIBMESH_HAVE_DLOPEN
995  // Close any open dynamic libraries
996  for (const auto & lib_pair : _lib_handles)
997  dlclose(lib_pair.second.library_handle);
998 #endif
999 
1000 #ifdef MOOSE_KOKKOS_ENABLED
1002 #endif
1003 }
1004 
1005 std::string
1007 {
1008  return MOOSE_VERSION;
1009 }
1010 
1011 std::string
1013 {
1014  return MOOSE_VERSION;
1015 }
1016 
1017 std::string
1019 {
1020  return getPrintableName() + " Version: " + getVersion();
1021 }
1022 
1023 void
1025 {
1026  TIME_SECTION("setupOptions", 5, "Setting Up Options");
1027 
1028  // Print the header, this is as early as possible
1029  if (header().length() && !getParam<bool>("suppress_header"))
1030  _console << header() << std::endl;
1031 
1032  if (getParam<bool>("error_unused"))
1033  setCheckUnusedFlag(true);
1034  else if (getParam<bool>("allow_unused"))
1035  setCheckUnusedFlag(false);
1036 
1037  if (getParam<bool>("error_override"))
1039 
1040  if (getParam<bool>("trap_fpe"))
1041  {
1042  _trap_fpe = true;
1043  _perf_graph.setActive(false);
1044  if (getParam<bool>("no_trap_fpe"))
1045  mooseError("Cannot use both \"--trap-fpe\" and \"--no-trap-fpe\" flags.");
1046  }
1047  else if (getParam<bool>("no_trap_fpe"))
1048  _trap_fpe = false;
1049 
1050  // Turn all warnings in MOOSE to errors (almost see next logic block)
1051  Moose::_warnings_are_errors = getParam<bool>("error");
1052 
1053  // Deprecated messages can be toggled to errors independently from everything else.
1054  Moose::_deprecated_is_error = getParam<bool>("error_deprecated");
1055 
1056  if (isUltimateMaster()) // makes sure coloring isn't reset incorrectly in multi-app settings
1057  {
1058  // Set from command line
1059  auto color = getParam<MooseEnum>("color");
1060  if (!isParamSetByUser("color"))
1061  {
1062  // Set from deprecated --no-color
1063  if (getParam<bool>("no_color"))
1064  color = "off";
1065  // Set from environment
1066  else
1067  {
1068  char * c_color = std::getenv("MOOSE_COLOR");
1069  if (c_color)
1070  color.assign(std::string(c_color), "While assigning environment variable MOOSE_COLOR");
1071  }
1072  }
1073 
1074  if (color == "auto")
1075  Moose::setColorConsole(true);
1076  else if (color == "on")
1077  Moose::setColorConsole(true, true);
1078  else if (color == "off")
1079  Moose::setColorConsole(false);
1080  else
1081  mooseAssert(false, "Should not hit");
1082 
1083  // After setting color so that non-yellow deprecated is honored
1084  if (getParam<bool>("no_color"))
1085  mooseDeprecated("The --no-color flag is deprecated. Use '--color off' instead.");
1086  }
1087 
1088 // If there's no threading model active, but the user asked for
1089 // --n-threads > 1 on the command line, throw a mooseError. This is
1090 // intended to prevent situations where the user has potentially
1091 // built MOOSE incorrectly (neither TBB nor pthreads found) and is
1092 // asking for multiple threads, not knowing that there will never be
1093 // any threads launched.
1094 #if !LIBMESH_USING_THREADS
1095  if (libMesh::command_line_value("--n-threads", 1) > 1)
1096  mooseError("You specified --n-threads > 1, but there is no threading model active!");
1097 #endif
1098 
1099  // Capability checking
1100  {
1101  // Augment capabilities from the TestHarness
1102  std::optional<std::set<std::string>> ignore_capabilities;
1103  if (isParamValid("testharness_capabilities"))
1104  {
1105  if (!isParamValid("required_capabilities"))
1106  mooseError(
1107  "--testharness-capabilities: Should not be specified without --required-capabilities");
1108 
1109  const auto file_path = std::filesystem::absolute(
1110  std::filesystem::path(getParam<std::string>("testharness_capabilities")));
1111 
1112  std::ifstream file(file_path);
1113  if (!file)
1114  mooseError("--testharness-capabilities: Could not open ", file_path);
1115 
1116  nlohmann::json root;
1117  try
1118  {
1119  file >> root;
1120  if (const auto it = root.find("capabilities"); it != root.end())
1122  if (const auto it = root.find("ignore_capabilities"); it != root.end())
1123  ignore_capabilities = it->get<std::set<std::string>>();
1124  }
1125  catch (const std::exception & e)
1126  {
1127  mooseError(
1128  "--testharness-capabilities: Failed to load capabilities ", file_path, ":\n", e.what());
1129  }
1130  }
1131 
1132  if (isParamValid("required_capabilities"))
1133  {
1135 
1136  const auto & required_capabilities = getParam<std::string>("required_capabilities");
1137 
1138  CapabilityRegistry::CheckOptions options;
1139  // Allowed to be unknown
1140  options.certain = false;
1141  // Add ignored capabilities, if any
1142  if (ignore_capabilities)
1143  options.ignore_capabilities = *ignore_capabilities;
1144 
1145  CapabilityRegistry::CheckResult result;
1146  try
1147  {
1148  result = Moose::internal::Capabilities::getCapabilities({}).check(required_capabilities,
1149  options);
1150  }
1151  catch (const std::exception & e)
1152  {
1153  mooseError("--required-capablities: ", e.what());
1154  }
1155 
1156  if (result.state < CapabilityRegistry::CheckState::UNKNOWN)
1157  {
1158  mooseInfo("Required capabilities '", required_capabilities, "' not fulfilled.");
1159  _ready_to_exit = true;
1160  // we use code 77 as "skip" in the Testharness
1161  _exit_code = 77;
1162  return;
1163  }
1164  if (result.state == CapabilityRegistry::CheckState::UNKNOWN)
1165  mooseError("Required capabilities '",
1166  required_capabilities,
1167  "' are not specific enough. A comparison test is performed on an undefined "
1168  "capability. Disambiguate this requirement by adding an existence/non-existence "
1169  "requirement. Example: 'unknown<1.2.3' should become 'unknown & unknown<1.2.3' "
1170  "or '!unknown | unknown<1.2.3'");
1171  }
1172  }
1173 
1174  // Build a minimal running application, ignoring the input file.
1175  if (getParam<bool>("minimal"))
1176  createMinimalApp();
1177 
1178  else if (getParam<bool>("display_version"))
1179  {
1180  Moose::out << getPrintableVersion() << std::endl;
1181  _early_exit_param = "--version";
1182  _ready_to_exit = true;
1183  return;
1184  }
1185  else if (getParam<bool>("help"))
1186  {
1187  _command_line->printUsage();
1188  _early_exit_param = "--help";
1189  _ready_to_exit = true;
1190  }
1191  else if (getParam<bool>("dump") || isParamSetByUser("dump_search"))
1192  {
1193  const std::string search =
1194  isParamSetByUser("dump_search") ? getParam<std::string>("dump_search") : "";
1195 
1196  JsonSyntaxTree tree(search);
1197 
1198  {
1199  TIME_SECTION("dump", 1, "Building Syntax Tree");
1201  }
1202 
1203  // Check if second arg is valid or not
1204  if ((tree.getRoot()).is_object())
1205  {
1206  // Turn off live printing so that it doesn't mess with the dump
1208 
1209  JsonInputFileFormatter formatter;
1210  Moose::out << "\n### START DUMP DATA ###\n"
1211  << formatter.toString(tree.getRoot()) << "\n### END DUMP DATA ###" << std::endl;
1212  _early_exit_param = "--dump";
1213  _ready_to_exit = true;
1214  }
1215  else
1216  mooseError("Search parameter '", search, "' was not found in the registered syntax.");
1217  }
1218  else if (getParam<bool>("registry"))
1219  {
1221 
1222  Moose::out << "Label\tType\tName\tClass\tFile\n";
1223 
1224  auto & objmap = Registry::allObjects();
1225  for (auto & entry : objmap)
1226  for (auto & obj : entry.second)
1227  Moose::out << entry.first << "\tobject\t" << obj->name() << "\t" << obj->_classname << "\t"
1228  << obj->_file << "\n";
1229 
1230  auto & actmap = Registry::allActions();
1231  for (auto & entry : actmap)
1232  {
1233  for (auto & act : entry.second)
1234  Moose::out << entry.first << "\taction\t" << act->_name << "\t" << act->_classname << "\t"
1235  << act->_file << "\n";
1236  }
1237  _early_exit_param = "--registry";
1238  _ready_to_exit = true;
1239  }
1240  else if (getParam<bool>("registry_hit"))
1241  {
1243 
1244  Moose::out << "### START REGISTRY DATA ###\n";
1245 
1246  hit::Section root("");
1247  auto sec = new hit::Section("registry");
1248  root.addChild(sec);
1249  auto objsec = new hit::Section("objects");
1250  sec->addChild(objsec);
1251 
1252  auto & objmap = Registry::allObjects();
1253  for (auto & entry : objmap)
1254  for (auto & obj : entry.second)
1255  {
1256  auto ent = new hit::Section("entry");
1257  objsec->addChild(ent);
1258  ent->addChild(new hit::Field("label", hit::Field::Kind::String, entry.first));
1259  ent->addChild(new hit::Field("type", hit::Field::Kind::String, "object"));
1260  ent->addChild(new hit::Field("name", hit::Field::Kind::String, obj->name()));
1261  ent->addChild(new hit::Field("class", hit::Field::Kind::String, obj->_classname));
1262  ent->addChild(new hit::Field("file", hit::Field::Kind::String, obj->_file));
1263  }
1264 
1265  auto actsec = new hit::Section("actions");
1266  sec->addChild(actsec);
1267  auto & actmap = Registry::allActions();
1268  for (auto & entry : actmap)
1269  for (auto & act : entry.second)
1270  {
1271  auto ent = new hit::Section("entry");
1272  actsec->addChild(ent);
1273  ent->addChild(new hit::Field("label", hit::Field::Kind::String, entry.first));
1274  ent->addChild(new hit::Field("type", hit::Field::Kind::String, "action"));
1275  ent->addChild(new hit::Field("task", hit::Field::Kind::String, act->_name));
1276  ent->addChild(new hit::Field("class", hit::Field::Kind::String, act->_classname));
1277  ent->addChild(new hit::Field("file", hit::Field::Kind::String, act->_file));
1278  }
1279 
1280  Moose::out << root.render();
1281 
1282  Moose::out << "\n### END REGISTRY DATA ###\n";
1283  _early_exit_param = "--registry_hit";
1284  _ready_to_exit = true;
1285  }
1286  else if (getParam<bool>("yaml") || isParamSetByUser("yaml_search"))
1287  {
1288  const std::string search =
1289  isParamSetByUser("yaml_search") ? getParam<std::string>("yaml_search") : "";
1291 
1293  _builder.buildFullTree(search);
1294 
1295  _early_exit_param = "--yaml";
1296  _ready_to_exit = true;
1297  }
1298  else if (getParam<bool>("json") || isParamSetByUser("json_search"))
1299  {
1300  const std::string search =
1301  isParamSetByUser("json_search") ? getParam<std::string>("json_search") : "";
1303 
1304  JsonSyntaxTree tree(search);
1306 
1308  "json", "**START JSON DATA**\n", "\n**END JSON DATA**", tree.getRoot().dump(2));
1309  _early_exit_param = "--json";
1310  _ready_to_exit = true;
1311  }
1312  else if (getParam<bool>("syntax"))
1313  {
1315 
1316  std::multimap<std::string, Syntax::ActionInfo> syntax = _syntax.getAssociatedActions();
1317  std::stringstream ss;
1318  for (const auto & it : syntax)
1319  ss << it.first << "\n";
1320  outputMachineReadableData("syntax", "**START SYNTAX DATA**\n", "**END SYNTAX DATA**", ss.str());
1321  _early_exit_param = "--syntax";
1322  _ready_to_exit = true;
1323  }
1324  else if (getParam<bool>("show_type"))
1325  {
1327 
1328  Moose::out << "MooseApp Type: " << type() << std::endl;
1329  _early_exit_param = "--show-type";
1330  _ready_to_exit = true;
1331  }
1332  else if (getParam<bool>("show_capabilities"))
1333  {
1335  outputMachineReadableData("show_capabilities",
1336  "**START JSON DATA**\n",
1337  "\n**END JSON DATA**",
1339  _ready_to_exit = true;
1340  }
1341  else if (isParamValid("check_capabilities"))
1342  {
1344 
1346  const auto & capabilities = getParam<std::string>("check_capabilities");
1347 
1348  CapabilityRegistry::CheckResult result;
1349  try
1350  {
1351  result = Moose::internal::Capabilities::getCapabilities({}).check(capabilities);
1352  }
1353  catch (const std::exception & e)
1354  {
1355  mooseError("--check-capablities: ", e.what());
1356  }
1357 
1358  const bool pass = result.state == CapabilityRegistry::CheckState::CERTAIN_PASS;
1359  _console << "Capabilities '" << capabilities << "' are " << (pass ? "" : "not ") << "fulfilled."
1360  << std::endl;
1361  _ready_to_exit = true;
1362  if (!pass)
1363  _exit_code = 77;
1364  return;
1365  }
1366  else if (!getInputFileNames().empty())
1367  {
1368  if (isParamSetByUser("recover"))
1369  {
1370  // We need to set the flag manually here since the recover parameter is a string type (takes
1371  // an optional filename)
1372  _recover = true;
1373  const auto & recover = getParam<std::string>("recover");
1374  if (recover.size())
1375  _restart_recover_base = recover;
1376  }
1377 
1378  _builder.build();
1379 
1380  // Lambda to check for mutually exclusive parameters
1381  auto isExclusiveParamSetByUser =
1382  [this](const std::vector<std::string> & group, const std::string & param)
1383  {
1384  auto is_set = isParamSetByUser(param);
1385  if (is_set)
1386  for (const auto & p : group)
1387  if (p != param && isParamSetByUser(p))
1388  mooseError("Parameters '" + p + "' and '" + param +
1389  "' are mutually exclusive. Please choose only one of them.");
1390  return is_set;
1391  };
1392 
1393  // The following parameters set the final task and so are mutually exclusive.
1394  const std::vector<std::string> final_task_params = {
1395  "csg_only", "mesh_only", "split_mesh", "parse_neml2_only"};
1396  if (isExclusiveParamSetByUser(final_task_params, "csg_only"))
1397  {
1398  // Error checking on incompatible command line options
1400  mooseError("--csg-only cannot be used in conjunction with --distributed-mesh");
1401  const bool has_mesh_split = isParamSetByUser("split_file") || _use_split;
1402  if (has_mesh_split)
1403  mooseError("--csg-only is not compatible with any mesh splitting options");
1404  if (isParamSetByUser("refinements"))
1405  mooseError("--csg-only cannot be used in conjunction with -r refinements option");
1406  if (!isUltimateMaster())
1407  mooseError("--csg-only option cannot be used as a Subapp");
1408  if (_recover)
1409  mooseError("--csg-only option cannot be used in recovery mode");
1410 
1411  _syntax.registerTaskName("execute_csg_generators", true);
1412  _syntax.addDependency("execute_csg_generators", "execute_mesh_generators");
1413  _syntax.addDependency("recover_meta_data", "execute_csg_generators");
1414 
1415  _syntax.registerTaskName("csg_only", true);
1416  _syntax.addDependency("csg_only", "recover_meta_data");
1417  _syntax.addDependency("set_mesh_base", "csg_only");
1418  _action_warehouse.setFinalTask("csg_only");
1419  }
1420  else if (isExclusiveParamSetByUser(final_task_params, "mesh_only"))
1421  {
1422  // If we are looking to just check the input, there is no need to
1423  // call MeshOnlyAction and generate a mesh
1424  if (_check_input)
1425  _action_warehouse.setFinalTask("setup_mesh_complete");
1426  else
1427  {
1428  _syntax.registerTaskName("mesh_only", true);
1429  _syntax.addDependency("mesh_only", "setup_mesh_complete");
1430  _syntax.addDependency("determine_system_type", "mesh_only");
1431  _action_warehouse.setFinalTask("mesh_only");
1432  }
1433  }
1434  else if (isExclusiveParamSetByUser(final_task_params, "split_mesh"))
1435  {
1436  _split_mesh = true;
1437  _syntax.registerTaskName("split_mesh", true);
1438  _syntax.addDependency("split_mesh", "setup_mesh_complete");
1439  _syntax.addDependency("determine_system_type", "split_mesh");
1440  _action_warehouse.setFinalTask("split_mesh");
1441  }
1442  else if (isExclusiveParamSetByUser(final_task_params, "parse_neml2_only"))
1443  {
1444  _syntax.registerTaskName("parse_neml2");
1445  _syntax.addDependency("determine_system_type", "parse_neml2");
1446  _action_warehouse.setFinalTask("parse_neml2");
1447  }
1449 
1450  // Setup the AppFileBase for use by the Outputs or other systems that need output file info
1451  {
1452  // Extract the CommonOutputAction
1453  const auto common_actions = _action_warehouse.getActions<CommonOutputAction>();
1454  mooseAssert(common_actions.size() <= 1, "Should not be more than one CommonOutputAction");
1455  const Action * common = common_actions.empty() ? nullptr : *common_actions.begin();
1456 
1457  // If file_base is set in CommonOutputAction through parsing input, obtain the file_base
1458  if (common && common->isParamValid("file_base"))
1459  {
1460  _output_file_base = common->getParam<std::string>("file_base");
1461  _file_base_set_by_user = true;
1462  }
1463  else if (isUltimateMaster())
1464  {
1465  // if this app is a master, we use the first input file name as the default file base.
1466  // use proximate here because the input file is an absolute path
1467  const auto & base = getLastInputFileName();
1468  size_t pos = base.find_last_of('.');
1469  _output_file_base = base.substr(0, pos);
1470  // Note: we did not append "_out" in the file base here because we do not want to
1471  // have it in between the input file name and the object name for Output/*
1472  // syntax.
1473  }
1474  // default file base for multiapps is set by MultiApp
1475  }
1476  }
1477  // No input file provided but we have other arguments (so don't just show print usage)
1478  else if (!isParamSetByUser("input_file") && _command_line->getArguments().size() > 2)
1479  {
1480  mooseAssert(getInputFileNames().empty(), "Should be empty");
1481 
1482  if (_check_input)
1483  mooseError("You specified --check-input, but did not provide an input file. Add -i "
1484  "<inputfile> to your command line.");
1485 
1486  mooseError("No input files specified. Add -i <inputfile> to your command line.");
1487  }
1488  else if (isParamValid("language_server") && getParam<bool>("language_server"))
1489  {
1491 
1492  // Reset output to the buffer what was cached before it was turned it off
1493  if (!Moose::out.rdbuf() && _output_buffer_cache)
1494  Moose::out.rdbuf(_output_buffer_cache);
1495 
1496  // Start a language server that communicates using an iostream connection
1497  MooseServer moose_server(*this);
1498 
1499  moose_server.run();
1500 
1501  _early_exit_param = "--language-server";
1502  _ready_to_exit = true;
1503  }
1504 
1505  else /* The catch-all case for bad options or missing options, etc. */
1506  {
1507  _command_line->printUsage();
1508  _early_exit_param = "bad or missing";
1509  _ready_to_exit = true;
1510  _exit_code = 1;
1511  }
1512 
1513  Moose::out << std::flush;
1514 }
1515 
1516 const std::vector<std::string> &
1518 {
1519  mooseAssert(_parser, "Parser is not set");
1520  return _parser->getInputFileNames();
1521 }
1522 
1523 const std::string &
1525 {
1526  mooseAssert(_parser, "Parser is not set");
1527  return _parser->getLastInputFileName();
1528 }
1529 
1530 std::string
1531 MooseApp::getOutputFileBase(bool for_non_moose_build_output) const
1532 {
1533  if (_file_base_set_by_user || for_non_moose_build_output || _multiapp_level)
1534  return _output_file_base;
1535  else
1536  return _output_file_base + "_out";
1537 }
1538 
1539 void
1540 MooseApp::setOutputFileBase(const std::string & output_file_base)
1541 {
1542  _output_file_base = output_file_base;
1543 
1544  // Reset the file base in the outputs
1546 
1547  // Reset the file base in multiapps (if they have been constructed yet)
1548  if (getExecutioner())
1549  for (auto & multi_app : feProblem().getMultiAppWarehouse().getObjects())
1550  multi_app->setAppOutputFileBase();
1551 
1552  _file_base_set_by_user = true;
1553 }
1554 
1555 void
1557 {
1558  TIME_SECTION("runInputFile", 3);
1559 
1560  // If early exit param has been set, then just return
1561  if (_ready_to_exit)
1562  return;
1563 
1565 
1566  if (isParamSetByUser("csg_only"))
1567  {
1568  _early_exit_param = "--csg-only";
1569  _ready_to_exit = true;
1570  }
1571  else if (isParamSetByUser("mesh_only"))
1572  {
1573  _early_exit_param = "--mesh-only";
1574  _ready_to_exit = true;
1575  }
1576  else if (isParamSetByUser("split_mesh"))
1577  {
1578  _early_exit_param = "--split-mesh";
1579  _ready_to_exit = true;
1580  }
1581  else if (isParamSetByUser("parse_neml2_only"))
1582  {
1583  _early_exit_param = "--parse-neml2-only";
1584  _ready_to_exit = true;
1585  }
1586  else if (getParam<bool>("list_constructed_objects"))
1587  {
1588  // TODO: ask multiapps for their constructed objects
1589  _early_exit_param = "--list-constructed-objects";
1590  _ready_to_exit = true;
1591  std::stringstream ss;
1592  for (const auto & obj : _factory.getConstructedObjects())
1593  ss << obj << '\n';
1595  "list_constructed_objects", "**START OBJECT DATA**\n", "\n**END OBJECT DATA**", ss.str());
1596  }
1597 }
1598 
1599 void
1601 {
1602  bool warn = _enable_unused_check == WARN_UNUSED;
1604 
1605  _builder.errorCheck(*_comm, warn, err);
1606 
1607  // Return early for mesh only mode, since we want error checking to run even though
1608  // an executor is not created for this case
1609  if (isParamSetByUser("mesh_only"))
1610  return;
1611 
1612  if (!_executor.get() && !_executioner.get())
1613  {
1614  if (!_early_exit_param.empty())
1615  {
1616  mooseAssert(_check_input,
1617  "Something went wrong, we should only get here if _check_input is true.");
1618  mooseError(
1619  "Incompatible command line arguments provided. --check-input cannot be called with ",
1621  ".");
1622  }
1623  // We should never get here
1624  mooseError("The Executor is being called without being initialized. This is likely "
1625  "caused by "
1626  "incompatible command line arguments");
1627  }
1628 
1629  auto apps = feProblem().getMultiAppWarehouse().getObjects();
1630  for (auto app : apps)
1631  for (unsigned int i = 0; i < app->numLocalApps(); i++)
1632  app->localApp(i)->errorCheck();
1633 }
1634 
1635 void
1637 {
1638  TIME_SECTION("executeExecutioner", 3);
1639 
1640  // If ready to exit has been set, then just return
1641  if (_ready_to_exit)
1642  return;
1643 
1644  // run the simulation
1645  if (_use_executor && _executor)
1646  {
1647  LibmeshPetscCall(Moose::PetscSupport::petscSetupOutput(_command_line.get()));
1648  _executor->init();
1649  errorCheck();
1650  auto result = _executor->exec();
1651  if (!result.convergedAll())
1652  mooseError(result.str());
1653  }
1654  else if (_executioner)
1655  {
1656  LibmeshPetscCall(Moose::PetscSupport::petscSetupOutput(_command_line.get()));
1657  _executioner->init();
1658  errorCheck();
1659  _executioner->execute();
1660  if (!_executioner->lastSolveConverged())
1661  setExitCode(1);
1662  }
1663  else
1664  mooseError("No executioner was specified (go fix your input file)");
1665 }
1666 
1667 bool
1669 {
1670  return _recover;
1671 }
1672 
1673 bool
1675 {
1676  return _restart;
1677 }
1678 
1679 bool
1681 {
1682  return _split_mesh;
1683 }
1684 
1685 bool
1687 {
1688  return !_restart_recover_base.empty();
1689 }
1690 
1691 bool
1693 {
1694  mooseDeprecated("MooseApp::hasRecoverFileBase is deprecated, use "
1695  "MooseApp::hasRestartRecoverFileBase() instead.");
1696  return !_restart_recover_base.empty();
1697 }
1698 
1699 void
1702 {
1704  switch (filter)
1705  {
1706  case RESTARTABLE_FILTER::RECOVERABLE:
1707  _recoverable_data_names.insert(name);
1708  break;
1709  default:
1710  mooseError("Unknown filter");
1711  }
1712 }
1713 
1714 std::vector<std::filesystem::path>
1715 MooseApp::backup(const std::filesystem::path & folder_base)
1716 {
1717  TIME_SECTION("backup", 2, "Backing Up Application to File");
1718 
1719  preBackup();
1720 
1722  return writer.write(folder_base);
1723 }
1724 
1725 std::unique_ptr<Backup>
1727 {
1728  TIME_SECTION("backup", 2, "Backing Up Application");
1729 
1731 
1732  preBackup();
1733 
1734  auto backup = std::make_unique<Backup>();
1735  packMeshBackup(*this, *backup);
1736  writer.write(*backup->header, *backup->data);
1737 
1738  return backup;
1739 }
1740 
1741 bool
1743 {
1744  return hasInitialBackup() && !(*_initial_backup)->mesh_files.empty();
1745 }
1746 
1747 void
1749 {
1750  mooseAssert(hasInitialBackup(), "Missing initial backup");
1751  _restored_initial_backup_mesh = restoreMeshBackup(*this, **_initial_backup, mesh);
1752 }
1753 
1754 void
1755 MooseApp::restore(const std::filesystem::path & folder_base, const bool for_restart)
1756 {
1757  TIME_SECTION("restore", 2, "Restoring Application from File");
1758 
1759  const DataNames filter_names = for_restart ? getRecoverableData() : DataNames{};
1760 
1761  _rd_reader.setInput(folder_base);
1762  _rd_reader.restore(filter_names);
1763 
1764  postRestore(for_restart);
1765 }
1766 
1767 void
1768 MooseApp::restore(std::unique_ptr<Backup> backup, const bool for_restart)
1769 {
1770  TIME_SECTION("restore", 2, "Restoring Application");
1771 
1772  const DataNames filter_names = for_restart ? getRecoverableData() : DataNames{};
1773 
1774  if (!backup)
1775  mooseError("MooseApp::restore(): Provided backup is not initialized");
1776 
1777  auto header = std::move(backup->header);
1778  mooseAssert(header, "Header not available");
1779 
1780  auto data = std::move(backup->data);
1781  mooseAssert(data, "Data not available");
1782 
1783  if (restoreMeshBackup(*this, *backup, feProblem().mesh()))
1784  {
1786  feProblem().mesh().prepare(/*mesh_to_clone=*/nullptr);
1787  feProblem().meshChanged(/*intermediate_change=*/false,
1788  /*contract_mesh=*/false,
1789  /*clean_refinement_flags=*/false);
1790  }
1791 
1792  _rd_reader.setInput(std::move(header), std::move(data));
1793  _rd_reader.restore(filter_names);
1794 
1795  postRestore(for_restart);
1796 }
1797 
1798 void
1799 MooseApp::restoreFromInitialBackup(const bool for_restart)
1800 {
1801  mooseAssert(hasInitialBackup(), "Missing initial backup");
1802  restore(std::move(*_initial_backup), for_restart);
1803 }
1804 
1805 std::unique_ptr<Backup>
1807 {
1808  if (!_rd_reader.isRestoring())
1809  mooseError("MooseApp::finalizeRestore(): Not currently restoring");
1810 
1811  // This gives us access to the underlying streams so that we can return it if needed
1812  auto input_streams = _rd_reader.clear();
1813 
1814  std::unique_ptr<Backup> backup;
1815 
1816  // Give them back a backup if this restore started from a Backup, in which case
1817  // the two streams in the Backup are formed into StringInputStreams
1818  if (auto header_string_input = dynamic_cast<StringInputStream *>(input_streams.header.get()))
1819  {
1820  auto data_string_input = dynamic_cast<StringInputStream *>(input_streams.data.get());
1821  mooseAssert(data_string_input, "Should also be a string input");
1822 
1823  auto header_sstream = header_string_input->release();
1824  mooseAssert(header_sstream, "Header not available");
1825 
1826  auto data_sstream = data_string_input->release();
1827  mooseAssert(data_sstream, "Data not available");
1828 
1829  backup = std::make_unique<Backup>();
1830  backup->header = std::move(header_sstream);
1831  backup->data = std::move(data_sstream);
1832  packMeshBackup(*this, *backup);
1833  }
1834 
1835  return backup;
1836 }
1837 
1838 void
1839 MooseApp::setCheckUnusedFlag(bool warn_is_error)
1840 {
1841  _enable_unused_check = warn_is_error ? ERROR_UNUSED : WARN_UNUSED;
1842 }
1843 
1844 void
1846 {
1848 }
1849 
1850 FEProblemBase &
1852 {
1853  mooseAssert(_executor.get() || _executioner.get(), "No executioner yet, calling too early!");
1854  return _executor.get() ? _executor->feProblem() : _executioner->feProblem();
1855 }
1856 
1857 void
1858 MooseApp::addExecutor(const std::string & type,
1859  const std::string & name,
1860  const InputParameters & params)
1861 {
1862  std::shared_ptr<Executor> executor = _factory.create<Executor>(type, name, params);
1863 
1864  if (_executors.count(executor->name()) > 0)
1865  mooseError("an executor with name '", executor->name(), "' already exists");
1866  _executors[executor->name()] = executor;
1867 }
1868 
1869 void
1870 MooseApp::addExecutorParams(const std::string & type,
1871  const std::string & name,
1872  const InputParameters & params)
1873 {
1874  _executor_params[name] = std::make_pair(type, std::make_unique<InputParameters>(params));
1875 }
1876 
1877 const Parser &
1879 {
1880  mooseAssert(_parser, "Not set");
1881  return *_parser;
1882 }
1883 
1884 Parser &
1886 {
1887  return const_cast<Parser &>(std::as_const(*this).parser());
1888 }
1889 
1890 void
1891 MooseApp::recursivelyCreateExecutors(const std::string & current_executor_name,
1892  std::list<std::string> & possible_roots,
1893  std::list<std::string> & current_branch)
1894 {
1895  // Did we already make this one?
1896  if (_executors.find(current_executor_name) != _executors.end())
1897  return;
1898 
1899  // Is this one already on the current branch (i.e. there is a cycle)
1900  if (std::find(current_branch.begin(), current_branch.end(), current_executor_name) !=
1901  current_branch.end())
1902  {
1903  std::stringstream exec_names_string;
1904 
1905  auto branch_it = current_branch.begin();
1906 
1907  exec_names_string << *branch_it++;
1908 
1909  for (; branch_it != current_branch.end(); ++branch_it)
1910  exec_names_string << ", " << *branch_it;
1911 
1912  exec_names_string << ", " << current_executor_name;
1913 
1914  mooseError("Executor cycle detected: ", exec_names_string.str());
1915  }
1916 
1917  current_branch.push_back(current_executor_name);
1918 
1919  // Build the dependencies first
1920  const auto & params = *_executor_params[current_executor_name].second;
1921 
1922  for (const auto & param : params)
1923  {
1924  if (params.have_parameter<ExecutorName>(param.first))
1925  {
1926  const auto & dependency_name = params.get<ExecutorName>(param.first);
1927 
1928  possible_roots.remove(dependency_name);
1929 
1930  if (!dependency_name.empty())
1931  recursivelyCreateExecutors(dependency_name, possible_roots, current_branch);
1932  }
1933  }
1934 
1935  // Add this Executor
1936  const auto & type = _executor_params[current_executor_name].first;
1937  addExecutor(type, current_executor_name, params);
1938 
1939  current_branch.pop_back();
1940 }
1941 
1942 void
1944 {
1945  // Do we have any?
1946  if (_executor_params.empty())
1947  return;
1948 
1949  // Holds the names of Executors that may be the root executor
1950  std::list<std::string> possibly_root;
1951 
1952  // What is already built
1953  std::map<std::string, bool> already_built;
1954 
1955  // The Executors that are currently candidates for being roots
1956  std::list<std::string> possible_roots;
1957 
1958  // The current line of dependencies - used for finding cycles
1959  std::list<std::string> current_branch;
1960 
1961  // Build the NullExecutor
1962  {
1963  auto params = _factory.getValidParams("NullExecutor");
1964  _null_executor = _factory.create<NullExecutor>("NullExecutor", "_null_executor", params);
1965  }
1966 
1967  for (const auto & params_entry : _executor_params)
1968  {
1969  const auto & name = params_entry.first;
1970 
1971  // Did we already make this one?
1972  if (_executors.find(name) != _executors.end())
1973  continue;
1974 
1975  possible_roots.emplace_back(name);
1976 
1977  recursivelyCreateExecutors(name, possible_roots, current_branch);
1978  }
1979 
1980  // If there is more than one possible root - error
1981  if (possible_roots.size() > 1)
1982  {
1983  auto root_string_it = possible_roots.begin();
1984 
1985  std::stringstream roots_string;
1986 
1987  roots_string << *root_string_it++;
1988 
1989  for (; root_string_it != possible_roots.end(); ++root_string_it)
1990  roots_string << ", " << *root_string_it;
1991 
1992  mooseError("Multiple Executor roots found: ", roots_string.str());
1993  }
1994 
1995  // Set the root executor
1996  _executor = _executors[possible_roots.front()];
1997 }
1998 
1999 Executor &
2000 MooseApp::getExecutor(const std::string & name, bool fail_if_not_found)
2001 {
2002  auto it = _executors.find(name);
2003 
2004  if (it != _executors.end())
2005  return *it->second;
2006 
2007  if (fail_if_not_found)
2008  mooseError("Executor not found: ", name);
2009 
2010  return *_null_executor;
2011 }
2012 
2013 Executioner *
2015 {
2016  return _executioner.get() ? _executioner.get() : _executor.get();
2017 }
2018 
2019 void
2021 {
2022  _error_overridden = true;
2023 }
2024 
2025 void
2027 {
2028  TIME_SECTION("run", 3);
2029  if (getParam<bool>("show_docs"))
2030  {
2031  auto binname = appBinaryName();
2032  if (binname == "")
2033  mooseError("could not locate installed tests to run (unresolved binary/app name)");
2034  auto docspath = MooseUtils::docsDir(binname);
2035  if (docspath == "")
2036  mooseError("no installed documentation found");
2037 
2038  auto docmsgfile = MooseUtils::pathjoin(docspath, "docmsg.txt");
2039  std::string docmsg = "file://" + MooseUtils::realpath(docspath) + "/index.html";
2040  if (MooseUtils::pathExists(docmsgfile) && MooseUtils::checkFileReadable(docmsgfile))
2041  {
2042  std::ifstream ifs(docmsgfile);
2043  std::string content((std::istreambuf_iterator<char>(ifs)),
2044  (std::istreambuf_iterator<char>()));
2045  content.replace(content.find("$LOCAL_SITE_HOME"), content.length(), docmsg);
2046  docmsg = content;
2047  }
2048 
2049  Moose::out << docmsg << "\n";
2050  _early_exit_param = "--docs";
2051  _ready_to_exit = true;
2052  return;
2053  }
2054 
2055  if (showInputs() || copyInputs() || runInputs())
2056  {
2057  _early_exit_param = "--show-input, --copy-inputs, or --run";
2058  _ready_to_exit = true;
2059  return;
2060  }
2061 
2062  try
2063  {
2064  TIME_SECTION("setup", 2, "Setting Up");
2065  setupOptions();
2066  runInputFile();
2067  }
2068  catch (Parser::Error & err)
2069  {
2070  mooseAssert(_parser->getThrowOnError(), "Should be true");
2071  throw;
2072  }
2073  catch (MooseRuntimeError & err)
2074  {
2075  mooseAssert(Moose::_throw_on_error, "Should be true");
2076  throw;
2077  }
2078  catch (std::exception & err)
2079  {
2080  mooseError(err.what());
2081  }
2082 
2083  if (!_check_input)
2084  {
2085  TIME_SECTION("execute", 2, "Executing");
2087  }
2088  else
2089  {
2090  errorCheck();
2091  // Output to stderr, so it is easier for peacock to get the result
2092  Moose::err << "Syntax OK" << std::endl;
2093  }
2094 
2095  if (isParamSetByUser("citations"))
2096  requestCitations();
2097 }
2098 
2099 void
2100 MooseApp::collectCitations(std::map<std::string, std::string> & citations) const
2101 {
2102  // Gather the citations that apply to this app: for every object type actually constructed, the
2103  // citations registered for its owning app/module. The framework paper is tied to "MooseApp", so
2104  // it is gathered whenever a MooseApp object is used; apps composed of MooseApp inherit it. The
2105  // map is keyed by BibTeX key so a citation shared across apps is folded in only once.
2106  for (const auto & objname : _factory.getConstructedObjects())
2107  {
2108  mooseAssert(Registry::isRegisteredObj(objname),
2109  "Constructed object '" + objname + "' is not registered");
2110  const auto & app_citations = Registry::getCitations(Registry::objData(objname)._label);
2111  citations.insert(app_citations.begin(), app_citations.end());
2112  }
2113 
2114  // Credit the finite element backend actually used in the run. These are mutually exclusive, so
2115  // only the backend in use is cited.
2116  std::string backend = "libMesh";
2117 #ifdef MOOSE_MFEM_ENABLED
2119  backend = "MFEM";
2120 #endif
2121  const auto & backend_citations = Registry::getCitations(backend);
2122  citations.insert(backend_citations.begin(), backend_citations.end());
2123 
2124  // Recurse into the MultiApp subapps so that objects/modules used only inside subapps are still
2125  // attributed. Each subapp is a separate MooseApp whose run() (and thus requestCitations()) is
2126  // never called, so the master gathers their citations here. feProblem() asserts when there is no
2127  // executioner, so only descend once one exists; nested MultiApps are handled by the recursion.
2128  if (_executor || _executioner)
2129  for (const auto & multi_app : feProblem().getMultiAppWarehouse().getObjects())
2130  for (const auto i : make_range(multi_app->numLocalApps()))
2131  multi_app->localApp(i)->collectCitations(citations);
2132 }
2133 
2134 void
2136 {
2137  // Collect the de-duplicated citations across this app and, recursively, every MultiApp subapp.
2138  std::map<std::string, std::string> citations;
2139  collectCitations(citations);
2140 
2141  // MultiApp subapps are distributed across the MPI ranks, so each rank has collected citations
2142  // only for the subapps it owns. PETSc prints the citation list from rank 0 alone, so gather every
2143  // rank's citations onto all ranks; otherwise a module used only by a subapp that lives off rank 0
2144  // would be omitted.
2145  std::vector<std::string> flattened;
2146  flattened.reserve(citations.size() * 2);
2147  for (const auto & [key, bibtex] : citations)
2148  {
2149  flattened.push_back(key);
2150  flattened.push_back(bibtex);
2151  }
2152  _comm->allgather(flattened);
2153  for (std::size_t i = 0; i + 1 < flattened.size(); i += 2)
2154  {
2155  [[maybe_unused]] const auto [it, inserted] = citations.emplace(flattened[i], flattened[i + 1]);
2156  mooseAssert(inserted || it->second == flattened[i + 1],
2157  "The same citation key was registered with different BibTeX entries");
2158  }
2159 
2160  // Register the resolved BibTeX entries with PETSc and enable its -citations option. PETSc prints
2161  // them, together with the run-specific citations from any PETSc solvers/preconditioners actually
2162  // used, at PetscFinalize (to the console or, if a file name was given, to that file).
2163  for (const auto & citation : citations)
2165 
2166  Moose::PetscSupport::setSinglePetscOption("-citations", getParam<std::string>("citations"));
2167 }
2168 
2169 bool
2171 {
2172  if (getParam<bool>("show_inputs"))
2173  {
2174  const auto show_inputs_syntax = _pars.getCommandLineMetadata("show_inputs").switches;
2175  std::vector<std::string> dirs;
2176  const auto installable_inputs = getInstallableInputs();
2177 
2178  if (installable_inputs == "")
2179  {
2180  Moose::out
2181  << "Show inputs has not been overriden in this application.\nContact the developers of "
2182  "this appication and request that they override \"MooseApp::getInstallableInputs\".\n";
2183  }
2184  else
2185  {
2186  mooseAssert(!show_inputs_syntax.empty(), "show_inputs sytnax should not be empty");
2187 
2188  MooseUtils::tokenize(installable_inputs, dirs, 1, " ");
2189  Moose::out << "The following directories are installable into a user-writeable directory:\n\n"
2190  << installable_inputs << '\n'
2191  << "\nTo install one or more directories of inputs, execute the binary with the \""
2192  << show_inputs_syntax[0] << "\" flag. e.g.:\n$ "
2193  << _command_line->getExecutableName() << ' ' << show_inputs_syntax[0] << ' '
2194  << dirs[0] << '\n';
2195  }
2196  return true;
2197  }
2198  return false;
2199 }
2200 
2201 std::string
2203 {
2204  return "tests";
2205 }
2206 
2207 bool
2209 {
2210  if (isParamSetByUser("copy_inputs"))
2211  {
2212  if (comm().size() > 1)
2213  mooseError("The --copy-inputs option should not be ran in parallel");
2214 
2215  // Get command line argument following --copy-inputs on command line
2216  auto dir_to_copy = getParam<std::string>("copy_inputs");
2217 
2218  if (dir_to_copy.empty())
2219  mooseError("Error retrieving directory to copy");
2220  if (dir_to_copy.back() != '/')
2221  dir_to_copy += '/';
2222 
2223  // This binary name is the actual binary. That is, if we called a symlink it'll
2224  // be the name of what the symlink points to
2225  auto binname = appBinaryName();
2226  if (binname == "")
2227  mooseError("could not locate installed tests to run (unresolved binary/app name)");
2228 
2229  auto src_dir = MooseUtils::installedInputsDir(
2230  binname,
2231  dir_to_copy,
2232  "Rerun binary with " + _pars.getCommandLineMetadata("show_inputs").switches[0] +
2233  " to get a list of installable directories.");
2234 
2235  // Use the command line here because if we have a symlink to another binary,
2236  // we want to dump into a directory that is named after the symlink not the true binary
2237  auto dst_dir = _command_line->getExecutableNameBase() + "/" + dir_to_copy;
2238  auto cmdname = _command_line->getExecutableName();
2239  if (cmdname.find_first_of("/") != std::string::npos)
2240  cmdname = cmdname.substr(cmdname.find_first_of("/") + 1, std::string::npos);
2241 
2242  if (MooseUtils::pathExists(dst_dir))
2243  mooseError(
2244  "The directory \"./",
2245  dst_dir,
2246  "\" already exists.\nTo update/recopy the contents of this directory, rename (\"mv ",
2247  dst_dir,
2248  " new_dir_name\") or remove (\"rm -r ",
2249  dst_dir,
2250  "\") the existing directory.\nThen re-run \"",
2251  cmdname,
2252  " --copy-inputs ",
2253  dir_to_copy,
2254  "\".");
2255 
2256  std::string cmd = "mkdir -p " + dst_dir + "; rsync -av " + src_dir + " " + dst_dir;
2257 
2258  TIME_SECTION("copy_inputs", 2, "Copying Inputs");
2259 
2260  mooseAssert(comm().size() == 1, "Should be run in serial");
2261  const auto return_value = system(cmd.c_str());
2262  if (!WIFEXITED(return_value))
2263  mooseError("Process exited unexpectedly");
2264  setExitCode(WEXITSTATUS(return_value));
2265  if (exitCode() == 0)
2266  Moose::out << "Directory successfully copied into ./" << dst_dir << '\n';
2267  return true;
2268  }
2269  return false;
2270 }
2271 
2272 bool
2274 {
2275  if (isParamSetByUser("run"))
2276  {
2277  if (comm().size() > 1)
2278  mooseError("The --run option should not be ran in parallel");
2279 
2280  // Pass everything after --run on the cli to the TestHarness
2281  const auto find_run_it = std::as_const(*_command_line).findCommandLineParam("run");
2282  const auto & cl_entries = std::as_const(*_command_line).getEntries();
2283  mooseAssert(find_run_it != cl_entries.end(), "Didn't find the option");
2284  std::string test_args;
2285  for (auto it = std::next(find_run_it); it != cl_entries.end(); ++it)
2286  for (const auto & arg : it->raw_args)
2287  {
2288  test_args += " " + arg;
2290  }
2291 
2292  auto working_dir = MooseUtils::getCurrentWorkingDir();
2293  if (MooseUtils::findTestRoot() == "")
2294  {
2295  auto bin_name = appBinaryName();
2296  if (bin_name == "")
2297  mooseError("Could not locate binary name relative to installed location");
2298 
2299  auto cmd_name = Moose::getExecutableName();
2300  mooseError(
2301  "Could not locate installed tests from the current working directory:",
2302  working_dir,
2303  ".\nMake sure you are executing this command from within a writable installed inputs ",
2304  "directory.\nRun \"",
2305  cmd_name,
2306  " --copy-inputs <dir>\" to copy the contents of <dir> to a \"./",
2307  bin_name,
2308  "_<dir>\" directory.\nChange into that directory and try \"",
2309  cmd_name,
2310  " --run <dir>\" again.");
2311  }
2312 
2313  // Set this application as the app name for the moose_test_runner script that we're running
2314  setenv("MOOSE_TEST_RUNNER_APP_NAME", appBinaryName().c_str(), true);
2315 
2316  const std::string cmd = MooseUtils::runTestsExecutable() + test_args;
2317  Moose::out << "Working Directory: " << working_dir << "\nRunning Command: " << cmd << std::endl;
2318  mooseAssert(comm().size() == 1, "Should be run in serial");
2319  const auto return_value = system(cmd.c_str());
2320  if (!WIFEXITED(return_value))
2321  mooseError("Process exited unexpectedly");
2322  setExitCode(WEXITSTATUS(return_value));
2323  return true;
2324  }
2325 
2326  return false;
2327 }
2328 
2330 MooseApp::addCapabilityInternal(const std::string_view capability,
2331  const Moose::Capability::Value & value,
2332  const std::string_view doc)
2333 {
2334  try
2335  {
2336  return Moose::internal::Capabilities::getCapabilities({}).add(capability, value, doc);
2337  }
2338  catch (const std::exception & e)
2339  {
2340  ::mooseError(e.what());
2341  }
2342 }
2343 
2344 void
2346 {
2347  _output_position_set = true;
2348  _output_position = p;
2350 
2351  if (_executioner.get())
2352  _executioner->parentOutputPositionChanged();
2353 }
2354 
2355 std::list<std::string>
2357 {
2358  // Storage for the directory names
2359  std::list<std::string> checkpoint_dirs;
2360 
2361  // Add the directories added with Outputs/checkpoint=true input syntax
2362  checkpoint_dirs.push_back(getOutputFileBase() + "_cp");
2363 
2364  // Add the directories from any existing checkpoint output objects
2365  const auto & actions = _action_warehouse.getActionListByName("add_output");
2366  for (const auto & action : actions)
2367  {
2368  // Get the parameters from the MooseObjectAction
2369  MooseObjectAction * moose_object_action = dynamic_cast<MooseObjectAction *>(action);
2370  if (!moose_object_action)
2371  continue;
2372 
2373  const InputParameters & params = moose_object_action->getObjectParams();
2374  if (moose_object_action->getParam<std::string>("type") == "Checkpoint")
2375  {
2376  // Unless file_base was explicitly set by user, we cannot rely on it, as it will be changed
2377  // later
2378  const std::string cp_dir =
2379  _file_base_set_by_user ? params.get<std::string>("file_base")
2380  : (getOutputFileBase(true) + "_" + moose_object_action->name());
2381  checkpoint_dirs.push_back(cp_dir + "_cp");
2382  }
2383  }
2384  return checkpoint_dirs;
2385 }
2386 
2387 std::list<std::string>
2389 {
2390  auto checkpoint_dirs = getCheckpointDirectories();
2391  return MooseUtils::getFilesInDirs(checkpoint_dirs, false);
2392 }
2393 
2394 void
2396 {
2397  _start_time_set = true;
2398  _start_time = time;
2399 }
2400 
2401 std::string
2402 MooseApp::getFileName(bool stripLeadingPath) const
2403 {
2404  return _builder.getPrimaryFileName(stripLeadingPath);
2405 }
2406 
2409 {
2410  return _output_warehouse;
2411 }
2412 
2413 const OutputWarehouse &
2415 {
2416  return _output_warehouse;
2417 }
2418 
2419 std::string
2420 MooseApp::appNameToLibName(const std::string & app_name) const
2421 {
2422  std::string library_name(app_name);
2423 
2424  // Strip off the App part (should always be the last 3 letters of the name)
2425  size_t pos = library_name.find("App");
2426  if (pos != library_name.length() - 3)
2427  mooseError("Invalid application name: ", library_name);
2428  library_name.erase(pos);
2429 
2430  // Now get rid of the camel case, prepend lib, and append the method and suffix
2431  return std::string("lib") + MooseUtils::camelCaseToUnderscore(library_name) + '-' +
2432  QUOTE(METHOD) + ".la";
2433 }
2434 
2435 std::string
2436 MooseApp::libNameToAppName(const std::string & library_name) const
2437 {
2438  std::string app_name(library_name);
2439 
2440  // Strip off the leading "lib" and trailing ".la"
2441  if (pcrecpp::RE("lib(.+?)(?:-\\w+)?\\.la").Replace("\\1", &app_name) == 0)
2442  mooseError("Invalid library name: ", app_name);
2443 
2444  return MooseUtils::underscoreToCamelCase(app_name, true);
2445 }
2446 
2448 MooseApp::registerRestartableData(std::unique_ptr<RestartableDataValue> data,
2449  THREAD_ID tid,
2450  bool read_only,
2451  const RestartableDataMapName & metaname)
2452 {
2453  if (!metaname.empty() && tid != 0)
2454  mooseError(
2455  "The meta data storage for '", metaname, "' is not threaded, so the tid must be zero.");
2456 
2457  mooseAssert(metaname.empty() ||
2458  _restartable_meta_data.find(metaname) != _restartable_meta_data.end(),
2459  "The desired meta data name does not exist: " + metaname);
2460 
2461  // Select the data store for saving this piece of restartable data (mesh or everything else)
2462  auto & data_map =
2463  metaname.empty() ? _restartable_data[tid] : _restartable_meta_data[metaname].first;
2464 
2465  RestartableDataValue * stored_data = data_map.findData(data->name());
2466  if (stored_data)
2467  {
2468  if (data->typeId() != stored_data->typeId())
2469  mooseError("Type mismatch found in RestartableData registration of '",
2470  data->name(),
2471  "'\n\n Stored type: ",
2472  stored_data->type(),
2473  "\n New type: ",
2474  data->type());
2475  }
2476  else
2477  stored_data = &data_map.addData(std::move(data));
2478 
2479  if (!read_only)
2480  stored_data->setDeclared({});
2481 
2482  return *stored_data;
2483 }
2484 
2486 MooseApp::registerRestartableData(const std::string & libmesh_dbg_var(name),
2487  std::unique_ptr<RestartableDataValue> data,
2488  THREAD_ID tid,
2489  bool read_only,
2490  const RestartableDataMapName & metaname)
2491 {
2492  mooseDeprecated("The use of MooseApp::registerRestartableData with a data name is "
2493  "deprecated.\n\nUse the call without a name instead.");
2494 
2495  mooseAssert(name == data->name(), "Inconsistent name");
2496  return registerRestartableData(std::move(data), tid, read_only, metaname);
2497 }
2498 
2499 bool
2500 MooseApp::hasRestartableMetaData(const std::string & name,
2501  const RestartableDataMapName & metaname) const
2502 {
2503  auto it = _restartable_meta_data.find(metaname);
2504  if (it == _restartable_meta_data.end())
2505  return false;
2506  return it->second.first.hasData(name);
2507 }
2508 
2510 MooseApp::getRestartableMetaData(const std::string & name,
2511  const RestartableDataMapName & metaname,
2512  THREAD_ID tid)
2513 {
2514  if (tid != 0)
2515  mooseError(
2516  "The meta data storage for '", metaname, "' is not threaded, so the tid must be zero.");
2517 
2518  // Get metadata reference from RestartableDataMap and return a (non-const) reference to its value
2519  auto & restartable_data_map = getRestartableDataMap(metaname);
2520  RestartableDataValue * const data = restartable_data_map.findData(name);
2521  if (!data)
2522  mooseError("Unable to find RestartableDataValue object with name " + name +
2523  " in RestartableDataMap");
2524 
2525  return *data;
2526 }
2527 
2528 void
2530  const std::filesystem::path & folder_base)
2531 {
2532  const auto & map_name = getRestartableDataMapName(name);
2533  const auto meta_data_folder_base = metaDataFolderBase(folder_base, map_name);
2534  if (RestartableDataReader::isAvailable(meta_data_folder_base))
2535  {
2538  reader.setInput(meta_data_folder_base);
2539  reader.restore();
2540  }
2541 }
2542 
2543 void
2544 MooseApp::loadRestartableMetaData(const std::filesystem::path & folder_base)
2545 {
2546  for (const auto & name_map_pair : _restartable_meta_data)
2547  possiblyLoadRestartableMetaData(name_map_pair.first, folder_base);
2548 }
2549 
2550 std::vector<std::filesystem::path>
2552  const std::filesystem::path & folder_base)
2553 {
2554  if (processor_id() != 0)
2555  mooseError("MooseApp::writeRestartableMetaData(): Should only run on processor 0");
2556 
2557  const auto & map_name = getRestartableDataMapName(name);
2558  const auto meta_data_folder_base = metaDataFolderBase(folder_base, map_name);
2559 
2561  return writer.write(meta_data_folder_base);
2562 }
2563 
2564 std::vector<std::filesystem::path>
2565 MooseApp::writeRestartableMetaData(const std::filesystem::path & folder_base)
2566 {
2567  std::vector<std::filesystem::path> paths;
2568 
2569  if (processor_id() == 0)
2570  for (const auto & name_map_pair : _restartable_meta_data)
2571  {
2572  const auto map_paths = writeRestartableMetaData(name_map_pair.first, folder_base);
2573  paths.insert(paths.end(), map_paths.begin(), map_paths.end());
2574  }
2575 
2576  return paths;
2577 }
2578 
2579 void
2580 MooseApp::dynamicAppRegistration(const std::string & app_name,
2581  std::string library_path,
2582  const std::string & library_name,
2583  bool lib_load_deps)
2584 {
2585 #ifdef LIBMESH_HAVE_DLOPEN
2586  Parameters params;
2587  params.set<std::string>("app_name") = app_name;
2588  params.set<RegistrationType>("reg_type") = APPLICATION;
2589  params.set<std::string>("registration_method") = app_name + "__registerApps";
2590  params.set<std::string>("library_path") = library_path;
2591 
2592  const auto effective_library_name =
2593  library_name.empty() ? appNameToLibName(app_name) : library_name;
2594  params.set<std::string>("library_name") = effective_library_name;
2595  params.set<bool>("library_load_dependencies") = lib_load_deps;
2596 
2597  const auto paths = getLibrarySearchPaths(library_path);
2598  std::ostringstream oss;
2599 
2600  auto successfully_loaded = false;
2601  if (paths.empty())
2602  oss << '"' << app_name << "\" is not a registered application name.\n"
2603  << "No search paths were set. We made no attempts to locate the corresponding library "
2604  "file.\n";
2605  else
2606  {
2607  dynamicRegistration(params);
2608 
2609  // At this point the application should be registered so check it
2610  if (!AppFactory::instance().isRegistered(app_name))
2611  {
2612  oss << '"' << app_name << "\" is not a registered application name.\n"
2613  << "Unable to locate library archive for \"" << app_name
2614  << "\".\nWe attempted to locate the library archive \"" << effective_library_name
2615  << "\" in the following paths:\n\t";
2616  std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
2617  }
2618  else
2619  successfully_loaded = true;
2620  }
2621 
2622  if (!successfully_loaded)
2623  {
2624  oss << "\nMake sure you have compiled the library and either set the \"library_path\" "
2625  "variable in your input file or exported \"MOOSE_LIBRARY_PATH\".\n";
2626 
2627  mooseError(oss.str());
2628  }
2629 
2630 #else
2631  libmesh_ignore(app_name, library_path, library_name, lib_load_deps);
2632  mooseError("Dynamic Loading is either not supported or was not detected by libMesh configure.");
2633 #endif
2634 }
2635 
2636 void
2637 MooseApp::dynamicAllRegistration(const std::string & app_name,
2638  Factory * factory,
2639  ActionFactory * action_factory,
2640  Syntax * syntax,
2641  std::string library_path,
2642  const std::string & library_name)
2643 {
2644 #ifdef LIBMESH_HAVE_DLOPEN
2645  Parameters params;
2646  params.set<std::string>("app_name") = app_name;
2647  params.set<RegistrationType>("reg_type") = REGALL;
2648  params.set<std::string>("registration_method") = app_name + "__registerAll";
2649  params.set<std::string>("library_path") = library_path;
2650  params.set<std::string>("library_name") =
2651  library_name.empty() ? appNameToLibName(app_name) : library_name;
2652 
2653  params.set<Factory *>("factory") = factory;
2654  params.set<Syntax *>("syntax") = syntax;
2655  params.set<ActionFactory *>("action_factory") = action_factory;
2656  params.set<bool>("library_load_dependencies") = false;
2657 
2658  dynamicRegistration(params);
2659 #else
2660  libmesh_ignore(app_name, factory, action_factory, syntax, library_path, library_name);
2661  mooseError("Dynamic Loading is either not supported or was not detected by libMesh configure.");
2662 #endif
2663 }
2664 
2665 void
2667 {
2668  const auto paths = getLibrarySearchPaths(params.get<std::string>("library_path"));
2669  const auto library_name = params.get<std::string>("library_name");
2670 
2671  // Attempt to dynamically load the library
2672  for (const auto & path : paths)
2673  if (MooseUtils::checkFileReadable(path + '/' + library_name, false, false))
2675  path + '/' + library_name, params, params.get<bool>("library_load_dependencies"));
2676 }
2677 
2678 void
2679 MooseApp::loadLibraryAndDependencies(const std::string & library_filename,
2680  const Parameters & params,
2681  const bool load_dependencies)
2682 {
2683  std::string line;
2684  std::string dl_lib_filename;
2685 
2686  // This RE looks for absolute path libtool filenames (i.e. begins with a slash and ends with a
2687  // .la)
2688  pcrecpp::RE re_deps("(/\\S*\\.la)");
2689 
2690  std::ifstream la_handle(library_filename.c_str());
2691  if (la_handle.is_open())
2692  {
2693  while (std::getline(la_handle, line))
2694  {
2695  // Look for the system dependent dynamic library filename to open
2696  if (line.find("dlname=") != std::string::npos)
2697  // Magic numbers are computed from length of this string "dlname=' and line minus that
2698  // string plus quotes"
2699  dl_lib_filename = line.substr(8, line.size() - 9);
2700 
2701  if (line.find("dependency_libs=") != std::string::npos)
2702  {
2703  if (load_dependencies)
2704  {
2705  pcrecpp::StringPiece input(line);
2706  pcrecpp::StringPiece depend_library;
2707  while (re_deps.FindAndConsume(&input, &depend_library))
2708  // Recurse here to load dependent libraries in depth-first order
2709  loadLibraryAndDependencies(depend_library.as_string(), params, load_dependencies);
2710  }
2711 
2712  // There's only one line in the .la file containing the dependency libs so break after
2713  // finding it
2714  break;
2715  }
2716  }
2717  la_handle.close();
2718  }
2719 
2720  // This should only occur if we have static linkage.
2721  if (dl_lib_filename.empty())
2722  return;
2723 
2724  const auto & [dir, file_name] = MooseUtils::splitFileName(library_filename);
2725 
2726  // Time to load the library, First see if we've already loaded this particular dynamic library
2727  // 1) make sure we haven't already loaded this library
2728  // AND 2) make sure we have a library name (we won't for static linkage)
2729  // Note: Here was are going to assume uniqueness based on the filename alone. This has significant
2730  // implications for applications that have "diamond" inheritance of libraries (usually
2731  // modules). We will only load one of those libraries, versions be damned.
2732  auto dyn_lib_it = _lib_handles.find(file_name);
2733  if (dyn_lib_it == _lib_handles.end())
2734  {
2735  // Assemble the actual filename using the base path of the *.la file and the dl_lib_filename
2736  const auto dl_lib_full_path = MooseUtils::pathjoin(dir, dl_lib_filename);
2737 
2738  MooseUtils::checkFileReadable(dl_lib_full_path, false, /*throw_on_unreadable=*/true);
2739 
2740 #ifdef LIBMESH_HAVE_DLOPEN
2741  void * const lib_handle = dlopen(dl_lib_full_path.c_str(), RTLD_LAZY);
2742 #else
2743  void * const lib_handle = nullptr;
2744 #endif
2745 
2746  if (!lib_handle)
2747  mooseError("The library file \"",
2748  dl_lib_full_path,
2749  "\" exists and has proper permissions, but cannot by dynamically loaded.\nThis "
2750  "generally means that the loader was unable to load one or more of the "
2751  "dependencies listed in the supplied library (see otool or ldd).\n",
2752  dlerror());
2753 
2754  DynamicLibraryInfo lib_info;
2755  lib_info.library_handle = lib_handle;
2756  lib_info.full_path = library_filename;
2757 
2758  auto insert_ret = _lib_handles.insert(std::make_pair(file_name, lib_info));
2759  mooseAssert(insert_ret.second == true, "Error inserting into lib_handles map");
2760 
2761  dyn_lib_it = insert_ret.first;
2762  }
2763 
2764  // Library has been loaded, check to see if we've called the requested registration method
2765  const auto registration_method = params.get<std::string>("registration_method");
2766  auto & entry_sym_from_curr_lib = dyn_lib_it->second.entry_symbols;
2767 
2768  if (entry_sym_from_curr_lib.find(registration_method) == entry_sym_from_curr_lib.end())
2769  {
2770  // get the pointer to the method in the library. The dlsym()
2771  // function returns a null pointer if the symbol cannot be found,
2772  // we also explicitly set the pointer to NULL if dlsym is not
2773  // available.
2774 #ifdef LIBMESH_HAVE_DLOPEN
2775  void * registration_handle =
2776  dlsym(dyn_lib_it->second.library_handle, registration_method.c_str());
2777 #else
2778  void * registration_handle = nullptr;
2779 #endif
2780 
2781  if (registration_handle)
2782  {
2783  switch (params.get<RegistrationType>("reg_type"))
2784  {
2785  case APPLICATION:
2786  {
2787  using register_app_t = void (*)();
2788  register_app_t * const reg_ptr = reinterpret_cast<register_app_t *>(&registration_handle);
2789  (*reg_ptr)();
2790  break;
2791  }
2792  case REGALL:
2793  {
2794  using register_app_t = void (*)(Factory *, ActionFactory *, Syntax *);
2795  register_app_t * const reg_ptr = reinterpret_cast<register_app_t *>(&registration_handle);
2796  (*reg_ptr)(params.get<Factory *>("factory"),
2797  params.get<ActionFactory *>("action_factory"),
2798  params.get<Syntax *>("syntax"));
2799  break;
2800  }
2801  default:
2802  mooseError("Unhandled RegistrationType");
2803  }
2804 
2805  entry_sym_from_curr_lib.insert(registration_method);
2806  }
2807  else
2808  {
2809 
2810 #if defined(DEBUG) && defined(LIBMESH_HAVE_DLOPEN)
2811  // We found a dynamic library that doesn't have a dynamic
2812  // registration method in it. This shouldn't be an error, so
2813  // we'll just move on.
2814  if (!registration_handle)
2815  mooseWarning("Unable to find extern \"C\" method \"",
2816  registration_method,
2817  "\" in library: ",
2818  dyn_lib_it->first,
2819  ".\n",
2820  "This doesn't necessarily indicate an error condition unless you believe that "
2821  "the method should exist in that library.\n",
2822  dlerror());
2823 #endif
2824  }
2825  }
2826 }
2827 
2828 std::set<std::string>
2830 {
2831  // Return the paths but not the open file handles
2832  std::set<std::string> paths;
2833  for (const auto & it : _lib_handles)
2834  paths.insert(it.first);
2835 
2836  return paths;
2837 }
2838 
2839 std::set<std::string>
2840 MooseApp::getLibrarySearchPaths(const std::string & library_path) const
2841 {
2842  std::set<std::string> paths;
2843 
2844  if (!library_path.empty())
2845  {
2846  std::vector<std::string> tmp_paths;
2847  MooseUtils::tokenize(library_path, tmp_paths, 1, ":");
2848 
2849  paths.insert(tmp_paths.begin(), tmp_paths.end());
2850  }
2851 
2852  char * moose_lib_path_env = std::getenv("MOOSE_LIBRARY_PATH");
2853  if (moose_lib_path_env)
2854  {
2855  std::string moose_lib_path(moose_lib_path_env);
2856  std::vector<std::string> tmp_paths;
2857  MooseUtils::tokenize(moose_lib_path, tmp_paths, 1, ":");
2858 
2859  paths.insert(tmp_paths.begin(), tmp_paths.end());
2860  }
2861 
2862  return paths;
2863 }
2864 
2867 {
2869 }
2870 
2871 std::string
2873 {
2874  return std::string("");
2875 }
2876 
2877 void
2879 {
2880  _restart = value;
2881 }
2882 
2883 void
2885 {
2886  _recover = value;
2887 }
2888 
2889 void
2891 {
2892  TIME_SECTION("createMinimalApp", 3, "Creating Minimal App");
2893 
2894  // SetupMeshAction
2895  {
2896  // Build the Action parameters
2897  InputParameters action_params = _action_factory.getValidParams("SetupMeshAction");
2898  action_params.set<std::string>("type") = "GeneratedMesh";
2899 
2900  // Create The Action
2901  std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
2902  _action_factory.create("SetupMeshAction", "Mesh", action_params));
2903 
2904  // Set the object parameters
2905  InputParameters & params = action->getObjectParams();
2906  params.set<MooseEnum>("dim") = "1";
2907  params.set<unsigned int>("nx") = 1;
2908 
2909  // Add Action to the warehouse
2911  }
2912 
2913  // Executioner
2914  {
2915  // Build the Action parameters
2916  InputParameters action_params = _action_factory.getValidParams("CreateExecutionerAction");
2917  action_params.set<std::string>("type") = "Transient";
2918 
2919  // Create the action
2920  std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
2921  _action_factory.create("CreateExecutionerAction", "Executioner", action_params));
2922 
2923  // Set the object parameters
2924  InputParameters & params = action->getObjectParams();
2925  params.set<unsigned int>("num_steps") = 1;
2926  params.set<Real>("dt") = 1;
2927 
2928  // Add Action to the warehouse
2930  }
2931 
2932  // Problem
2933  {
2934  // Build the Action parameters
2935  InputParameters action_params = _action_factory.getValidParams("CreateProblemDefaultAction");
2936  action_params.set<bool>("_solve") = false;
2937 
2938  // Create the action
2939  std::shared_ptr<Action> action = std::static_pointer_cast<Action>(
2940  _action_factory.create("CreateProblemDefaultAction", "Problem", action_params));
2941 
2942  // Add Action to the warehouse
2944  }
2945 
2946  // Outputs
2947  {
2948  // Build the Action parameters
2949  InputParameters action_params = _action_factory.getValidParams("CommonOutputAction");
2950  action_params.set<bool>("console") = false;
2951 
2952  // Create action
2953  std::shared_ptr<Action> action =
2954  _action_factory.create("CommonOutputAction", "Outputs", action_params);
2955 
2956  // Add Action to the warehouse
2958  }
2959 
2961 }
2962 
2963 bool
2964 MooseApp::hasRelationshipManager(const std::string & name) const
2965 {
2966  return std::find_if(_relationship_managers.begin(),
2967  _relationship_managers.end(),
2968  [&name](const std::shared_ptr<RelationshipManager> & rm)
2969  { return rm->name() == name; }) != _relationship_managers.end();
2970 }
2971 
2972 namespace
2973 {
2974 void
2975 donateForWhom(const RelationshipManager & donor, RelationshipManager & acceptor)
2976 {
2977  auto & existing_for_whom = acceptor.forWhom();
2978 
2979  // Take all the for_whoms from the donor, and give them to the acceptor
2980  for (auto & fw : donor.forWhom())
2981  {
2982  if (std::find(existing_for_whom.begin(), existing_for_whom.end(), fw) ==
2983  existing_for_whom.end())
2984  acceptor.addForWhom(fw);
2985  }
2986 }
2987 }
2988 
2989 bool
2990 MooseApp::addRelationshipManager(std::shared_ptr<RelationshipManager> new_rm)
2991 {
2992  // We prefer to always add geometric RMs. There is no hurt to add RMs for replicated mesh
2993  // since MeshBase::delete_remote_elements{} is a no-op (empty) for replicated mesh.
2994  // The motivation here is that MooseMesh::_use_distributed_mesh may not be properly set
2995  // at the time we are adding geometric relationship managers. We deleted the following
2996  // old logic to add all geometric RMs regardless of there is a distributed mesh or not.
2997  // Otherwise, all geometric RMs will be improperly ignored for a distributed mesh generator.
2998 
2999  // if (!_action_warehouse.mesh()->isDistributedMesh() && !_split_mesh &&
3000  // (relationship_manager->isType(Moose::RelationshipManagerType::GEOMETRIC) &&
3001  // !(relationship_manager->isType(Moose::RelationshipManagerType::ALGEBRAIC) ||
3002  // relationship_manager->isType(Moose::RelationshipManagerType::COUPLING))))
3003  // return false;
3004 
3005  bool add = true;
3006 
3007  std::set<std::shared_ptr<RelationshipManager>> rms_to_erase;
3008 
3009  for (const auto & existing_rm : _relationship_managers)
3010  {
3011  if (*existing_rm >= *new_rm)
3012  {
3013  add = false;
3014  donateForWhom(*new_rm, *existing_rm);
3015  break;
3016  }
3017  // The new rm did not provide less or the same amount/type of ghosting as the existing rm, but
3018  // what about the other way around?
3019  else if (*new_rm >= *existing_rm)
3020  rms_to_erase.emplace(existing_rm);
3021  }
3022 
3023  if (add)
3024  {
3025  _relationship_managers.emplace(new_rm);
3026  for (const auto & rm_to_erase : rms_to_erase)
3027  {
3028  donateForWhom(*rm_to_erase, *new_rm);
3029  removeRelationshipManager(rm_to_erase);
3030  }
3031  }
3032 
3033  // Inform the caller whether the object was added or not
3034  return add;
3035 }
3036 
3037 const std::string &
3039 {
3040  static const std::string suffix = "-mesh.cpa.gz";
3041  return suffix;
3042 }
3043 
3044 std::filesystem::path
3045 MooseApp::metaDataFolderBase(const std::filesystem::path & folder_base,
3046  const std::string & map_suffix)
3047 {
3048  return RestartableDataIO::restartableDataFolder(folder_base /
3049  std::filesystem::path("meta_data" + map_suffix));
3050 }
3051 
3052 std::filesystem::path
3053 MooseApp::restartFolderBase(const std::filesystem::path & folder_base) const
3054 {
3055  auto folder = folder_base;
3056  folder += "-restart-" + std::to_string(processor_id());
3058 }
3059 
3060 const hit::Node *
3062 {
3063  if (const auto action = _action_warehouse.getCurrentAction())
3064  return action->parameters().getHitNode();
3065  return nullptr;
3066 }
3067 
3068 bool
3069 MooseApp::hasRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const
3070 {
3071  auto it = _template_to_clones.find(&template_rm);
3072  // C++ does short circuiting so we're safe here
3073  return (it != _template_to_clones.end()) && (it->second.find(&mesh) != it->second.end());
3074 }
3075 
3077 MooseApp::getRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const
3078 {
3079  auto outer_it = _template_to_clones.find(&template_rm);
3080  if (outer_it == _template_to_clones.end())
3081  mooseError("The template rm does not exist in our _template_to_clones map");
3082 
3083  auto & mesh_to_clone_map = outer_it->second;
3084  auto inner_it = mesh_to_clone_map.find(&mesh);
3085  if (inner_it == mesh_to_clone_map.end())
3086  mooseError("We should have the mesh key in our mesh");
3087 
3088  return *inner_it->second;
3089 }
3090 
3091 void
3092 MooseApp::removeRelationshipManager(std::shared_ptr<RelationshipManager> rm)
3093 {
3094  auto * const mesh = _action_warehouse.mesh().get();
3095  if (!mesh)
3096  mooseError("The MooseMesh should exist");
3097 
3098  const MeshBase * const undisp_lm_mesh = mesh->getMeshPtr();
3099  RelationshipManager * undisp_clone = nullptr;
3100  if (undisp_lm_mesh && hasRMClone(*rm, *undisp_lm_mesh))
3101  {
3102  undisp_clone = &getRMClone(*rm, *undisp_lm_mesh);
3103  const_cast<MeshBase *>(undisp_lm_mesh)->remove_ghosting_functor(*undisp_clone);
3104  }
3105 
3106  auto & displaced_mesh = _action_warehouse.displacedMesh();
3107  MeshBase * const disp_lm_mesh = displaced_mesh ? &displaced_mesh->getMesh() : nullptr;
3108  RelationshipManager * disp_clone = nullptr;
3109  if (disp_lm_mesh && hasRMClone(*rm, *disp_lm_mesh))
3110  {
3111  disp_clone = &getRMClone(*rm, *disp_lm_mesh);
3112  disp_lm_mesh->remove_ghosting_functor(*disp_clone);
3113  }
3114 
3115  if (_executioner)
3116  {
3117  auto & problem = feProblem();
3118  if (undisp_clone)
3119  {
3120  problem.removeAlgebraicGhostingFunctor(*undisp_clone);
3121  problem.removeCouplingGhostingFunctor(*undisp_clone);
3122  }
3123 
3124  auto * dp = problem.getDisplacedProblem().get();
3125  if (dp && disp_clone)
3126  dp->removeAlgebraicGhostingFunctor(*disp_clone);
3127  }
3128 
3129  _factory.releaseSharedObjects(*rm);
3130  _relationship_managers.erase(rm);
3131 }
3132 
3135  MooseMesh & moose_mesh,
3136  MeshBase & mesh,
3137  const DofMap * const dof_map)
3138 {
3139  auto & mesh_to_clone = _template_to_clones[&template_rm];
3140  auto it = mesh_to_clone.find(&mesh);
3141  if (it != mesh_to_clone.end())
3142  {
3143  // We've already created a clone for this mesh
3144  auto & clone_rm = *it->second;
3145  if (!clone_rm.dofMap() && dof_map)
3146  // We didn't have a DofMap before, but now we do, so we should re-init
3147  clone_rm.init(moose_mesh, mesh, dof_map);
3148  else if (clone_rm.dofMap() && dof_map && (clone_rm.dofMap() != dof_map))
3149  mooseError("Attempting to create and initialize an existing clone with a different DofMap. "
3150  "This should not happen.");
3151 
3152  return clone_rm;
3153  }
3154 
3155  // It's possible that this method is going to get called for multiple different MeshBase
3156  // objects. If that happens, then we *cannot* risk having a MeshBase object with a ghosting
3157  // functor that is init'd with another MeshBase object. So the safe thing to do is to make a
3158  // different RM for every MeshBase object that gets called here. Then the
3159  // RelationshipManagers stored here in MooseApp are serving as a template only
3160  auto pr = mesh_to_clone.emplace(
3161  std::make_pair(&const_cast<const MeshBase &>(mesh),
3162  dynamic_pointer_cast<RelationshipManager>(template_rm.clone())));
3163  mooseAssert(pr.second, "An insertion should have happened");
3164  auto & clone_rm = *pr.first->second;
3165  clone_rm.init(moose_mesh, mesh, dof_map);
3166  return clone_rm;
3167 }
3168 
3169 void
3171 {
3172  for (auto & rm : _relationship_managers)
3173  {
3175  {
3176  if (rm->attachGeometricEarly())
3177  {
3178  mesh.add_ghosting_functor(createRMFromTemplateAndInit(*rm, moose_mesh, mesh));
3180  }
3181  else
3182  {
3183  // If we have a geometric ghosting functor that can't be attached early, then we have to
3184  // prevent the mesh from deleting remote elements
3185  moose_mesh.allowRemoteElementRemoval(false);
3186 
3187  if (const MeshBase * const moose_mesh_base = moose_mesh.getMeshPtr())
3188  {
3189  if (moose_mesh_base != &mesh)
3190  mooseError("The MooseMesh MeshBase and the MeshBase we're trying to attach "
3191  "relationship managers to are different");
3192  }
3193  else
3194  // The MeshBase isn't attached to the MooseMesh yet, so have to tell it not to remove
3195  // remote elements independently
3197  }
3198  }
3199  }
3200 }
3201 
3202 void
3204  bool attach_geometric_rm_final)
3205 {
3206  for (auto & rm : _relationship_managers)
3207  {
3208  if (!rm->isType(rm_type))
3209  continue;
3210 
3211  // RM is already attached (this also handles the geometric early case)
3212  if (_attached_relationship_managers[rm_type].count(rm.get()))
3213  continue;
3214 
3216  {
3217  // The problem is not built yet - so the ActionWarehouse currently owns the mesh
3218  MooseMesh * const mesh = _action_warehouse.mesh().get();
3219 
3220  // "attach_geometric_rm_final = true" inidicate that it is the last chance to attach
3221  // geometric RMs. Therefore, we need to attach them.
3222  if (!rm->attachGeometricEarly() && !attach_geometric_rm_final)
3223  // Will attach them later (during algebraic). But also, we need to tell the mesh that we
3224  // shouldn't be deleting remote elements yet
3225  mesh->allowRemoteElementRemoval(false);
3226  else
3227  {
3228  MeshBase & undisp_mesh_base = mesh->getMesh();
3229  const DofMap * const undisp_sys_dof_map =
3230  _executioner ? &feProblem().getSolverSystem(0).dofMap() : nullptr;
3231  undisp_mesh_base.add_ghosting_functor(
3232  createRMFromTemplateAndInit(*rm, *mesh, undisp_mesh_base, undisp_sys_dof_map));
3233 
3234  // In the final stage, if there is a displaced mesh, we need to
3235  // clone ghosting functors for displacedMesh
3236  if (auto & disp_moose_mesh = _action_warehouse.displacedMesh();
3237  attach_geometric_rm_final && disp_moose_mesh)
3238  {
3239  MeshBase & disp_mesh_base = _action_warehouse.displacedMesh()->getMesh();
3240  const DofMap * disp_sys_dof_map = nullptr;
3241  if (_executioner && feProblem().getDisplacedProblem())
3242  disp_sys_dof_map = &feProblem().getDisplacedProblem()->solverSys(0).dofMap();
3243  disp_mesh_base.add_ghosting_functor(
3244  createRMFromTemplateAndInit(*rm, *disp_moose_mesh, disp_mesh_base, disp_sys_dof_map));
3245  }
3246  else if (_action_warehouse.displacedMesh())
3247  mooseError("The displaced mesh should not yet exist at the time that we are attaching "
3248  "early geometric relationship managers.");
3249 
3250  // Mark this RM as attached
3251  mooseAssert(!_attached_relationship_managers[rm_type].count(rm.get()), "Already attached");
3252  _attached_relationship_managers[rm_type].insert(rm.get());
3253  }
3254  }
3255  else // rm_type is algebraic or coupling
3256  {
3257  if (!_executioner && !_executor)
3258  mooseError("We must have an executioner by now or else we do not have to data to add "
3259  "algebraic or coupling functors to in MooseApp::attachRelationshipManagers");
3260 
3261  // Now we've built the problem, so we can use it
3262  auto & problem = feProblem();
3263  auto & undisp_moose_mesh = problem.mesh();
3264  auto & undisp_sys = feProblem().getSolverSystem(0);
3265  auto & undisp_sys_dof_map = undisp_sys.dofMap();
3266  auto & undisp_mesh = undisp_moose_mesh.getMesh();
3267 
3268  if (rm->useDisplacedMesh() && problem.getDisplacedProblem())
3269  {
3271  // We actually need to add this to the FEProblemBase NonlinearSystemBase's DofMap
3272  // because the DisplacedProblem "nonlinear" DisplacedSystem doesn't have any matrices
3273  // for which to do coupling. It's actually horrifying to me that we are adding a
3274  // coupling functor, that is going to determine its couplings based on a displaced
3275  // MeshBase object, to a System associated with the undisplaced MeshBase object (there
3276  // is only ever one EquationSystems object per MeshBase object and visa versa). So here
3277  // I'm left with the choice of whether to pass in a MeshBase object that is *not* the
3278  // MeshBase object that will actually determine the couplings or to pass in the MeshBase
3279  // object that is inconsistent with the System DofMap that we are adding the coupling
3280  // functor for! Let's err on the side of *libMesh* consistency and pass properly paired
3281  // MeshBase-DofMap
3282  problem.addCouplingGhostingFunctor(
3283  createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
3284  /*to_mesh = */ false);
3285 
3286  else if (rm_type == Moose::RelationshipManagerType::ALGEBRAIC)
3287  {
3288  auto & displaced_problem = *problem.getDisplacedProblem();
3289  auto & disp_moose_mesh = displaced_problem.mesh();
3290  auto & disp_mesh = disp_moose_mesh.getMesh();
3291  const DofMap * const disp_nl_dof_map = &displaced_problem.solverSys(0).dofMap();
3292  displaced_problem.addAlgebraicGhostingFunctor(
3293  createRMFromTemplateAndInit(*rm, disp_moose_mesh, disp_mesh, disp_nl_dof_map),
3294  /*to_mesh = */ false);
3295  }
3296  }
3297  else // undisplaced
3298  {
3300  problem.addCouplingGhostingFunctor(
3301  createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
3302  /*to_mesh = */ false);
3303 
3304  else if (rm_type == Moose::RelationshipManagerType::ALGEBRAIC)
3305  problem.addAlgebraicGhostingFunctor(
3306  createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
3307  /*to_mesh = */ false);
3308  }
3309 
3310  // Mark this RM as attached
3311  mooseAssert(!_attached_relationship_managers[rm_type].count(rm.get()), "Already attached");
3312  _attached_relationship_managers[rm_type].insert(rm.get());
3313  }
3314  }
3315 }
3316 
3317 std::vector<std::pair<std::string, std::string>>
3319 {
3320  std::vector<std::pair<std::string, std::string>> info_strings;
3321  info_strings.reserve(_relationship_managers.size());
3322 
3323  for (const auto & rm : _relationship_managers)
3324  {
3325  std::stringstream oss;
3326  oss << rm->getInfo();
3327 
3328  auto & for_whom = rm->forWhom();
3329 
3330  if (!for_whom.empty())
3331  {
3332  oss << " for ";
3333 
3334  std::copy(for_whom.begin(), for_whom.end(), infix_ostream_iterator<std::string>(oss, ", "));
3335  }
3336 
3337  info_strings.emplace_back(std::make_pair(Moose::stringify(rm->getType()), oss.str()));
3338  }
3339 
3340  // List the libMesh GhostingFunctors - Not that in libMesh all of the algebraic and coupling
3341  // Ghosting Functors are also attached to the mesh. This should catch them all.
3342  const auto & mesh = _action_warehouse.getMesh();
3343  if (mesh)
3344  {
3345  // Let us use an ordered map to avoid stochastic console behaviors.
3346  // I believe we won't have many RMs, and there is no performance issue.
3347  // Deterministic behaviors are good for setting up regression tests
3348  std::map<std::string, unsigned int> counts;
3349 
3350  for (auto & gf : as_range(mesh->getMesh().ghosting_functors_begin(),
3351  mesh->getMesh().ghosting_functors_end()))
3352  {
3353  const auto * gf_ptr = dynamic_cast<const RelationshipManager *>(gf);
3354  if (!gf_ptr)
3355  // Count how many occurences of the same Ghosting Functor types we are encountering
3356  counts[demangle(typeid(*gf).name())]++;
3357  }
3358 
3359  for (const auto & pair : counts)
3360  info_strings.emplace_back(std::make_pair(
3361  "Default", pair.first + (pair.second > 1 ? " x " + std::to_string(pair.second) : "")));
3362  }
3363 
3364  // List the libMesh GhostingFunctors - Not that in libMesh all of the algebraic and coupling
3365  // Ghosting Functors are also attached to the mesh. This should catch them all.
3366  const auto & d_mesh = _action_warehouse.getDisplacedMesh();
3367  if (d_mesh)
3368  {
3369  // Let us use an ordered map to avoid stochastic console behaviors.
3370  // I believe we won't have many RMs, and there is no performance issue.
3371  // Deterministic behaviors are good for setting up regression tests
3372  std::map<std::string, unsigned int> counts;
3373 
3374  for (auto & gf : as_range(d_mesh->getMesh().ghosting_functors_begin(),
3375  d_mesh->getMesh().ghosting_functors_end()))
3376  {
3377  const auto * gf_ptr = dynamic_cast<const RelationshipManager *>(gf);
3378  if (!gf_ptr)
3379  // Count how many occurences of the same Ghosting Functor types we are encountering
3380  counts[demangle(typeid(*gf).name())]++;
3381  }
3382 
3383  for (const auto & pair : counts)
3384  info_strings.emplace_back(
3385  std::make_pair("Default",
3386  pair.first + (pair.second > 1 ? " x " + std::to_string(pair.second) : "") +
3387  " for DisplacedMesh"));
3388  }
3389 
3390  return info_strings;
3391 }
3392 
3393 void
3395 {
3396  for (auto map_iter = _restartable_meta_data.begin(); map_iter != _restartable_meta_data.end();
3397  ++map_iter)
3398  {
3399  const RestartableDataMapName & name = map_iter->first;
3400  const RestartableDataMap & meta_data = map_iter->second.first;
3401 
3402  std::vector<std::string> not_declared;
3403 
3404  for (const auto & data : meta_data)
3405  if (!data.declared())
3406  not_declared.push_back(data.name());
3407 
3408  if (!not_declared.empty())
3409  {
3410  std::ostringstream oss;
3411  std::copy(
3412  not_declared.begin(), not_declared.end(), infix_ostream_iterator<std::string>(oss, ", "));
3413 
3414  mooseError("The following '",
3415  name,
3416  "' meta-data properties were retrieved but never declared: ",
3417  oss.str());
3418  }
3419  }
3420 }
3421 
3422 const RestartableDataMapName MooseApp::MESH_META_DATA = "MeshMetaData";
3424 
3427 {
3428  auto iter = _restartable_meta_data.find(name);
3429  if (iter == _restartable_meta_data.end())
3430  mooseError("Unable to find RestartableDataMap object for the supplied name '",
3431  name,
3432  "', did you call registerRestartableDataMapName in the application constructor?");
3433  return iter->second.first;
3434 }
3435 
3436 bool
3438 {
3439  return _restartable_meta_data.count(name);
3440 }
3441 
3442 void
3444 {
3445  if (!suffix.empty())
3446  std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
3447  suffix.insert(0, "_");
3448  _restartable_meta_data.emplace(
3449  std::make_pair(name, std::make_pair(RestartableDataMap(), suffix)));
3450 }
3451 
3452 const std::string &
3454 {
3455  const auto it = _restartable_meta_data.find(name);
3456  if (it == _restartable_meta_data.end())
3457  mooseError("MooseApp::getRestartableDataMapName: The name '", name, "' is not registered");
3458  return it->second.second;
3459 }
3460 
3461 PerfGraph &
3463 {
3465 
3466  auto perf_graph =
3467  std::make_unique<RestartableData<PerfGraph>>("perf_graph",
3468  this,
3469  type() + " (" + name() + ')',
3470  *this,
3471  getParam<bool>("perf_graph_live_all"),
3472  !getParam<bool>("disable_perf_graph_live"));
3473 
3474  return dynamic_cast<RestartableData<PerfGraph> &>(
3475  registerRestartableData(std::move(perf_graph), 0, false))
3476  .set();
3477 }
3478 
3481 {
3483 
3484  auto solution_invalidity =
3485  std::make_unique<RestartableData<SolutionInvalidity>>("solution_invalidity", nullptr, *this);
3486 
3487  return dynamic_cast<RestartableData<SolutionInvalidity> &>(
3488  registerRestartableData(std::move(solution_invalidity), 0, false))
3489  .set();
3490 }
3491 
3492 bool
3494 {
3495  return _action_warehouse.getCurrentTaskName() == "create_added_mesh_generators" ||
3497 }
3498 
3499 #ifdef MOOSE_LIBTORCH_ENABLED
3500 torch::DeviceType
3502 {
3503  const auto pname = "--compute-device";
3504  if (device_enum == "cuda")
3505  {
3506 #ifdef __linux__
3507  if (!torch::cuda::is_available())
3508  mooseError(pname, "=cuda: CUDA support is not available in the linked libtorch library");
3509  return torch::kCUDA;
3510 #else
3511  mooseError(pname, "=cuda: CUDA is not supported on your platform");
3512 #endif
3513  }
3514  else if (device_enum == "mps")
3515  {
3516 #ifdef __APPLE__
3517  if (!torch::mps::is_available())
3518  mooseError(pname, "=mps: MPS support is not available in the linked libtorch library");
3519  return torch::kMPS;
3520 #else
3521  mooseError(pname, "=mps: MPS is not supported on your platform");
3522 #endif
3523  }
3524  else if (device_enum == "xpu")
3525  {
3526 #ifdef MOOSE_HAVE_XPU
3527  if (!torch::xpu::is_available())
3528  mooseError(pname, "=xpu: XPU support is not available in the linked libtorch library");
3529  return torch::kXPU;
3530 #else
3531  mooseError(pname, "=xpu: XPU is not supported in the current application");
3532 #endif
3533  }
3534  else if (device_enum != "cpu")
3535  mooseError("The device '",
3536  device_enum,
3537  "' is not currently supported by the MOOSE libtorch integration.");
3538  return torch::kCPU;
3539 }
3540 #endif
3541 
3542 void
3543 MooseApp::outputMachineReadableData(const std::string & param,
3544  const std::string & start_marker,
3545  const std::string & end_marker,
3546  const std::string & data) const
3547 {
3548  // Bool parameter, just to screen
3549  if (_pars.have_parameter<bool>(param))
3550  {
3551  Moose::out << start_marker << data << end_marker << std::endl;
3552  return;
3553  }
3554 
3555  // String parameter, to file
3556  const auto & filename = getParam<std::string>(param);
3557  // write to file
3558  std::ofstream out(filename.c_str());
3559  if (out.is_open())
3560  {
3561  std::ofstream out(filename.c_str());
3562  out << data << std::flush;
3563  out.close();
3564  }
3565  else
3566  mooseError("Unable to open file `", filename, "` for writing ", param, " data to it.");
3567 }
3568 
3570 MooseApp::addBoolCapability(const std::string_view capability,
3571  const bool value,
3572  const std::string_view doc)
3573 {
3574  return addCapabilityInternal(capability, value, doc);
3575 }
3576 
3578 MooseApp::addIntCapability(const std::string_view capability,
3579  const int value,
3580  const std::string_view doc)
3581 {
3582  return addCapabilityInternal(capability, value, doc);
3583 }
3584 
3586 MooseApp::addStringCapability(const std::string_view capability,
3587  const std::string_view value,
3588  const std::string_view doc)
3589 {
3590  return addCapabilityInternal(capability, std::string(value), doc);
3591 }
3592 
3594 MooseApp::addCapability(const std::string_view capability,
3595  const Moose::Capability::Value & value,
3596  const std::string_view doc)
3597 {
3598 
3599  // Warn deprecation on the first time this is added so that we
3600  // don't get multiple warnings if the app is registered more
3601  // than once
3602  if (!Moose::internal::Capabilities::getCapabilities({}).query(std::string(capability)))
3603  ::mooseDeprecated("MooseApp::addCapability() is deprecated (adding capability '",
3604  capability,
3605  "'); use one of MooseApp::add[Bool,Int,String]Capability instead.");
3606 
3607  return addCapabilityInternal(capability, value, doc);
3608 }
3609 
3610 bool
3612 {
3614 }
3615 
3616 bool
3618 {
3620 }
3621 
3622 #ifdef MOOSE_MFEM_ENABLED
3623 void
3624 MooseApp::setMFEMDevice(const std::string & device_string,
3625  bool gpu_aware_mpi,
3627 {
3628  const auto string_vec = MooseUtils::split(device_string, ",");
3629  auto string_set = std::set<std::string>(string_vec.begin(), string_vec.end());
3630  if (!_mfem_device)
3631  {
3632  _mfem_device = std::make_shared<mfem::Device>(device_string);
3633  _mfem_devices = std::move(string_set);
3634  _mfem_device->SetGPUAwareMPI(mfem::GetEnv("MFEM_GPU_AWARE_MPI") ? true : gpu_aware_mpi);
3635  _mfem_device->Print(Moose::out);
3636  }
3637  else if (!device_string.empty() && string_set != _mfem_devices)
3638  mooseError("Attempted to configure with "
3639  "MFEM devices '",
3640  MooseUtils::join(string_set, " "),
3641  "', but we have already "
3642  "configured the MFEM device "
3643  "object with the devices '",
3644  MooseUtils::join(_mfem_devices, " "),
3645  "'");
3646 }
3647 #endif
void makedirs(const std::string &dir_name, bool throw_on_failure)
Definition: MooseUtils.C:449
std::string name(const ElemQuality q)
GhostingFunctorIterator ghosting_functors_begin() const
std::list< std::string > getCheckpointFiles() const
Extract all possible checkpoint file names.
Definition: MooseApp.C:2388
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Definition: MooseApp.C:3493
std::list< std::string > getCheckpointDirectories() const
Get all checkpoint directories.
Definition: MooseApp.C:2356
OStreamProxy err
static const std::string & checkpointSuffix()
The file suffix for the checkpoint mesh.
Definition: MooseApp.C:3038
std::string getFileName(bool stripLeadingPath=true) const
Return the primary (first) filename that was parsed Note: When stripLeadingPath is false...
Definition: MooseApp.C:2402
void mooseInfo(Args &&... args) const
Definition: MooseBase.h:344
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:2100
virtual void meshChanged(bool intermediate_change, bool contract_mesh, bool clean_refinement_flags)
Update data after a mesh change.
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:284
std::string docsDir(const std::string &app_name)
Definition: MooseUtils.C:125
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 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:1870
virtual std::string getPrintableName() const
Get printable name of the application.
Definition: MooseApp.h:148
virtual std::string getInstallableInputs() const
Method to retrieve the installable inputs from a given applications <app>Revision.h file.
Definition: MooseApp.C:2202
void write(std::ostream &header_stream, std::ostream &data_stream)
Writes the restartable data to header stream header_stream and data stream data_stream.
static bool isRelocated()
Definition: MooseApp.C:3611
PerfGraph & _perf_graph
The PerfGraph object for this application (recoverable)
Definition: MooseApp.h:1355
void setOutputPosition(const Point &p)
Tell the app to output in a specific position.
Definition: MooseApp.C:2345
virtual void write(const std::string &name) override
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
const bool _check_input
true if we want to just check the input file
Definition: MooseApp.h:1451
void setGlobalCommandLineParam(const std::string &name)
Sets the command line parameter with name as global.
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
static const RegistryEntryBase & objData(const std::string &name)
Definition: Registry.C:58
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition: MooseApp.h:866
Storage container for all InputParamter objects.
std::map< Moose::RelationshipManagerType, std::set< const RelationshipManager * > > _attached_relationship_managers
The relationship managers that have been attached (type -> RMs)
Definition: MooseApp.h:1458
unsigned int n_threads()
const InputParameters & _pars
The object&#39;s parameters.
Definition: MooseBase.h:394
Reader for restartable data written by the RestartableDataWriter.
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
void dynamicRegistration(const libMesh::Parameters &params)
Helper method for dynamic loading of objects.
Definition: MooseApp.C:2666
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 ...
bool hasRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname) const
Definition: MooseApp.C:2500
virtual void setupOptions()
Setup options based on InputParameters.
Definition: MooseApp.C:1024
PerfGraph & createRecoverablePerfGraph()
Creates a recoverable PerfGraph.
Definition: MooseApp.C:3462
std::shared_ptr< DisplacedProblem > displaced_problem
std::string libNameToAppName(const std::string &library_name) const
Converts a library name to an application name:
Definition: MooseApp.C:2436
const unsigned int invalid_uint
RelationshipManagerType
Main types of Relationship Managers.
Definition: MooseTypes.h:1012
const std::shared_ptr< Parser > _parser
Parser for parsing the input file (owns the root hit node)
Definition: MooseApp.h:1334
std::string getFrameworkVersion() const
Returns the framework version.
Definition: MooseApp.C:1006
Base class for everything in MOOSE with a name and a type.
Definition: MooseBase.h:49
const std::multimap< std::string, ActionInfo > & getAssociatedActions() const
Return all Syntax to Action associations.
Definition: Syntax.C:374
void setRecover(bool value)
Definition: MooseApp.C:2884
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
std::vector< std::pair< std::string, std::string > > getRelationshipManagerInfo() const
Returns the Relationship managers info suitable for printing.
Definition: MooseApp.C:3318
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseBase.h:416
bool hasRMClone(const RelationshipManager &template_rm, const MeshBase &mesh) const
Definition: MooseApp.C:3069
torch::DeviceType determineLibtorchDeviceType(const MooseEnum &device) const
Function to determine the device which should be used by libtorch on this application.
Definition: MooseApp.C:3501
bool _file_base_set_by_user
Whether or not file base is set through input or setOutputFileBase by MultiApp.
Definition: MooseApp.h:1300
const Capability & get(const std::string &capability) const
Get a capability.
const Action * getCurrentAction() const
bool _output_position_set
Whether or not an output position has been set for this app.
Definition: MooseApp.h:1303
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 addDependency(const std::string &task, const std::string &pre_req)
Definition: Syntax.C:60
std::unique_ptr< TheWarehouse > _the_warehouse
The combined warehouse for storing any MooseObject based object.
Definition: MooseApp.h:1674
InputParameters getValidParams(const std::string &name)
Definition: ActionFactory.C:94
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:1839
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
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 hasInitialBackup() const
Definition: MooseApp.h:1047
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...
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:3045
bool _warnings_are_errors
Variable to toggle any warning into an error (includes deprecated code warnings)
Definition: Moose.C:904
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:2866
bool tokenizeAndConvert(const std::string &str, std::vector< T > &tokenized_vector, const std::string &delimiter=" \\\)
tokenizeAndConvert splits a string using delimiter and then converts to type T.
static const RestartableDataMapName MESH_META_DATA
Definition: MooseApp.h:136
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 registerTaskName(const std::string &task, bool should_auto_build=false)
Method to register a new task.
Definition: Syntax.C:20
static Capabilities & getCapabilities(const GetCapabilitiesPassKey)
Get the singleton Capabilities.
Definition: Capabilities.C:52
virtual const std::type_info & typeId() const =0
The type ID of the underlying data.
std::shared_ptr< MooseMesh > & displacedMesh()
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:248
virtual std::unique_ptr< GhostingFunctor > clone() const=0
virtual std::string appBinaryName() const
Definition: MooseApp.h:150
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
const std::shared_ptr< MooseMesh > & getMesh() const
std::string getOutputFileBase(bool for_non_moose_build_output=false) const
Get the output file base name.
Definition: MooseApp.C:1531
static void addInputParam(InputParameters &params)
Definition: MooseApp.C:271
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:3077
void setFinalTask(const std::string &task)
void deallocateKokkosMemoryPool()
Deallocate Kokkos memory pool.
bool runInputs()
Handles the run input parameter logic: Checks to see whether a directory exists in user space and lau...
Definition: MooseApp.C:2273
void registerRestartableNameWithFilter(const std::string &name, Moose::RESTARTABLE_FILTER filter)
NOTE: This is an internal function meant for MOOSE use only!
Definition: MooseApp.C:1700
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
virtual void run()
Run the application.
Definition: MooseApp.C:2026
void removeRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Purge this relationship manager from meshes and DofMaps and finally from us.
Definition: MooseApp.C:3092
Real _start_time
The time at which to start the simulation.
Definition: MooseApp.h:1312
Writer for restartable data, to be read by the RestartableDataReader.
This attribute describes sorting state.
Definition: TheWarehouse.h:113
void createExecutors()
After adding all of the Executor Params - this function will actually cause all of them to be built...
Definition: MooseApp.C:1943
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:1891
bool forceRestart() const
Whether or not we are forcefully restarting (allowing the load of potentially incompatibie checkpoint...
Definition: MooseApp.h:1114
std::filesystem::path restartFolderBase(const std::filesystem::path &folder_base) const
The file suffix for restartable data.
Definition: MooseApp.C:3053
const bool _use_split
Whether or not we are using a (pre-)split mesh (automatically DistributedMesh)
Definition: MooseApp.h:1431
void remove_ghosting_functor(GhostingFunctor &ghosting_functor)
MeshBase & mesh
void registerPetscCitation(const std::string &bibtex)
Register a BibTeX entry with PETSc&#39;s citation list so that it is printed (alongside the run-specific ...
bool hasRelationshipManager(const std::string &name) const
Returns a Boolean indicating whether a RelationshipManater exists with the same name.
Definition: MooseApp.C:2964
Base class for MOOSE-based applications.
Definition: MooseApp.h:109
virtual ~MooseApp()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:314
static bool isInTree()
Definition: MooseApp.C:3617
const Parallel::Communicator & comm() const
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:3594
bool hasRestartableDataMap(const RestartableDataMapName &name) const
Definition: MooseApp.C:3437
void addActionBlock(std::shared_ptr< Action > blk)
This method add an Action instance to the warehouse.
void restoreMeshFromInitialBackup(MooseMesh &mesh)
Restore mesh from this app&#39;s initial Backup object and consume the mesh checkpoint entries...
Definition: MooseApp.C:1748
std::set< std::string > _mfem_devices
MFEM supported devices based on user-provided config.
Definition: MooseApp.h:1751
Syntax _syntax
Syntax of the input file.
Definition: MooseApp.h:1318
Syntax & syntax()
Returns a writable reference to the syntax object.
Definition: MooseApp.h:231
std::map< std::string, std::shared_ptr< Executor > > _executors
Pointers to all of the Executors for this run.
Definition: MooseApp.h:1370
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:2551
ExecuteMooseObjectWarehouse< MultiApp > & getMultiAppWarehouse()
bool _trap_fpe
Whether or not FPE trapping should be turned on.
Definition: MooseApp.h:1437
int exitCode() const
Get the shell exit code for the application.
Definition: MooseApp.h:163
GhostingFunctorIterator ghosting_functors_end() const
processor_id_type processor_id() const
Returns the MPI processor ID of the current processor.
Definition: MooseApp.h:417
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:243
std::string installedInputsDir(const std::string &app_name, const std::string &dir_name, const std::string &extra_error_msg)
Definition: MooseUtils.C:103
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
Helper class to hold streams for Backup and Restore operations.
Definition: Backup.h:25
const hit::Node * getCurrentActionHitNode() const
Definition: MooseApp.C:3061
ActionWarehouse _action_warehouse
Where built actions are stored.
Definition: MooseApp.h:1328
std::string realpath(const std::string &path)
Definition: MooseUtils.C:1125
RestartableDataReader _rd_reader
Definition: MooseApp.h:1697
void checkMetaDataIntegrity() const
Function to check the integrity of the restartable meta data structure.
Definition: MooseApp.C:3394
const std::list< Action * > & getActionListByName(const std::string &task) const
Retrieve a constant list of Action pointers associated with the passed in task.
virtual const std::vector< std::string > & forWhom() const
The object (or Action) this RelationshipManager was built for.
static InputParameters validParams()
Definition: MooseApp.C:278
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition: MooseApp.C:1674
bool isSplitMesh() const
Whether or not this is a split mesh operation.
Definition: MooseApp.C:1680
RestartableDataMap & getRestartableDataMap(const RestartableDataMapName &name)
Return a reference to restartable data for the specific type flag.
Definition: MooseApp.C:3426
Holds the syntax in a Json::Value tree.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Base class for actions.
Definition: Action.h:34
std::string hostname()
Definition: MooseUtils.C:624
FEProblemBase & feProblem() const
Definition: MooseApp.C:1851
std::shared_ptr< Action > create(const std::string &action, const std::string &action_name, InputParameters &parameters)
Definition: ActionFactory.C:40
MooseApp(const InputParameters &parameters)
Constructor is protected so that this object is constructed through the AppFactory object...
Definition: MooseApp.C:624
std::optional< MooseEnum > getComputeDevice() const
Get the device accelerated computations are supposed to be running on.
void allowRemoteElementRemoval(bool allow_removal)
Set whether to allow remote element removal.
Definition: MooseMesh.C:4035
std::vector< RestartableDataMap > _restartable_data
Where the restartable data is held (indexed on tid)
Definition: MooseApp.h:1346
std::string camelCaseToUnderscore(const std::string &camel_case_name)
Definition: MooseUtils.C:568
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:3134
void setOutputFileBase(const std::string &output_file_base)
Override the selection of the output file base name.
Definition: MooseApp.C:1540
This class wraps provides and tracks access to command line parameters.
Definition: CommandLine.h:29
int _exit_code
The exit code.
Definition: MooseApp.h:1410
Storage for restartable data that is ordered based on insertion order.
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System...
std::shared_ptr< MooseMesh > & mesh()
std::variant< bool, int, std::string > Value
A capability can have a bool, int, or string value.
Definition: Capability.h:33
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:295
MeshGeneratorSystem _mesh_generator_system
The system that manages the MeshGenerators.
Definition: MooseApp.h:1692
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:3203
const MeshBase * getMeshPtr() const
Definition: MooseMesh.C:3542
bool _start_time_set
Whether or not an start time has been set.
Definition: MooseApp.h:1309
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:1164
void allow_remote_element_removal(bool allow)
void libmesh_ignore(const Args &...)
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:2529
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
bool showInputs() const
Prints a message showing the installable inputs for a given application (if getInstallableInputs has ...
Definition: MooseApp.C:2170
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition: MooseApp.C:2990
RestartableDataValue & getRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname, THREAD_ID tid)
Definition: MooseApp.C:2510
std::shared_ptr< NullExecutor > _null_executor
Used to return an executor that does nothing.
Definition: MooseApp.h:1386
const T & get(std::string_view) const
const std::string & getLastInputFileName() const
Definition: MooseApp.C:1524
virtual void preBackup()
Insertion point for other apps that is called before backup()
Definition: MooseApp.h:770
InputParameters & getObjectParams()
Retrieve the parameters of the object to be created by this action.
void setErrorOverridden()
Set a flag so that the parser will throw an error if overridden parameters are detected.
Definition: MooseApp.C:2020
void resetFileBase()
Resets the file base for all FileOutput objects.
virtual void postRestore(const bool)
Insertion point for other apps that is called after restore()
Definition: MooseApp.h:804
T command_line_value(const std::string &, T)
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:2679
virtual std::unique_ptr< Base > create()=0
Tracks the libmesh system number that a MooseObject is associated with.
Definition: Attributes.h:276
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...
bool _restart
Whether or not this is a restart run.
Definition: MooseApp.h:1425
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3548
std::unique_ptr< Backup > backup()
Backs up the application memory in a Backup.
Definition: MooseApp.C:1726
bool _deprecated_is_error
Variable to toggle only deprecated warnings as errors.
Definition: Moose.C:905
Generic AppFactory class for building Application objects.
Definition: AppFactory.h:54
RESTARTABLE_FILTER
The filter type applied to a particular piece of "restartable" data.
Definition: MooseTypes.h:840
void clearAppParams(const InputParameters &params, const ClearAppParamsKey)
Clears the stored parameters for the given application parameteres.
Definition: AppFactory.C:53
void mooseDeprecated(Args &&... args) const
Emits a deprecation warning prefixed with the object name and type, and a stack trace.
Definition: MooseBase.h:327
void meshChanged()
Calls the meshChanged method for every output object.
void setErrorOnLoadWithDifferentNumberOfProcessors(bool value)
void setActive(bool active)
Turn on or off timing.
Definition: PerfGraph.h:129
RestartableDataValue & registerRestartableData(std::unique_ptr< RestartableDataValue > data, THREAD_ID tid, bool read_only, const RestartableDataMapName &metaname="")
Definition: MooseApp.C:2448
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
void initSyntaxFormatter(SyntaxFormatterType type, bool dump_mode)
Creates a syntax formatter for printing.
Definition: Builder.C:400
Specialized factory for generic Action System objects.
Definition: ActionFactory.h:48
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:3624
void setRestart(bool value)
Sets the restart/recover flags.
Definition: MooseApp.C:2878
AttribBoundaries tracks all boundary IDs associated with an object.
Definition: Attributes.h:189
std::shared_ptr< Executioner > _executioner
Pointer to the executioner of this run (typically build by actions)
Definition: MooseApp.h:1364
static Moose::Capability & addIntCapability(const std::string_view capability, const int value, const std::string_view doc)
Register an integer capability.
Definition: MooseApp.C:3578
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:93
ActionFactory _action_factory
The Factory responsible for building Actions.
Definition: MooseApp.h:1325
std::string runTestsExecutable()
Definition: MooseUtils.C:65
An entry for a single capability.
Definition: Capability.h:29
void disableLivePrint()
Completely disables Live Print (cannot be restarted)
Definition: PerfGraph.C:68
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:93
void restoreFromInitialBackup(const bool for_restart)
Restores from a "initial" backup, that is, one set in _initial_backup.
Definition: MooseApp.C:1799
std::string underscoreToCamelCase(const std::string &underscore_name, bool leading_upper_case)
Definition: MooseUtils.C:580
const Parser & parser() const
Definition: MooseApp.C:1878
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
RegistrationType
Enumeration for holding the valid types of dynamic registrations allowed.
Definition: MooseApp.h:1667
Executioners are objects that do the actual work of solving your problem.
Definition: Executioner.h:30
enum MooseApp::UNUSED_CHECK _enable_unused_check
bool _recover
Whether or not this is a recovery run.
Definition: MooseApp.h:1422
void buildJsonSyntaxTree(JsonSyntaxTree &tree) const
Use MOOSE Factories to construct a parameter tree for documentation or echoing input.
Definition: Builder.C:417
Point _output_position
The output position.
Definition: MooseApp.h:1306
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:363
OStreamProxy err(std::cerr)
const std::shared_ptr< CommandLine > _command_line
The CommandLine object.
Definition: MooseApp.h:1337
void errorCheck(const libMesh::Parallel::Communicator &comm, bool warn_unused, bool err_unused)
Definition: Builder.C:358
const nlohmann::json & getRoot() const
Get the root of the tree.
bool _error_overridden
Indicates whether warnings or errors are displayed when overridden parameters are detected...
Definition: MooseApp.h:1405
virtual std::string getVersion() const
Returns the current version of the framework or application (default: framework version).
Definition: MooseApp.C:1012
SolutionInvalidity & createRecoverableSolutionInvalidity()
Creates a recoverable SolutionInvalidity.
Definition: MooseApp.C:3480
bool _heap_profiling
Memory profiling.
Definition: MooseApp.h:1718
std::string getPrimaryFileName(bool stripLeadingPath=true) const
Return the primary (first) filename that was parsed.
Definition: Builder.C:179
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:345
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
Class for storing and utilizing output objects.
std::string demangle(const char *name)
void addForWhom(const std::string &for_whom)
Add another name to for_whom.
Interface for objects interacting with the PerfGraph.
virtual void clear()
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition: MooseApp.C:2014
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:2840
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
The SolutionInvalidity will contain all the information about the occurrence(s) of solution invalidit...
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
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:3543
virtual Moose::FEBackend feBackend() const
static std::filesystem::path restartableDataFolder(const std::filesystem::path &folder_base)
bool meshChangedForBackup() const
Whether this app requires mesh topology data in its next Backup object.
Definition: MooseApp.h:760
virtual std::string type() const =0
String identifying the type of parameter stored.
static AppFactory & instance()
Get the instance of the AppFactory.
Definition: AppFactory.C:20
This class produces produces a dump of the InputParameters that appears like the normal input file sy...
Residual objects have this attribute.
Definition: Attributes.h:412
const std::string & getCurrentTaskName() const
const std::string & getRestartableDataMapName(const RestartableDataMapName &name) const
Definition: MooseApp.C:3453
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
Helper class that hands out input streams to a stringstream.
bool hasRecoverFileBase() const
Definition: MooseApp.C:1692
query_obj query
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
bool hasRestartRecoverFileBase() const
Return true if the recovery file base is set.
Definition: MooseApp.C:1686
void registerRestartableDataMapName(const RestartableDataMapName &name, std::string suffix="")
Reserve a location for storing custom RestartableDataMap objects.
Definition: MooseApp.C:3443
void restore(const std::filesystem::path &folder_base, const bool for_restart)
Restore an application from file.
Definition: MooseApp.C:1755
bool _trap_fpe
Variable indicating whether we will enable FPE trapping for this run.
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:2544
static bool isRegisteredObj(const std::string &name)
Definition: Registry.h:258
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition: MooseUtils.C:59
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
void addCommandLineParam(const std::string &name, const std::string &syntax, const std::string &doc_string)
virtual void executeExecutioner()
Execute the Executioner that was built.
Definition: MooseApp.C:1636
void setSinglePetscOption(const std::string &name, const std::string &value="", FEProblemBase *const problem=nullptr)
A wrapper function for dealing with different versions of PetscOptionsSetValue.
void addExecutor(const std::string &type, const std::string &name, const InputParameters &params)
Definition: MooseApp.C:1858
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
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
RelationshipManagers are used for describing what kinds of non-local resources are needed for an obje...
PetscErrorCode petscSetupOutput(CommandLine *cmd_line)
Definition: PetscSupport.C:399
void add_command_line_name(const std::string &name)
Moose::Builder _builder
Builder for building app related parser tree.
Definition: MooseApp.h:1343
const std::shared_ptr< MooseMesh > & getDisplacedMesh() const
Registry of capabilities that checks capability requirements.
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:3586
std::string RestartableDataMapName
Definition: MooseTypes.h:242
std::set< std::shared_ptr< RelationshipManager > > _relationship_managers
The relationship managers that have been added.
Definition: MooseApp.h:1454
OutputWarehouse _output_warehouse
OutputWarehouse object for this App.
Definition: MooseApp.h:1331
std::string _output_file_base
The output file basename.
Definition: MooseApp.h:1297
std::streambuf * _output_buffer_cache
Cache output buffer so the language server can turn it off then back on.
Definition: MooseApp.h:1709
bool _restored_initial_backup_mesh
Whether mesh topology has been restored from the initial Backup object.
Definition: MooseApp.h:1736
static void addAppParam(InputParameters &params)
Definition: MooseApp.C:264
bool _cpu_profiling
CPU profiling.
Definition: MooseApp.h:1715
T & set(const std::string &)
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
Concrete definition of a parameter value for a specified type.
void build()
Builds all auto-buildable tasks.
OStreamProxy out
void registerAll(Factory &f, ActionFactory &af, Syntax &s)
Register objects that are in MOOSE.
Definition: Moose.C:69
virtual void runInputFile()
Actually build everything in the input file.
Definition: MooseApp.C:1556
bool setColorConsole(bool use_color, bool force=false)
Turns color escape sequences on/off for info written to stdout.
Definition: Moose.C:861
virtual std::string header() const
Returns a string to be printed at the beginning of a simulation.
Definition: MooseApp.C:2872
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
Definition: MooseBase.h:309
IntRange< T > make_range(T beg, T end)
Holding syntax for parsing input files.
Definition: Syntax.h:21
virtual MooseMesh & mesh() override
class infix_ostream_iterator if void
Definition: InfixIterator.h:27
std::unordered_set< std::string > DataNames
static Moose::Capability & addBoolCapability(const std::string_view capability, const bool value, const std::string_view doc)
Register a boolean capability.
Definition: MooseApp.C:3570
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:281
static const std::string MESH_META_DATA_SUFFIX
Definition: MooseApp.h:137
SolverSystem & getSolverSystem(unsigned int sys_num)
Get non-constant reference to a solver system.
Factory _factory
Definition: MooseApp.h:1402
void executeAllActions()
This method loops over all actions in the warehouse and executes them.
std::unique_ptr< InputParameterWarehouse > _input_parameter_warehouse
Input parameter storage structure; unique_ptr so we can control its destruction order.
Definition: MooseApp.h:1322
const InputParameters::CommandLineMetadata & getCommandLineMetadata(const std::string &name) const
std::string getCurrentWorkingDir()
Definition: MooseUtils.C:436
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...
const std::vector< std::string > & getInputFileNames() const
Definition: MooseApp.C:1517
Tracks whether the object is on the displaced mesh.
Definition: Attributes.h:482
std::list< std::string > getFilesInDirs(const std::list< std::string > &directory_list, const bool files_only)
Definition: MooseUtils.C:808
InputStreams clear()
Clears the contents of the reader (header stream, data stream, header)
void mooseDeprecatedNoTrace(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:373
std::unique_ptr< Backup > finalizeRestore()
Finalizes (closes) the restoration process done in restore().
Definition: MooseApp.C:1806
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
bool appendingMeshGenerators() const
Whether or not mesh generators are currently being appended (append_mesh_generator task) ...
static const std::string allow_data_driven_param
The name of the boolean parameter on the MooseApp that will enable data driven generation.
std::vector< std::pair< std::string, std::string > > mesh_files
Pairs of checkpoint-relative entry names and binary payloads.
Definition: Backup.h:32
void restore(const DataNames &filter_names={})
Restores the restartable data.
std::vector< std::string > switches
The switches for the parameter (i.e., [-t, –timing])
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:2637
std::string toString(const nlohmann::json &root)
Returns a string representation of the tree in input file format.
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:2330
const DataNames & getRecoverableData() const
Return a reference to the recoverable data object.
Definition: MooseApp.h:727
void setDeclared(const SetDeclaredKey)
Sets that this restartable value has been declared.
std::vector< std::string > split(const std::string &str, const std::string &delimiter, std::size_t max_count)
Definition: MooseUtils.C:1020
const std::shared_ptr< libMesh::Parallel::Communicator > _comm
The MPI communicator this App is going to use.
Definition: MooseApp.h:1294
std::string getPrintableVersion() const
Non-virtual method for printing out the version string in a consistent format.
Definition: MooseApp.C:1018
std::shared_ptr< mfem::Device > _mfem_device
The MFEM Device object.
Definition: MooseApp.h:1748
std::vector< const T * > getActions()
Retrieve all actions in a specific type ordered by their names.
bool pathExists(const std::string &path)
Definition: MooseUtils.C:247
void createMinimalApp()
Method for creating the minimum required actions for an application (no input file) ...
Definition: MooseApp.C:2890
void setExitCode(const int exit_code)
Sets the exit code that the application will exit with.
Definition: MooseApp.h:168
Exception to be thrown whenever we have _throw_on_error set and a mooseError() is emitted...
Definition: MooseError.h:117
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition: MooseApp.C:1668
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
Definition: MooseUtils.C:254
DataNames _recoverable_data_names
Data names that will only be read from the restart file during RECOVERY.
Definition: MooseApp.h:1352
Executor * getExecutor() const
Definition: MooseApp.h:341
bool _ready_to_exit
Definition: MooseApp.h:1408
The PerfGraph will hold the master list of all registered performance segments and the head PerfNode...
Definition: PerfGraph.h:43
bool copyInputs()
Handles the copy_inputs input parameter logic: Checks to see whether the passed argument is valid (a ...
Definition: MooseApp.C:2208
bool _throw_on_error
Variable to turn on exceptions during mooseError(), should only be used within MOOSE unit tests or wh...
Definition: Moose.C:906
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:215
void clear()
This method deletes all of the Actions in the warehouse.
A scope guard that guarantees that whatever happens between when it gets created and when it is destr...
void disableCheckUnusedFlag()
Removes warnings and error checks for unrecognized variables in the input file.
Definition: MooseApp.C:1845
bool _split_mesh
Whether or not we are performing a split mesh operation (–split-mesh)
Definition: MooseApp.h:1428
void ErrorVector unsigned int
bool hasInitialBackupMesh() const
Whether this app has an initial Backup object with mesh checkpoint entries.
Definition: MooseApp.C:1742
const bool _use_executor
Indicates whether we are operating in the new/experimental executor mode instead of using the legacy ...
Definition: MooseApp.h:1383
const Elem & get(const ElemType type_in)
Abstract definition of a RestartableData value.
bool prepare(const MeshBase *mesh_to_clone)
Calls prepare_for_use() if the underlying MeshBase object isn&#39;t prepared, then communicates various b...
Definition: MooseMesh.C:385
Class for parsing input files.
Definition: Parser.h:87
void requestCitations()
Handles the –citations command-line option: registers with PETSc the BibTeX entries that should be c...
Definition: MooseApp.C:2135
Meta-action for creating common output object parameters This action serves two purpose, first it adds common output object parameters.
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
Definition: MooseApp.C:2408
std::string getExecutableName()
Gets the name of the running executable on Mac OS X and linux.
std::string appNameToLibName(const std::string &app_name) const
Converts an application name to a library name: Examples: AnimalApp -> libanimal-oprof.la (assuming METHOD=oprof) ThreeWordAnimalApp -> libthree_word_animal-dbg.la (assuming METHOD=dbg)
Definition: MooseApp.C:2420
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.
static InputParameters validParams()
Definition: MooseBase.C:28
static char addKnownLabel(const std::string &label)
addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
Definition: Registry.C:85
unsigned int THREAD_ID
Definition: MooseTypes.h:237
void setStartTime(Real time)
Set the starting time for the simulation.
Definition: MooseApp.C:2395
std::shared_ptr< Executor > _executor
Pointer to the Executor of this run.
Definition: MooseApp.h:1367
The Executor class directs the execution flow of simulations.
Definition: Executor.h:26
void add_ghosting_functor(GhostingFunctor &ghosting_functor)
std::string findTestRoot()
Definition: MooseUtils.C:75
void errorCheck()
Runs post-initialization error checking that cannot be run correctly unless the simulation has been f...
Definition: MooseApp.C:1600
std::set< std::string > getLoadedLibraryPaths() const
Return the paths of loaded libraries.
Definition: MooseApp.C:2829
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 bool isAvailable(const std::filesystem::path &folder_base)
void dynamicAppRegistration(const std::string &app_name, std::string library_path, const std::string &library_name, bool lib_load_deps)
Definition: MooseApp.C:2580
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