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