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