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