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