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