www.mooseframework.org
MooseApp.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
58 // Regular expression includes
59 #include "pcrecpp.h"
60 
61 #include "libmesh/exodusII_io.h"
62 #include "libmesh/mesh_refinement.h"
63 #include "libmesh/string_to_enum.h"
64 #include "libmesh/checkpoint_io.h"
65 #include "libmesh/mesh_base.h"
66 
67 // System include for dynamic library methods
68 #ifdef LIBMESH_HAVE_DLOPEN
69 #include <dlfcn.h>
70 #include <sys/utsname.h> // utsname
71 #endif
72 
73 // C++ includes
74 #include <numeric> // std::accumulate
75 #include <fstream>
76 #include <sys/types.h>
77 #include <unistd.h>
78 #include <cstdlib> // for system()
79 #include <chrono>
80 #include <thread>
81 
82 #define QUOTE(macro) stringifyName(macro)
83 
84 void
86 {
87  params.addCommandLineParam<std::string>(
88  "app_to_run",
89  "--app <AppName>",
90  "Specify the application that should be used to run the input file. This must match an "
91  "application name registered to the application factory. Note that this option is "
92  "case-sensitive.");
93 }
94 
97 {
99 
100  // Parameters that main also expects that we won't use (-i)
102 
103  params.addCommandLineParam<bool>(
104  "display_version", "-v --version", false, "Print application version");
105 
106  params.addCommandLineParam<std::string>(
107  "mesh_only",
108  "--mesh-only [mesh_file_name]",
109  "Setup and Output the input mesh only (Default: \"<input_file_name>_in.e\")");
110 
111  params.addCommandLineParam<bool>("show_input",
112  "--show-input",
113  false,
114  "Shows the parsed input file before running the simulation.");
115  params.addCommandLineParam<bool>(
116  "show_outputs", "--show-outputs", false, "Shows the output execution time information.");
117  params.addCommandLineParam<bool>(
118  "show_controls", "--show-controls", false, "Shows the Control logic available and executed.");
119 
120  params.addCommandLineParam<bool>(
121  "no_color", "--no-color", false, "Disable coloring of all Console outputs.");
122  params.addCommandLineParam<std::string>("color",
123  "--color [auto,on,off]",
124  "default-on",
125  "Whether to use color in console output (default 'on').");
126 
127  params.addCommandLineParam<bool>("help", "-h --help", false, "Displays CLI usage statement.");
128  params.addCommandLineParam<bool>(
129  "minimal",
130  "--minimal",
131  false,
132  "Ignore input file and build a minimal application with Transient executioner.");
133 
134  params.addCommandLineParam<bool>(
135  "language_server",
136  "--language-server",
137  "Starts a process to communicate with development tools using the language server protocol");
138 
139  params.addCommandLineParam<std::string>(
140  "definition", "--definition", "Shows a SON style input definition dump for input validation");
141  params.addCommandLineParam<std::string>(
142  "dump", "--dump [search_string]", "Shows a dump of available input file syntax.");
143  params.addCommandLineParam<bool>(
144  "registry", "--registry", "Lists all known objects and actions.");
145  params.addCommandLineParam<bool>(
146  "registry_hit", "--registry-hit", "Lists all known objects and actions in hit format.");
147  params.addCommandLineParam<bool>(
148  "use_executor", "--executor", false, "Use the new Executor system instead of Executioners");
149 
150  params.addCommandLineParam<bool>(
151  "apptype", "--type", false, "Return the name of the application object.");
152  params.addCommandLineParam<std::string>(
153  "yaml", "--yaml", "Dumps input file syntax in YAML format.");
154  params.addCommandLineParam<std::string>(
155  "json", "--json", "Dumps input file syntax in JSON format.");
156  params.addCommandLineParam<bool>(
157  "syntax", "--syntax", false, "Dumps the associated Action syntax paths ONLY");
158  params.addCommandLineParam<bool>(
159  "show_docs", "--docs", false, "print url/path to the documentation website");
160  params.addCommandLineParam<bool>("check_input",
161  "--check-input",
162  false,
163  "Check the input file (i.e. requires -i <filename>) and quit.");
164  params.addCommandLineParam<std::string>(
165  "show_inputs",
166  "--show-copyable-inputs",
167  "Shows the directories able to be installed (copied) into a user-writable location");
168 
169  params.addCommandLineParam<std::string>("copy_inputs",
170  "--copy-inputs <dir>",
171  "Copies installed inputs (e.g. tests, examples, etc.) to "
172  "an directory named <appname>_<dir>.");
173  params.addCommandLineParam<std::string>("run",
174  "--run",
175  "Runs the inputs in the current directory copied to a "
176  "user-writable location by \"--copy-inputs\"");
177 
178  params.addCommandLineParam<bool>(
179  "list_constructed_objects",
180  "--list-constructed-objects",
181  false,
182  "List all moose object type names constructed by the master app factory.");
183 
184  params.addCommandLineParam<unsigned int>(
185  "n_threads", "--n-threads=<n>", 1, "Runs the specified number of threads per process");
186 
187  params.addCommandLineParam<bool>("allow_unused",
188  "-w --allow-unused",
189  false,
190  "Warn about unused input file options instead of erroring.");
191  params.addCommandLineParam<bool>("error_unused",
192  "-e --error-unused",
193  false,
194  "Error when encountering unused input file options");
195  params.addCommandLineParam<bool>(
196  "error_override",
197  "-o --error-override",
198  false,
199  "Error when encountering overridden or parameters supplied multiple times");
200  params.addCommandLineParam<bool>(
201  "error_deprecated", "--error-deprecated", false, "Turn deprecated code messages into Errors");
202 
203  params.addCommandLineParam<bool>(
204  "distributed_mesh",
205  "--distributed-mesh",
206  false,
207  "The libMesh Mesh underlying MooseMesh should always be a DistributedMesh");
208 
209  params.addCommandLineParam<std::string>(
210  "split_mesh",
211  "--split-mesh [splits]",
212  "comma-separated list of numbers of chunks to split the mesh into");
213 
214  params.addCommandLineParam<std::string>("split_file",
215  "--split-file [filename]",
216  "",
217  "optional name of split mesh file(s) to write/read");
218 
219  params.addCommandLineParam<bool>(
220  "use_split", "--use-split", false, "use split distributed mesh files");
221 
222  params.addCommandLineParam<unsigned int>(
223  "refinements",
224  "-r <n>",
225  0,
226  "Specify additional initial uniform mesh refinements for grid convergence studies");
227 
228  params.addCommandLineParam<std::string>("recover",
229  "--recover [file_base]",
230  "Continue the calculation. If file_base is omitted then "
231  "the most recent recovery file will be utilized");
232 
233  params.addCommandLineParam<bool>("test_checkpoint_half_transient",
234  "--test-checkpoint-half-transient",
235  false,
236  "When true the simulation will only run half of "
237  "its specified transient (ie half the "
238  "timesteps) with checkpoints enabled. "
239  "This is useful for testing recovery and restart "
240  "and should only be used in the test harness.");
241 
242  params.addCommandLineParam<Real>("output_wall_time_interval",
243  "--output-wall-time-interval [interval]",
244  "The target wall time interval (in seconds) at "
245  "which to write to output. "
246  "USE FOR TEST SUITE PROBLEMS ONLY, FOR ALL OTHER USES "
247  "SEE THE wall_time_interval IN DERIVED Output OBJECTS.");
248 
249  // No default on these two options, they must not both be valid
250  params.addCommandLineParam<bool>(
251  "trap_fpe",
252  "--trap-fpe",
253  "Enable Floating Point Exception handling in critical sections of "
254  "code. This is enabled automatically in DEBUG mode");
255  params.addCommandLineParam<bool>("no_trap_fpe",
256  "--no-trap-fpe",
257  "Disable Floating Point Exception handling in critical "
258  "sections of code when using DEBUG mode.");
259 
260  params.addCommandLineParam<bool>("error", "--error", false, "Turn all warnings into errors");
261 
262  params.addCommandLineParam<bool>(
263  "timing",
264  "-t --timing",
265  false,
266  "Enable all performance logging for timing purposes. This will disable all "
267  "screen output of performance logs for all Console objects.");
268  params.addCommandLineParam<bool>("no_timing",
269  "--no-timing",
270  false,
271  "Disabled performance logging. Overrides -t or --timing "
272  "if passed in conjunction with this flag");
273 
274  params.addCommandLineParam<bool>(
275  "allow_test_objects", "--allow-test-objects", false, "Register test objects and syntax.");
276 
277  // Options ignored by MOOSE but picked up by libMesh, these are here so that they are displayed in
278  // the application help
279  params.addCommandLineParam<bool>(
280  "keep_cout",
281  "--keep-cout",
282  false,
283  "Keep standard output from all processors when running in parallel");
284  params.addCommandLineParam<bool>(
285  "redirect_stdout",
286  "--redirect-stdout",
287  false,
288  "Keep standard output from all processors when running in parallel");
289 
290  params.addCommandLineParam<std::string>(
291  "timpi_sync",
292  "--timpi-sync <sync type>",
293  "nbx",
294  "Changes the sync type used in spare parallel communitations within the TIMPI library "
295  "(advanced option).");
296 
297  // Options for debugging
298  params.addCommandLineParam<std::string>("start_in_debugger",
299  "--start-in-debugger <debugger>",
300  "Start the application and attach a debugger. This will "
301  "launch xterm windows using the command you specify for "
302  "'debugger'");
303 
304  params.addCommandLineParam<unsigned int>("stop_for_debugger",
305  "--stop-for-debugger [seconds]",
306  30,
307  "Pauses the application during startup for the "
308  "specified time to allow for connection of debuggers.");
309 
310  params.addCommandLineParam<bool>("perf_graph_live_all",
311  "--perf-graph-live-all",
312  false,
313  "Forces printing of ALL progress messages.");
314 
315  params.addCommandLineParam<bool>("disable_perf_graph_live",
316  "--disable-perf-graph-live",
317  false,
318  "Disables PerfGraph Live Printing.");
319 
320  params.addParam<bool>(
321  "automatic_automatic_scaling", false, "Whether to turn on automatic scaling by default.");
322 
323 #ifdef HAVE_GPERFTOOLS
324  params.addCommandLineParam<std::string>(
325  "gperf_profiler_on",
326  "--gperf-profiler-on [ranks]",
327  "To generate profiling report only on comma-separated list of MPI ranks.");
328 #endif
329 
330  params.addPrivateParam<std::string>("_app_name"); // the name passed to AppFactory::create
331  params.addPrivateParam<std::string>("_type");
332  params.addPrivateParam<int>("_argc");
333  params.addPrivateParam<char **>("_argv");
334  params.addPrivateParam<std::shared_ptr<CommandLine>>("_command_line");
335  params.addPrivateParam<std::shared_ptr<Parallel::Communicator>>("_comm");
336  params.addPrivateParam<unsigned int>("_multiapp_level");
337  params.addPrivateParam<unsigned int>("_multiapp_number");
338  params.addPrivateParam<const MooseMesh *>("_master_mesh");
339  params.addPrivateParam<const MooseMesh *>("_master_displaced_mesh");
340  params.addPrivateParam<std::unique_ptr<Backup> *>("_initial_backup", nullptr);
341  params.addPrivateParam<std::shared_ptr<Parser>>("_parser");
342 
343  params.addParam<bool>(
344  "use_legacy_material_output",
345  true,
346  "Set false to allow material properties to be output on INITIAL, not just TIMESTEP_END.");
347 
348  params.addParam<bool>(
350  false,
351  "Set true to enable data-driven mesh generation, which is an experimental feature");
352 
353  MooseApp::addAppParam(params);
354 
355  return params;
356 }
357 
359  : ConsoleStreamInterface(*this),
360  PerfGraphInterface(*this, "MooseApp"),
361  ParallelObject(*parameters.get<std::shared_ptr<Parallel::Communicator>>(
362  "_comm")), // Can't call getParam() before pars is set
363  MooseBase(parameters.get<std::string>("_type"),
364  parameters.get<std::string>("_app_name"),
365  *this,
366  _pars),
367  _pars(parameters),
368  _comm(getParam<std::shared_ptr<Parallel::Communicator>>("_comm")),
369  _file_base_set_by_user(false),
370  _output_position_set(false),
371  _start_time_set(false),
372  _start_time(0.0),
373  _global_time_offset(0.0),
374  _input_parameter_warehouse(std::make_unique<InputParameterWarehouse>()),
375  _action_factory(*this),
376  _action_warehouse(*this, _syntax, _action_factory),
377  _output_warehouse(*this),
378  _parser(parameters.get<std::shared_ptr<Parser>>("_parser")),
379  _builder(*this, _action_warehouse, _parser),
380  _restartable_data(libMesh::n_threads()),
381  _perf_graph(createRecoverablePerfGraph()),
382  _solution_invalidity(createRecoverableSolutionInvalidity()),
383  _rank_map(*_comm, _perf_graph),
384  _use_executor(parameters.get<bool>("use_executor")),
385  _null_executor(NULL),
386  _use_nonlinear(true),
387  _use_eigen_value(false),
388  _enable_unused_check(ERROR_UNUSED),
389  _factory(*this),
390  _error_overridden(false),
391  _ready_to_exit(false),
392  _initial_from_file(false),
393  _distributed_mesh_on_command_line(false),
394  _recover(false),
395  _restart(false),
396  _split_mesh(false),
397  _use_split(parameters.get<bool>("use_split")),
398 #ifdef DEBUG
399  _trap_fpe(true),
400 #else
401  _trap_fpe(false),
402 #endif
403  _test_checkpoint_half_transient(false),
404  _check_input(getParam<bool>("check_input")),
405  _multiapp_level(
406  isParamValid("_multiapp_level") ? parameters.get<unsigned int>("_multiapp_level") : 0),
407  _multiapp_number(
408  isParamValid("_multiapp_number") ? parameters.get<unsigned int>("_multiapp_number") : 0),
409  _master_mesh(isParamValid("_master_mesh") ? parameters.get<const MooseMesh *>("_master_mesh")
410  : nullptr),
411  _master_displaced_mesh(isParamValid("_master_displaced_mesh")
412  ? parameters.get<const MooseMesh *>("_master_displaced_mesh")
413  : nullptr),
414  _mesh_generator_system(*this),
415  _rd_reader(*this, _restartable_data),
416  _execute_flags(moose::internal::ExecFlagRegistry::getExecFlagRegistry().getFlags()),
417  _output_buffer_cache(nullptr),
418  _automatic_automatic_scaling(getParam<bool>("automatic_automatic_scaling")),
419  _initial_backup(getParam<std::unique_ptr<Backup> *>("_initial_backup"))
420 {
421  // Set the TIMPI sync type via --timpi-sync
422  const auto & timpi_sync = parameters.get<std::string>("timpi_sync");
423  const_cast<Parallel::Communicator &>(comm()).sync_type(timpi_sync);
424 
425 #ifdef HAVE_GPERFTOOLS
426  if (isUltimateMaster())
427  {
428  bool has_cpu_profiling = false;
429  bool has_heap_profiling = false;
430  static std::string cpu_profile_file;
431  static std::string heap_profile_file;
432 
433  // For CPU profiling, users need to have environment 'MOOSE_PROFILE_BASE'
434  if (std::getenv("MOOSE_PROFILE_BASE"))
435  {
436  has_cpu_profiling = true;
437  cpu_profile_file =
438  std::getenv("MOOSE_PROFILE_BASE") + std::to_string(_comm->rank()) + ".prof";
439  // create directory if needed
440  auto name = MooseUtils::splitFileName(cpu_profile_file);
441  if (!name.first.empty())
442  {
443  if (processor_id() == 0)
444  MooseUtils::makedirs(name.first.c_str());
445  _comm->barrier();
446  }
447  }
448 
449  // For Heap profiling, users need to have 'MOOSE_HEAP_BASE'
450  if (std::getenv("MOOSE_HEAP_BASE"))
451  {
452  has_heap_profiling = true;
453  heap_profile_file = std::getenv("MOOSE_HEAP_BASE") + std::to_string(_comm->rank());
454  // create directory if needed
455  auto name = MooseUtils::splitFileName(heap_profile_file);
456  if (!name.first.empty())
457  {
458  if (processor_id() == 0)
459  MooseUtils::makedirs(name.first.c_str());
460  _comm->barrier();
461  }
462  }
463 
464  // turn on profiling only on selected ranks
465  if (isParamValid("gperf_profiler_on"))
466  {
467  auto rankstr = getParam<std::string>("gperf_profiler_on");
468  std::vector<processor_id_type> ranks;
469  bool success = MooseUtils::tokenizeAndConvert(rankstr, ranks, ", ");
470  if (!success)
471  mooseError("Invalid argument for --gperf-profiler-on: '", rankstr, "'");
472  for (auto & rank : ranks)
473  {
474  if (rank >= _comm->size())
475  mooseError("Invalid argument for --gperf-profiler-on: ",
476  rank,
477  " is greater than or equal to ",
478  _comm->size());
479  if (rank == _comm->rank())
480  {
481  _cpu_profiling = has_cpu_profiling;
482  _heap_profiling = has_heap_profiling;
483  }
484  }
485  }
486  else
487  {
488  _cpu_profiling = has_cpu_profiling;
489  _heap_profiling = has_heap_profiling;
490  }
491 
492  if (_cpu_profiling)
493  if (!ProfilerStart(cpu_profile_file.c_str()))
494  mooseError("CPU profiler is not started properly");
495 
496  if (_heap_profiling)
497  {
498  HeapProfilerStart(heap_profile_file.c_str());
499  if (!IsHeapProfilerRunning())
500  mooseError("Heap profiler is not started properly");
501  }
502  }
503 #else
504  if (std::getenv("MOOSE_PROFILE_BASE") || std::getenv("MOOSE_HEAP_BASE"))
505  mooseError("gperftool is not available for CPU or heap profiling");
506 #endif
507 
508  // If this will be a language server then turn off output until that starts
509  if (isParamValid("language_server"))
510  _output_buffer_cache = Moose::out.rdbuf(nullptr);
511 
514 
515  _the_warehouse = std::make_unique<TheWarehouse>();
516  _the_warehouse->registerAttribute<AttribMatrixTags>("matrix_tags", 0);
517  _the_warehouse->registerAttribute<AttribVectorTags>("vector_tags", 0);
518  _the_warehouse->registerAttribute<AttribExecOns>("exec_ons", 0);
519  _the_warehouse->registerAttribute<AttribSubdomains>("subdomains", 0);
520  _the_warehouse->registerAttribute<AttribBoundaries>("boundaries", 0);
521  _the_warehouse->registerAttribute<AttribThread>("thread", 0);
522  _the_warehouse->registerAttribute<AttribExecutionOrderGroup>("execution_order_group", 0);
523  _the_warehouse->registerAttribute<AttribPreIC>("pre_ic", 0);
524  _the_warehouse->registerAttribute<AttribPreAux>("pre_aux");
525  _the_warehouse->registerAttribute<AttribPostAux>("post_aux");
526  _the_warehouse->registerAttribute<AttribName>("name", "dummy");
527  _the_warehouse->registerAttribute<AttribSystem>("system", "dummy");
528  _the_warehouse->registerAttribute<AttribVar>("variable", -1);
529  _the_warehouse->registerAttribute<AttribInterfaces>("interfaces", 0);
530  _the_warehouse->registerAttribute<AttribSysNum>("sys_num", libMesh::invalid_uint);
531  _the_warehouse->registerAttribute<AttribResidualObject>("residual_object");
532  _the_warehouse->registerAttribute<AttribSorted>("sorted");
533  _the_warehouse->registerAttribute<AttribDisplaced>("displaced", -1);
534 
535  if (isParamValid("_argc") && isParamValid("_argv"))
536  {
537  int argc = getParam<int>("_argc");
538  char ** argv = getParam<char **>("_argv");
539 
540  _sys_info = std::make_unique<SystemInfo>(argc, argv);
541  }
542  if (isParamValid("_command_line"))
543  _command_line = getParam<std::shared_ptr<CommandLine>>("_command_line");
544  else
545  mooseError("Valid CommandLine object required");
546 
547  if (_check_input && isParamValid("recover"))
548  mooseError("Cannot run --check-input with --recover. Recover files might not exist");
549 
550  if (isParamValid("start_in_debugger") && _multiapp_level == 0)
551  {
552  auto command = getParam<std::string>("start_in_debugger");
553 
554  Moose::out << "Starting in debugger using: " << command << std::endl;
555 
557 
558  std::stringstream command_stream;
559 
560  // This will start XTerm and print out some info first... then run the debugger
561  command_stream << "xterm -e \"echo 'Rank: " << processor_id() << " Hostname: " << hostname
562  << " PID: " << getpid() << "'; echo ''; ";
563 
564  // Figure out how to run the debugger
565  if (command.find("lldb") != std::string::npos || command.find("gdb") != std::string::npos)
566  command_stream << command << " -p " << getpid();
567  else
568  mooseError("Unknown debugger: ",
569  command,
570  "\nIf this is truly what you meant then contact moose-users to have a discussion "
571  "about adding your debugger.");
572 
573  // Finish up the command
574  command_stream << "\""
575  << " & ";
576 
577  std::string command_string = command_stream.str();
578  Moose::out << "Running: " << command_string << std::endl;
579 
580  int ret = std::system(command_string.c_str());
581  libmesh_ignore(ret);
582 
583  // Sleep to allow time for the debugger to attach
584  std::this_thread::sleep_for(std::chrono::seconds(10));
585  }
586 
587  if (!parameters.isParamSetByAddParam("stop_for_debugger"))
588  {
589  Moose::out << "\nStopping for " << getParam<unsigned int>("stop_for_debugger")
590  << " seconds to allow attachment from a debugger.\n";
591 
592  Moose::out << "\nAll of the processes you can connect to:\n";
593  Moose::out << "rank - hostname - pid\n";
594 
596 
597  {
598  // The 'false' turns off the serialization warning
599  SerializerGuard sg(_communicator, false); // Guarantees that the processors print in order
600  Moose::err << processor_id() << " - " << hostname << " - " << getpid() << "\n";
601  }
602 
603  Moose::out << "\nWaiting...\n" << std::endl;
604 
605  // Sleep to allow time for the debugger to attach
606  std::this_thread::sleep_for(std::chrono::seconds(getParam<unsigned int>("stop_for_debugger")));
607  }
608 
609  if (_master_mesh && _multiapp_level == 0)
610  mooseError("Mesh can be passed in only for sub-apps");
611 
613  mooseError("_master_mesh should have been set when _master_displaced_mesh is set");
614 
615  // Data specifically associated with the mesh (meta-data) that will read from the restart
616  // file early during the simulation setup so that they are available to Actions and other objects
617  // that need them during the setup process. Most of the restartable data isn't made available
618  // until all objects have been created and all Actions have been executed (i.e. initialSetup).
620 
621  if (parameters.have_parameter<bool>("use_legacy_dirichlet_bc"))
622  mooseDeprecated("The parameter 'use_legacy_dirichlet_bc' is no longer valid.\n\n",
623  "All Dirichlet boundary conditions are preset by default.\n\n",
624  "Remove said parameter in ",
625  name(),
626  " to remove this deprecation warning.");
627 
628  Moose::out << std::flush;
629 }
630 
632 {
633 #ifdef HAVE_GPERFTOOLS
634  // CPU profiling stop
635  if (_cpu_profiling)
636  ProfilerStop();
637  // Heap profiling stop
638  if (_heap_profiling)
639  HeapProfilerStop();
640 #endif
642  _executioner.reset();
643  _the_warehouse.reset();
644 
645  // Don't wait for implicit destruction of input parameter storage
647 
648  // This is dirty, but I don't know what else to do. Obviously, others
649  // have had similar problems if you look above. In specific, the
650  // dlclose below on macs is destructing some data that does not
651  // belong to it in garbage collection. So... don't even give
652  // dlclose an option
653  _restartable_data.clear();
654 
655 #ifdef LIBMESH_HAVE_DLOPEN
656  // Close any open dynamic libraries
657  for (const auto & lib_pair : _lib_handles)
658  dlclose(lib_pair.second.library_handle);
659 #endif
660 }
661 
662 std::string
664 {
665  return MOOSE_VERSION;
666 }
667 
668 std::string
670 {
671  return MOOSE_VERSION;
672 }
673 
674 std::string
676 {
677  return getPrintableName() + " Version: " + getVersion();
678 }
679 
680 void
682 {
683  TIME_SECTION("setupOptions", 5, "Setting Up Options");
684 
685  // Print the header, this is as early as possible
686  auto hdr = header();
687  if (hdr.length() != 0)
688  {
689  if (multiAppLevel() > 0)
691  Moose::out << hdr << std::endl;
692  }
693 
694  if (getParam<bool>("error_unused"))
695  setCheckUnusedFlag(true);
696  else if (getParam<bool>("allow_unused"))
697  setCheckUnusedFlag(false);
698 
699  if (getParam<bool>("error_override"))
701 
702  _distributed_mesh_on_command_line = getParam<bool>("distributed_mesh");
703 
704  _test_checkpoint_half_transient = getParam<bool>("test_checkpoint_half_transient");
705 
706  if (isParamValid("output_wall_time_interval"))
707  {
708  const auto output_wall_time_interval = getParam<Real>("output_wall_time_interval");
709  if (output_wall_time_interval <= 0)
710  mooseError("--output-wall-time-interval must be greater than zero.");
711  }
712 
713  // The no_timing flag takes precedence over the timing flag.
714  if (getParam<bool>("no_timing"))
715  {
716  _pars.set<bool>("timing") = false;
717 
718  _perf_graph.setActive(false);
719  }
720 
721  if (isParamValid("trap_fpe") && isParamValid("no_trap_fpe"))
722  mooseError("Cannot use both \"--trap-fpe\" and \"--no-trap-fpe\" flags.");
723  if (isParamValid("trap_fpe"))
724  _trap_fpe = true;
725  else if (isParamValid("no_trap_fpe"))
726  _trap_fpe = false;
727 
728  // Turn all warnings in MOOSE to errors (almost see next logic block)
729  Moose::_warnings_are_errors = getParam<bool>("error");
730 
731  // Deprecated messages can be toggled to errors independently from everything else.
732  Moose::_deprecated_is_error = getParam<bool>("error_deprecated");
733 
734  if (isUltimateMaster()) // makes sure coloring isn't reset incorrectly in multi-app settings
735  {
736  // Toggle the color console off
737  Moose::setColorConsole(true, true); // set default color condition
738  if (getParam<bool>("no_color"))
739  Moose::setColorConsole(false);
740 
741  char * c_color = std::getenv("MOOSE_COLOR");
742  std::string color = "on";
743  if (c_color)
744  color = c_color;
745  if (getParam<std::string>("color") != "default-on")
746  color = getParam<std::string>("color");
747 
748  if (color == "auto")
750  else if (color == "on")
751  Moose::setColorConsole(true, true);
752  else if (color == "off")
753  Moose::setColorConsole(false);
754  else
755  mooseWarning("ignoring invalid --color arg (want 'auto', 'on', or 'off')");
756  }
757 
758  // this warning goes below --color processing to honor that setting for
759  // the warning. And below settings for warnings/error setup.
760  if (getParam<bool>("no_color"))
761  mooseDeprecated("The --no-color flag is deprecated. Use '--color off' instead.");
762 
763 // If there's no threading model active, but the user asked for
764 // --n-threads > 1 on the command line, throw a mooseError. This is
765 // intended to prevent situations where the user has potentially
766 // built MOOSE incorrectly (neither TBB nor pthreads found) and is
767 // asking for multiple threads, not knowing that there will never be
768 // any threads launched.
769 #if !LIBMESH_USING_THREADS
770  if (libMesh::command_line_value("--n-threads", 1) > 1)
771  mooseError("You specified --n-threads > 1, but there is no threading model active!");
772 #endif
773 
774  // Build a minimal running application, ignoring the input file.
775  if (getParam<bool>("minimal"))
777 
778  else if (getParam<bool>("display_version"))
779  {
780  Moose::out << getPrintableVersion() << std::endl;
781  _ready_to_exit = true;
782  return;
783  }
784  else if (getParam<bool>("help"))
785  {
786  _command_line->printUsage();
787  _ready_to_exit = true;
788  }
789  else if (isParamValid("dump"))
790  {
791  // Get command line argument following --dump on command line
792  std::string following_arg = getParam<std::string>("dump");
793 
794  // The argument following --dump is a parameter search string,
795  // which can be empty.
796  std::string param_search;
797  if (!following_arg.empty() && (following_arg.find('-') != 0))
798  param_search = following_arg;
799 
800  JsonSyntaxTree tree(param_search);
801 
802  {
803  TIME_SECTION("dump", 1, "Building Syntax Tree");
805  }
806 
807  // Turn off live printing so that it doesn't mess with the dump
809 
810  JsonInputFileFormatter formatter;
811  Moose::out << "\n### START DUMP DATA ###\n"
812  << formatter.toString(tree.getRoot()) << "\n### END DUMP DATA ###" << std::endl;
813  _ready_to_exit = true;
814  }
815  else if (isParamValid("registry"))
816  {
818 
819  Moose::out << "Label\tType\tName\tClass\tFile\n";
820 
821  auto & objmap = Registry::allObjects();
822  for (auto & entry : objmap)
823  for (auto & obj : entry.second)
824  Moose::out << entry.first << "\tobject\t" << obj->name() << "\t" << obj->_classname << "\t"
825  << obj->_file << "\n";
826 
827  auto & actmap = Registry::allActions();
828  for (auto & entry : actmap)
829  {
830  for (auto & act : entry.second)
831  Moose::out << entry.first << "\taction\t" << act->_name << "\t" << act->_classname << "\t"
832  << act->_file << "\n";
833  }
834 
835  _ready_to_exit = true;
836  }
837  else if (isParamValid("registry_hit"))
838  {
840 
841  Moose::out << "### START REGISTRY DATA ###\n";
842 
843  hit::Section root("");
844  auto sec = new hit::Section("registry");
845  root.addChild(sec);
846  auto objsec = new hit::Section("objects");
847  sec->addChild(objsec);
848 
849  auto & objmap = Registry::allObjects();
850  for (auto & entry : objmap)
851  for (auto & obj : entry.second)
852  {
853  auto ent = new hit::Section("entry");
854  objsec->addChild(ent);
855  ent->addChild(new hit::Field("label", hit::Field::Kind::String, entry.first));
856  ent->addChild(new hit::Field("type", hit::Field::Kind::String, "object"));
857  ent->addChild(new hit::Field("name", hit::Field::Kind::String, obj->name()));
858  ent->addChild(new hit::Field("class", hit::Field::Kind::String, obj->_classname));
859  ent->addChild(new hit::Field("file", hit::Field::Kind::String, obj->_file));
860  }
861 
862  auto actsec = new hit::Section("actions");
863  sec->addChild(actsec);
864  auto & actmap = Registry::allActions();
865  for (auto & entry : actmap)
866  for (auto & act : entry.second)
867  {
868  auto ent = new hit::Section("entry");
869  actsec->addChild(ent);
870  ent->addChild(new hit::Field("label", hit::Field::Kind::String, entry.first));
871  ent->addChild(new hit::Field("type", hit::Field::Kind::String, "action"));
872  ent->addChild(new hit::Field("task", hit::Field::Kind::String, act->_name));
873  ent->addChild(new hit::Field("class", hit::Field::Kind::String, act->_classname));
874  ent->addChild(new hit::Field("file", hit::Field::Kind::String, act->_file));
875  }
876 
877  Moose::out << root.render();
878 
879  Moose::out << "\n### END REGISTRY DATA ###\n";
880  _ready_to_exit = true;
881  }
882  else if (isParamValid("definition"))
883  {
885 
886  JsonSyntaxTree tree("");
888  SONDefinitionFormatter formatter;
889  Moose::out << "%-START-SON-DEFINITION-%\n"
890  << formatter.toString(tree.getRoot()) << "\n%-END-SON-DEFINITION-%\n";
891  _ready_to_exit = true;
892  }
893  else if (isParamValid("yaml"))
894  {
896 
898 
899  // Get command line argument following --yaml on command line
900  std::string yaml_following_arg = getParam<std::string>("yaml");
901 
902  // If the argument following --yaml is non-existent or begins with
903  // a dash, call buildFullTree() with an empty string, otherwise
904  // pass the argument following --yaml.
905  if (yaml_following_arg.empty() || (yaml_following_arg.find('-') == 0))
907  else
908  _builder.buildFullTree(yaml_following_arg);
909 
910  _ready_to_exit = true;
911  }
912  else if (isParamValid("json"))
913  {
915 
916  // Get command line argument following --json on command line
917  std::string json_following_arg = getParam<std::string>("json");
918 
919  // The argument following --json is a parameter search string,
920  // which can be empty.
921  std::string search;
922  if (!json_following_arg.empty() && (json_following_arg.find('-') != 0))
923  search = json_following_arg;
924 
925  JsonSyntaxTree tree(search);
927 
928  Moose::out << "**START JSON DATA**\n" << tree.getRoot().dump(2) << "\n**END JSON DATA**\n";
929  _ready_to_exit = true;
930  }
931  else if (getParam<bool>("syntax"))
932  {
934 
935  std::multimap<std::string, Syntax::ActionInfo> syntax = _syntax.getAssociatedActions();
936  Moose::out << "**START SYNTAX DATA**\n";
937  for (const auto & it : syntax)
938  Moose::out << it.first << "\n";
939  Moose::out << "**END SYNTAX DATA**\n" << std::endl;
940  _ready_to_exit = true;
941  }
942  else if (getParam<bool>("apptype"))
943  {
945 
946  Moose::out << "MooseApp Type: " << type() << std::endl;
947  _ready_to_exit = true;
948  }
949  else if (getInputFileNames().size())
950  {
951  if (isParamValid("recover"))
952  {
953  // We need to set the flag manually here since the recover parameter is a string type (takes
954  // an optional filename)
955  _recover = true;
956 
957  // Get command line argument following --recover on command line
958  std::string recover_following_arg = getParam<std::string>("recover");
959 
960  // If the argument following --recover is non-existent or begins with
961  // a dash then we are going to eventually find the newest recovery file to use
962  if (!(recover_following_arg.empty() || (recover_following_arg.find('-') == 0)))
963  _restart_recover_base = recover_following_arg;
964  }
965 
966  // In the event that we've parsed once before already in MooseMain, we
967  // won't need to parse again
968  if (!_parser->root())
969  _parser->parse();
970 
971  _builder.build();
972 
973  if (isParamValid("mesh_only"))
974  {
975  _syntax.registerTaskName("mesh_only", true);
976  _syntax.addDependency("mesh_only", "setup_mesh_complete");
977  _syntax.addDependency("determine_system_type", "mesh_only");
978  _action_warehouse.setFinalTask("mesh_only");
979  }
980  else if (isParamValid("split_mesh"))
981  {
982  _split_mesh = true;
983  _syntax.registerTaskName("split_mesh", true);
984  _syntax.addDependency("split_mesh", "setup_mesh_complete");
985  _syntax.addDependency("determine_system_type", "split_mesh");
986  _action_warehouse.setFinalTask("split_mesh");
987  }
989 
990  // Setup the AppFileBase for use by the Outputs or other systems that need output file info
991  {
992  // Extract the CommonOutputAction
993  const auto common_actions = _action_warehouse.getActions<CommonOutputAction>();
994  mooseAssert(common_actions.size() <= 1, "Should not be more than one CommonOutputAction");
995  const Action * common = common_actions.empty() ? nullptr : *common_actions.begin();
996 
997  // If file_base is set in CommonOutputAction through parsing input, obtain the file_base
998  if (common && common->isParamValid("file_base"))
999  {
1000  _output_file_base = common->getParam<std::string>("file_base");
1001  _file_base_set_by_user = true;
1002  }
1003  else if (isUltimateMaster())
1004  {
1005  // if this app is a master, we use the first input file name as the default file base
1006  std::string base = getLastInputFileName();
1007  size_t pos = base.find_last_of('.');
1008  _output_file_base = base.substr(0, pos);
1009  // Note: we did not append "_out" in the file base here because we do not want to
1010  // have it in between the input file name and the object name for Output/*
1011  // syntax.
1012  }
1013  // default file base for multiapps is set by MultiApp
1014  }
1015  }
1016  else if (isParamValid("input_file"))
1017  {
1018  mooseAssert(getInputFileNames().empty(), "Should be empty");
1019  mooseError("No input files specified. Add -i <inputfile> to your command line.");
1020  }
1021  else if (isParamValid("language_server"))
1022  {
1024 
1025  // Reset output to the buffer what was cached before it was turned it off
1026  if (!Moose::out.rdbuf() && _output_buffer_cache)
1027  Moose::out.rdbuf(_output_buffer_cache);
1028 
1029  // Start a language server that communicates using an iostream connection
1030  MooseServer moose_server(*this);
1031 
1032  moose_server.run();
1033 
1034  _ready_to_exit = true;
1035  }
1036 
1037  else /* The catch-all case for bad options or missing options, etc. */
1038  {
1039  if (_check_input)
1040  mooseError("You specified --check-input, but did not provide an input file. Add -i "
1041  "<inputfile> to your command line.");
1042 
1043  _command_line->printUsage();
1044 
1045  _ready_to_exit = true;
1046  }
1047 
1048  Moose::out << std::flush;
1049 }
1050 
1051 const std::vector<std::string> &
1053 {
1054  mooseAssert(_parser, "Parser is not set");
1055  return _parser->getInputFileNames();
1056 }
1057 
1058 const std::string &
1060 {
1061  mooseAssert(_parser, "Parser is not set");
1062  return _parser->getLastInputFileName();
1063 }
1064 
1065 std::string
1066 MooseApp::getOutputFileBase(bool for_non_moose_build_output) const
1067 {
1068  if (_file_base_set_by_user || for_non_moose_build_output || _multiapp_level)
1069  return _output_file_base;
1070  else
1071  return _output_file_base + "_out";
1072 }
1073 
1074 void
1075 MooseApp::setOutputFileBase(const std::string & output_file_base)
1076 {
1077  _output_file_base = output_file_base;
1078 
1079  // Reset the file base in the outputs
1081 
1082  // Reset the file base in multiapps (if they have been constructed yet)
1083  if (getExecutioner())
1084  for (auto & multi_app : feProblem().getMultiAppWarehouse().getObjects())
1085  multi_app->setAppOutputFileBase();
1086 
1087  _file_base_set_by_user = true;
1088 }
1089 
1090 void
1092 {
1093  TIME_SECTION("runInputFile", 3);
1094 
1095  // If ready to exit has been set, then just return
1096  if (_ready_to_exit)
1097  return;
1098 
1100 
1101  if (isParamValid("mesh_only") || isParamValid("split_mesh"))
1102  _ready_to_exit = true;
1103  else if (getParam<bool>("list_constructed_objects"))
1104  {
1105  // TODO: ask multiapps for their constructed objects
1106  _ready_to_exit = true;
1107  std::vector<std::string> obj_list = _factory.getConstructedObjects();
1108  Moose::out << "**START OBJECT DATA**\n";
1109  for (const auto & name : obj_list)
1110  Moose::out << name << "\n";
1111  Moose::out << "**END OBJECT DATA**\n" << std::endl;
1112  }
1113 }
1114 
1115 void
1117 {
1118  bool warn = _enable_unused_check == WARN_UNUSED;
1120 
1121  _builder.errorCheck(*_comm, warn, err);
1122 
1123  auto apps = feProblem().getMultiAppWarehouse().getObjects();
1124  for (auto app : apps)
1125  for (unsigned int i = 0; i < app->numLocalApps(); i++)
1126  app->localApp(i)->errorCheck();
1127 }
1128 
1129 void
1131 {
1132  TIME_SECTION("executeExecutioner", 3);
1133 
1134  // If ready to exit has been set, then just return
1135  if (_ready_to_exit)
1136  return;
1137 
1138  // run the simulation
1139  if (_use_executor && _executor)
1140  {
1142 
1143  _executor->init();
1144  errorCheck();
1145  auto result = _executor->exec();
1146  if (!result.convergedAll())
1147  mooseError(result.str());
1148  }
1149  else if (_executioner)
1150  {
1152  _executioner->init();
1153  errorCheck();
1154  _executioner->execute();
1155  }
1156  else
1157  mooseError("No executioner was specified (go fix your input file)");
1158 }
1159 
1160 bool
1162 {
1163  return _recover;
1164 }
1165 
1166 bool
1168 {
1169  return _restart;
1170 }
1171 
1172 bool
1174 {
1175  return _split_mesh;
1176 }
1177 
1178 bool
1180 {
1181  return !_restart_recover_base.empty();
1182 }
1183 
1184 bool
1186 {
1187  mooseDeprecated("MooseApp::hasRecoverFileBase is deprecated, use "
1188  "MooseApp::hasRestartRecoverFileBase() instead.");
1189  return !_restart_recover_base.empty();
1190 }
1191 
1192 void
1195 {
1197  switch (filter)
1198  {
1199  case RESTARTABLE_FILTER::RECOVERABLE:
1200  _recoverable_data_names.insert(name);
1201  break;
1202  default:
1203  mooseError("Unknown filter");
1204  }
1205 }
1206 
1207 std::vector<std::filesystem::path>
1208 MooseApp::backup(const std::filesystem::path & folder_base)
1209 {
1210  TIME_SECTION("backup", 2, "Backing Up Application to File");
1211 
1212  preBackup();
1213 
1215  return writer.write(folder_base);
1216 }
1217 
1218 std::unique_ptr<Backup>
1220 {
1221  TIME_SECTION("backup", 2, "Backing Up Application");
1222 
1224 
1225  preBackup();
1226 
1227  auto backup = std::make_unique<Backup>();
1228  writer.write(*backup->header, *backup->data);
1229 
1230  return backup;
1231 }
1232 
1233 void
1234 MooseApp::restore(const std::filesystem::path & folder_base, const bool for_restart)
1235 {
1236  TIME_SECTION("restore", 2, "Restoring Application from File");
1237 
1238  const DataNames filter_names = for_restart ? getRecoverableData() : DataNames{};
1239 
1240  _rd_reader.setInput(folder_base);
1241  _rd_reader.restore(filter_names);
1242 
1243  postRestore(for_restart);
1244 }
1245 
1246 void
1247 MooseApp::restore(std::unique_ptr<Backup> backup, const bool for_restart)
1248 {
1249  TIME_SECTION("restore", 2, "Restoring Application");
1250 
1251  const DataNames filter_names = for_restart ? getRecoverableData() : DataNames{};
1252 
1253  if (!backup)
1254  mooseError("MooseApp::resore(): Provided backup is not initialized");
1255 
1256  auto header = std::move(backup->header);
1257  mooseAssert(header, "Header not available");
1258 
1259  auto data = std::move(backup->data);
1260  mooseAssert(data, "Data not available");
1261 
1262  _rd_reader.setInput(std::move(header), std::move(data));
1263  _rd_reader.restore(filter_names);
1264 
1265  postRestore(for_restart);
1266 }
1267 
1268 void
1269 MooseApp::restoreFromInitialBackup(const bool for_restart)
1270 {
1271  mooseAssert(hasInitialBackup(), "Missing initial backup");
1272  restore(std::move(*_initial_backup), for_restart);
1273 }
1274 
1275 std::unique_ptr<Backup>
1277 {
1278  if (!_rd_reader.isRestoring())
1279  mooseError("MooseApp::finalizeRestore(): Not currently restoring");
1280 
1281  // This gives us access to the underlying streams so that we can return it if needed
1282  auto input_streams = _rd_reader.clear();
1283 
1284  std::unique_ptr<Backup> backup;
1285 
1286  // Give them back a backup if this restore started from a Backup, in which case
1287  // the two streams in the Backup are formed into StringInputStreams
1288  if (auto header_string_input = dynamic_cast<StringInputStream *>(input_streams.header.get()))
1289  {
1290  auto data_string_input = dynamic_cast<StringInputStream *>(input_streams.data.get());
1291  mooseAssert(data_string_input, "Should also be a string input");
1292 
1293  auto header_sstream = header_string_input->release();
1294  mooseAssert(header_sstream, "Header not available");
1295 
1296  auto data_sstream = data_string_input->release();
1297  mooseAssert(data_sstream, "Data not available");
1298 
1299  backup = std::make_unique<Backup>();
1300  backup->header = std::move(header_sstream);
1301  backup->data = std::move(data_sstream);
1302  }
1303 
1304  return backup;
1305 }
1306 
1307 void
1308 MooseApp::setCheckUnusedFlag(bool warn_is_error)
1309 {
1310  _enable_unused_check = warn_is_error ? ERROR_UNUSED : WARN_UNUSED;
1311 }
1312 
1313 void
1315 {
1317 }
1318 
1319 FEProblemBase &
1321 {
1322  return _executor.get() ? _executor->feProblem() : _executioner->feProblem();
1323 }
1324 
1325 void
1326 MooseApp::addExecutor(const std::string & type,
1327  const std::string & name,
1328  const InputParameters & params)
1329 {
1330  std::shared_ptr<Executor> executor = _factory.create<Executor>(type, name, params);
1331 
1332  if (_executors.count(executor->name()) > 0)
1333  mooseError("an executor with name '", executor->name(), "' already exists");
1334  _executors[executor->name()] = executor;
1335 }
1336 
1337 void
1338 MooseApp::addExecutorParams(const std::string & type,
1339  const std::string & name,
1340  const InputParameters & params)
1341 {
1342  _executor_params[name] = std::make_pair(type, std::make_unique<InputParameters>(params));
1343 }
1344 
1345 Parser &
1347 {
1348  mooseAssert(_parser, "Not set");
1349  return *_parser;
1350 }
1351 
1352 void
1353 MooseApp::recursivelyCreateExecutors(const std::string & current_executor_name,
1354  std::list<std::string> & possible_roots,
1355  std::list<std::string> & current_branch)
1356 {
1357  // Did we already make this one?
1358  if (_executors.find(current_executor_name) != _executors.end())
1359  return;
1360 
1361  // Is this one already on the current branch (i.e. there is a cycle)
1362  if (std::find(current_branch.begin(), current_branch.end(), current_executor_name) !=
1363  current_branch.end())
1364  {
1365  std::stringstream exec_names_string;
1366 
1367  auto branch_it = current_branch.begin();
1368 
1369  exec_names_string << *branch_it++;
1370 
1371  for (; branch_it != current_branch.end(); ++branch_it)
1372  exec_names_string << ", " << *branch_it;
1373 
1374  exec_names_string << ", " << current_executor_name;
1375 
1376  mooseError("Executor cycle detected: ", exec_names_string.str());
1377  }
1378 
1379  current_branch.push_back(current_executor_name);
1380 
1381  // Build the dependencies first
1382  const auto & params = *_executor_params[current_executor_name].second;
1383 
1384  for (const auto & param : params)
1385  {
1386  if (params.have_parameter<ExecutorName>(param.first))
1387  {
1388  const auto & dependency_name = params.get<ExecutorName>(param.first);
1389 
1390  possible_roots.remove(dependency_name);
1391 
1392  if (!dependency_name.empty())
1393  recursivelyCreateExecutors(dependency_name, possible_roots, current_branch);
1394  }
1395  }
1396 
1397  // Add this Executor
1398  const auto & type = _executor_params[current_executor_name].first;
1399  addExecutor(type, current_executor_name, params);
1400 
1401  current_branch.pop_back();
1402 }
1403 
1404 void
1406 {
1407  // Do we have any?
1408  if (_executor_params.empty())
1409  return;
1410 
1411  // Holds the names of Executors that may be the root executor
1412  std::list<std::string> possibly_root;
1413 
1414  // What is already built
1415  std::map<std::string, bool> already_built;
1416 
1417  // The Executors that are currently candidates for being roots
1418  std::list<std::string> possible_roots;
1419 
1420  // The current line of dependencies - used for finding cycles
1421  std::list<std::string> current_branch;
1422 
1423  // Build the NullExecutor
1424  {
1425  auto params = _factory.getValidParams("NullExecutor");
1426  _null_executor = _factory.create<NullExecutor>("NullExecutor", "_null_executor", params);
1427  }
1428 
1429  for (const auto & params_entry : _executor_params)
1430  {
1431  const auto & name = params_entry.first;
1432 
1433  // Did we already make this one?
1434  if (_executors.find(name) != _executors.end())
1435  continue;
1436 
1437  possible_roots.emplace_back(name);
1438 
1439  recursivelyCreateExecutors(name, possible_roots, current_branch);
1440  }
1441 
1442  // If there is more than one possible root - error
1443  if (possible_roots.size() > 1)
1444  {
1445  auto root_string_it = possible_roots.begin();
1446 
1447  std::stringstream roots_string;
1448 
1449  roots_string << *root_string_it++;
1450 
1451  for (; root_string_it != possible_roots.end(); ++root_string_it)
1452  roots_string << ", " << *root_string_it;
1453 
1454  mooseError("Multiple Executor roots found: ", roots_string.str());
1455  }
1456 
1457  // Set the root executor
1458  _executor = _executors[possible_roots.front()];
1459 }
1460 
1461 Executor &
1462 MooseApp::getExecutor(const std::string & name, bool fail_if_not_found)
1463 {
1464  auto it = _executors.find(name);
1465 
1466  if (it != _executors.end())
1467  return *it->second;
1468 
1469  if (fail_if_not_found)
1470  mooseError("Executor not found: ", name);
1471 
1472  return *_null_executor;
1473 }
1474 
1475 Executioner *
1477 {
1478  return _executioner.get() ? _executioner.get() : _executor.get();
1479 }
1480 
1481 void
1483 {
1484  _error_overridden = true;
1485 }
1486 
1487 void
1489 {
1490  TIME_SECTION("run", 3);
1491  if (isParamValid("show_docs") && getParam<bool>("show_docs"))
1492  {
1493  auto binname = appBinaryName();
1494  if (binname == "")
1495  mooseError("could not locate installed tests to run (unresolved binary/app name)");
1496  auto docspath = MooseUtils::docsDir(binname);
1497  if (docspath == "")
1498  mooseError("no installed documentation found");
1499 
1500  auto docmsgfile = MooseUtils::pathjoin(docspath, "docmsg.txt");
1501  std::string docmsg = "file://" + MooseUtils::realpath(docspath) + "/index.html";
1502  if (MooseUtils::pathExists(docmsgfile) && MooseUtils::checkFileReadable(docmsgfile))
1503  {
1504  std::ifstream ifs(docmsgfile);
1505  std::string content((std::istreambuf_iterator<char>(ifs)),
1506  (std::istreambuf_iterator<char>()));
1507  content.replace(content.find("$LOCAL_SITE_HOME"), content.length(), docmsg);
1508  docmsg = content;
1509  }
1510 
1511  Moose::out << docmsg << "\n";
1512  _ready_to_exit = true;
1513  return;
1514  }
1515 
1516  if (showInputs() || copyInputs() || runInputs())
1517  {
1518  _ready_to_exit = true;
1519  return;
1520  }
1521 
1522  try
1523  {
1524  TIME_SECTION("setup", 2, "Setting Up");
1525  setupOptions();
1526  runInputFile();
1527  }
1528  catch (std::exception & err)
1529  {
1530  mooseError(err.what());
1531  }
1532 
1533  if (!_check_input)
1534  {
1535  TIME_SECTION("execute", 2, "Executing");
1537  }
1538  else
1539  {
1540  errorCheck();
1541  // Output to stderr, so it is easier for peacock to get the result
1542  Moose::err << "Syntax OK" << std::endl;
1543  }
1544 }
1545 
1546 bool
1548 {
1549  if (isParamValid("show_inputs"))
1550  {
1551  auto copy_syntax = _pars.getCommandLineSyntax("copy_inputs");
1552  std::vector<std::string> dirs;
1553  const auto installable_inputs = getInstallableInputs();
1554 
1555  if (installable_inputs == "")
1556  {
1557  Moose::out
1558  << "Show inputs has not been overriden in this application.\nContact the developers of "
1559  "this appication and request that they override \"MooseApp::getInstallableInputs\".\n";
1560  }
1561  else
1562  {
1563  mooseAssert(!copy_syntax.empty(), "copy_inputs sytnax should not be empty");
1564 
1565  MooseUtils::tokenize(installable_inputs, dirs, 1, " ");
1566  Moose::out << "The following directories are installable into a user-writeable directory:\n\n"
1567  << installable_inputs << '\n'
1568  << "\nTo install one or more directories of inputs, execute the binary with the \""
1569  << copy_syntax[0] << "\" flag. e.g.:\n$ " << _command_line->getExecutableName()
1570  << ' ' << copy_syntax[0] << ' ' << dirs[0] << '\n';
1571  }
1572  return true;
1573  }
1574  return false;
1575 }
1576 
1577 std::string
1579 {
1580  return "tests";
1581 }
1582 
1583 bool
1585 {
1586  if (isParamValid("copy_inputs"))
1587  {
1588  // Get command line argument following --copy-inputs on command line
1589  auto dir_to_copy = getParam<std::string>("copy_inputs");
1590 
1591  if (dir_to_copy.empty())
1592  mooseError("Error retrieving directory to copy");
1593  if (dir_to_copy.back() != '/')
1594  dir_to_copy += '/';
1595 
1596  // This binary name is the actual binary. That is, if we called a symlink it'll
1597  // be the name of what the symlink points to
1598  auto binname = appBinaryName();
1599  if (binname == "")
1600  mooseError("could not locate installed tests to run (unresolved binary/app name)");
1601 
1602  auto src_dir = MooseUtils::installedInputsDir(binname,
1603  dir_to_copy,
1604  "Rerun binary with " +
1605  _pars.getCommandLineSyntax("show_inputs")[0] +
1606  " to get a list of installable directories.");
1607 
1608  // Use the command line here because if we have a symlink to another binary,
1609  // we want to dump into a directory that is named after the symlink not the true binary
1610  auto dst_dir = _command_line->getExecutableNameBase() + "/" + dir_to_copy;
1611  auto cmdname = _command_line->getExecutableName();
1612  if (cmdname.find_first_of("/") != std::string::npos)
1613  cmdname = cmdname.substr(cmdname.find_first_of("/") + 1, std::string::npos);
1614 
1615  if (MooseUtils::pathExists(dst_dir))
1616  mooseError(
1617  "The directory \"./",
1618  dst_dir,
1619  "\" already exists.\nTo update/recopy the contents of this directory, rename (\"mv ",
1620  dst_dir,
1621  " new_dir_name\") or remove (\"rm -r ",
1622  dst_dir,
1623  "\") the existing directory.\nThen re-run \"",
1624  cmdname,
1625  " --copy-inputs ",
1626  dir_to_copy,
1627  "\".");
1628 
1629  std::string cmd = "mkdir -p " + dst_dir + "; rsync -av " + src_dir + " " + dst_dir;
1630 
1631  TIME_SECTION("copy_inputs", 2, "Copying Inputs");
1632 
1633  // Only perform the copy on the root processor
1634  int return_value = 0;
1635  if (processor_id() == 0)
1636  return_value = system(cmd.c_str());
1637  _communicator.broadcast(return_value);
1638 
1639  if (WIFEXITED(return_value) && WEXITSTATUS(return_value) != 0)
1640  mooseError("Failed to copy the requested directory.");
1641  Moose::out << "Directory successfully copied into ./" << dst_dir << '\n';
1642  return true;
1643  }
1644  return false;
1645 }
1646 
1647 bool
1649 {
1650  if (isParamValid("run"))
1651  {
1652  // Here we are going to pass everything after --run on the cli to the TestHarness. That means
1653  // cannot validate these CLIs.
1654  auto it = _command_line->find("run");
1655 
1656  std::string test_args;
1657  if (it != _command_line->end())
1658  {
1659  // Preincrement here to skip over --run
1660  while (++it != _command_line->end())
1661  test_args += " " + *it;
1662  }
1663 
1664  auto cmd = MooseUtils::runTestsExecutable() + test_args;
1665  auto working_dir = MooseUtils::getCurrentWorkingDir();
1666 
1667  if (MooseUtils::findTestRoot() == "")
1668  {
1669  auto bin_name = appBinaryName();
1670  if (bin_name == "")
1671  mooseError("Could not locate binary name relative to installed location");
1672 
1673  auto cmd_name = Moose::getExecutableName();
1674  mooseError(
1675  "Could not locate installed tests from the current working directory:",
1676  working_dir,
1677  ".\nMake sure you are executing this command from within a writable installed inputs ",
1678  "directory.\nRun \"",
1679  cmd_name,
1680  " --copy-inputs <dir>\" to copy the contents of <dir> to a \"./",
1681  bin_name,
1682  "_<dir>\" directory.\nChange into that directory and try \"",
1683  cmd_name,
1684  " --run <dir>\" again.");
1685  }
1686 
1687  // Only launch the tests on the root processor
1688  Moose::out << "Working Directory: " << working_dir << "\nRunning Command: " << cmd << std::endl;
1689  int return_value = 0;
1690  if (processor_id() == 0)
1691  return_value = system(cmd.c_str());
1692  _communicator.broadcast(return_value);
1693 
1694  if (WIFEXITED(return_value) && WEXITSTATUS(return_value) != 0)
1695  mooseError("Run failed");
1696  return true;
1697  }
1698 
1699  return false;
1700 }
1701 
1702 void
1704 {
1705  _output_position_set = true;
1706  _output_position = p;
1708 
1709  if (_executioner.get())
1710  _executioner->parentOutputPositionChanged();
1711 }
1712 
1713 std::list<std::string>
1715 {
1716  // Storage for the directory names
1717  std::list<std::string> checkpoint_dirs;
1718 
1719  // Add the directories added with Outputs/checkpoint=true input syntax
1720  checkpoint_dirs.push_back(getOutputFileBase() + "_cp");
1721 
1722  // Add the directories from any existing checkpoint output objects
1723  const auto & actions = _action_warehouse.getActionListByName("add_output");
1724  for (const auto & action : actions)
1725  {
1726  // Get the parameters from the MooseObjectAction
1727  MooseObjectAction * moose_object_action = dynamic_cast<MooseObjectAction *>(action);
1728  if (!moose_object_action)
1729  continue;
1730 
1731  const InputParameters & params = moose_object_action->getObjectParams();
1732  if (moose_object_action->getParam<std::string>("type") == "Checkpoint")
1733  {
1734  // Unless file_base was explicitly set by user, we cannot rely on it, as it will be changed
1735  // later
1736  const std::string cp_dir =
1737  _file_base_set_by_user ? params.get<std::string>("file_base")
1738  : (getOutputFileBase(true) + "_" + moose_object_action->name());
1739  checkpoint_dirs.push_back(cp_dir + "_cp");
1740  }
1741  }
1742  return checkpoint_dirs;
1743 }
1744 
1745 std::list<std::string>
1747 {
1748  auto checkpoint_dirs = getCheckpointDirectories();
1749  return MooseUtils::getFilesInDirs(checkpoint_dirs, false);
1750 }
1751 
1752 void
1754 {
1755  _start_time_set = true;
1756  _start_time = time;
1757 }
1758 
1759 std::string
1760 MooseApp::getFileName(bool stripLeadingPath) const
1761 {
1762  return _builder.getPrimaryFileName(stripLeadingPath);
1763 }
1764 
1767 {
1768  return _output_warehouse;
1769 }
1770 
1771 std::string
1772 MooseApp::appNameToLibName(const std::string & app_name) const
1773 {
1774  std::string library_name(app_name);
1775 
1776  // Strip off the App part (should always be the last 3 letters of the name)
1777  size_t pos = library_name.find("App");
1778  if (pos != library_name.length() - 3)
1779  mooseError("Invalid application name: ", library_name);
1780  library_name.erase(pos);
1781 
1782  // Now get rid of the camel case, prepend lib, and append the method and suffix
1783  return std::string("lib") + MooseUtils::camelCaseToUnderscore(library_name) + '-' +
1784  QUOTE(METHOD) + ".la";
1785 }
1786 
1787 std::string
1788 MooseApp::libNameToAppName(const std::string & library_name) const
1789 {
1790  std::string app_name(library_name);
1791 
1792  // Strip off the leading "lib" and trailing ".la"
1793  if (pcrecpp::RE("lib(.+?)(?:-\\w+)?\\.la").Replace("\\1", &app_name) == 0)
1794  mooseError("Invalid library name: ", app_name);
1795 
1796  return MooseUtils::underscoreToCamelCase(app_name, true);
1797 }
1798 
1800 MooseApp::registerRestartableData(std::unique_ptr<RestartableDataValue> data,
1801  THREAD_ID tid,
1802  bool read_only,
1803  const RestartableDataMapName & metaname)
1804 {
1805  if (!metaname.empty() && tid != 0)
1806  mooseError(
1807  "The meta data storage for '", metaname, "' is not threaded, so the tid must be zero.");
1808 
1809  mooseAssert(metaname.empty() ||
1810  _restartable_meta_data.find(metaname) != _restartable_meta_data.end(),
1811  "The desired meta data name does not exist: " + metaname);
1812 
1813  // Select the data store for saving this piece of restartable data (mesh or everything else)
1814  auto & data_map =
1815  metaname.empty() ? _restartable_data[tid] : _restartable_meta_data[metaname].first;
1816 
1817  RestartableDataValue * stored_data = data_map.findData(data->name());
1818  if (stored_data)
1819  {
1820  if (data->typeId() != stored_data->typeId())
1821  mooseError("Type mismatch found in RestartableData registration of '",
1822  data->name(),
1823  "'\n\n Stored type: ",
1824  stored_data->type(),
1825  "\n New type: ",
1826  data->type());
1827  }
1828  else
1829  stored_data = &data_map.addData(std::move(data));
1830 
1831  if (!read_only)
1832  stored_data->setDeclared({});
1833 
1834  return *stored_data;
1835 }
1836 
1838 MooseApp::registerRestartableData(const std::string & libmesh_dbg_var(name),
1839  std::unique_ptr<RestartableDataValue> data,
1840  THREAD_ID tid,
1841  bool read_only,
1842  const RestartableDataMapName & metaname)
1843 {
1844  mooseDeprecated("The use of MooseApp::registerRestartableData with a data name is "
1845  "deprecated.\n\nUse the call without a name instead.");
1846 
1847  mooseAssert(name == data->name(), "Inconsistent name");
1848  return registerRestartableData(std::move(data), tid, read_only, metaname);
1849 }
1850 
1851 bool
1852 MooseApp::hasRestartableMetaData(const std::string & name,
1853  const RestartableDataMapName & metaname) const
1854 {
1855  auto it = _restartable_meta_data.find(metaname);
1856  if (it == _restartable_meta_data.end())
1857  return false;
1858  return it->second.first.hasData(name);
1859 }
1860 
1862 MooseApp::getRestartableMetaData(const std::string & name,
1863  const RestartableDataMapName & metaname,
1864  THREAD_ID tid)
1865 {
1866  if (tid != 0)
1867  mooseError(
1868  "The meta data storage for '", metaname, "' is not threaded, so the tid must be zero.");
1869 
1870  // Get metadata reference from RestartableDataMap and return a (non-const) reference to its value
1871  auto & restartable_data_map = getRestartableDataMap(metaname);
1872  RestartableDataValue * const data = restartable_data_map.findData(name);
1873  if (!data)
1874  mooseError("Unable to find RestartableDataValue object with name " + name +
1875  " in RestartableDataMap");
1876 
1877  return *data;
1878 }
1879 
1880 void
1882  const std::filesystem::path & folder_base)
1883 {
1884  const auto & map_name = getRestartableDataMapName(name);
1885  const auto meta_data_folder_base = metaDataFolderBase(folder_base, map_name);
1886  if (RestartableDataReader::isAvailable(meta_data_folder_base))
1887  {
1890  reader.setInput(meta_data_folder_base);
1891  reader.restore();
1892  }
1893 }
1894 
1895 void
1896 MooseApp::loadRestartableMetaData(const std::filesystem::path & folder_base)
1897 {
1898  for (const auto & name_map_pair : _restartable_meta_data)
1899  possiblyLoadRestartableMetaData(name_map_pair.first, folder_base);
1900 }
1901 
1902 std::vector<std::filesystem::path>
1904  const std::filesystem::path & folder_base)
1905 {
1906  if (processor_id() != 0)
1907  mooseError("MooseApp::writeRestartableMetaData(): Should only run on processor 0");
1908 
1909  const auto & map_name = getRestartableDataMapName(name);
1910  const auto meta_data_folder_base = metaDataFolderBase(folder_base, map_name);
1911 
1913  return writer.write(meta_data_folder_base);
1914 }
1915 
1916 std::vector<std::filesystem::path>
1917 MooseApp::writeRestartableMetaData(const std::filesystem::path & folder_base)
1918 {
1919  std::vector<std::filesystem::path> paths;
1920 
1921  if (processor_id() == 0)
1922  for (const auto & name_map_pair : _restartable_meta_data)
1923  {
1924  const auto map_paths = writeRestartableMetaData(name_map_pair.first, folder_base);
1925  paths.insert(paths.end(), map_paths.begin(), map_paths.end());
1926  }
1927 
1928  return paths;
1929 }
1930 
1931 void
1932 MooseApp::dynamicAppRegistration(const std::string & app_name,
1933  std::string library_path,
1934  const std::string & library_name,
1935  bool lib_load_deps)
1936 {
1937 #ifdef LIBMESH_HAVE_DLOPEN
1938  Parameters params;
1939  params.set<std::string>("app_name") = app_name;
1940  params.set<RegistrationType>("reg_type") = APPLICATION;
1941  params.set<std::string>("registration_method") = app_name + "__registerApps";
1942  params.set<std::string>("library_path") = library_path;
1943 
1944  const auto effective_library_name =
1945  library_name.empty() ? appNameToLibName(app_name) : library_name;
1946  params.set<std::string>("library_name") = effective_library_name;
1947  params.set<bool>("library_load_dependencies") = lib_load_deps;
1948 
1949  const auto paths = getLibrarySearchPaths(library_path);
1950  std::ostringstream oss;
1951 
1952  auto successfully_loaded = false;
1953  if (paths.empty())
1954  oss << '"' << app_name << "\" is not a registered application name.\n"
1955  << "No search paths were set. We made no attempts to locate the corresponding library "
1956  "file.\n";
1957  else
1958  {
1959  dynamicRegistration(params);
1960 
1961  // At this point the application should be registered so check it
1962  if (!AppFactory::instance().isRegistered(app_name))
1963  {
1964  oss << '"' << app_name << "\" is not a registered application name.\n"
1965  << "Unable to locate library archive for \"" << app_name
1966  << "\".\nWe attempted to locate the library archive \"" << effective_library_name
1967  << "\" in the following paths:\n\t";
1968  std::copy(paths.begin(), paths.end(), infix_ostream_iterator<std::string>(oss, "\n\t"));
1969  }
1970  else
1971  successfully_loaded = true;
1972  }
1973 
1974  if (!successfully_loaded)
1975  {
1976  oss << "\nMake sure you have compiled the library and either set the \"library_path\" "
1977  "variable in your input file or exported \"MOOSE_LIBRARY_PATH\".\n";
1978 
1979  mooseError(oss.str());
1980  }
1981 
1982 #else
1983  libmesh_ignore(app_name, library_path, library_name, lib_load_deps);
1984  mooseError("Dynamic Loading is either not supported or was not detected by libMesh configure.");
1985 #endif
1986 }
1987 
1988 void
1989 MooseApp::dynamicAllRegistration(const std::string & app_name,
1990  Factory * factory,
1991  ActionFactory * action_factory,
1992  Syntax * syntax,
1993  std::string library_path,
1994  const std::string & library_name)
1995 {
1996 #ifdef LIBMESH_HAVE_DLOPEN
1997  Parameters params;
1998  params.set<std::string>("app_name") = app_name;
1999  params.set<RegistrationType>("reg_type") = REGALL;
2000  params.set<std::string>("registration_method") = app_name + "__registerAll";
2001  params.set<std::string>("library_path") = library_path;
2002  params.set<std::string>("library_name") =
2003  library_name.empty() ? appNameToLibName(app_name) : library_name;
2004 
2005  params.set<Factory *>("factory") = factory;
2006  params.set<Syntax *>("syntax") = syntax;
2007  params.set<ActionFactory *>("action_factory") = action_factory;
2008  params.set<bool>("library_load_dependencies") = false;
2009 
2010  dynamicRegistration(params);
2011 #else
2012  libmesh_ignore(app_name, factory, action_factory, syntax, library_path, library_name);
2013  mooseError("Dynamic Loading is either not supported or was not detected by libMesh configure.");
2014 #endif
2015 }
2016 
2017 void
2018 MooseApp::dynamicRegistration(const Parameters & params)
2019 {
2020  const auto paths = getLibrarySearchPaths(params.get<std::string>("library_path"));
2021  const auto library_name = params.get<std::string>("library_name");
2022 
2023  // Attempt to dynamically load the library
2024  for (const auto & path : paths)
2025  if (MooseUtils::checkFileReadable(path + '/' + library_name, false, false))
2027  path + '/' + library_name, params, params.get<bool>("library_load_dependencies"));
2028 }
2029 
2030 void
2031 MooseApp::loadLibraryAndDependencies(const std::string & library_filename,
2032  const Parameters & params,
2033  const bool load_dependencies)
2034 {
2035  std::string line;
2036  std::string dl_lib_filename;
2037 
2038  // This RE looks for absolute path libtool filenames (i.e. begins with a slash and ends with a
2039  // .la)
2040  pcrecpp::RE re_deps("(/\\S*\\.la)");
2041 
2042  std::ifstream la_handle(library_filename.c_str());
2043  if (la_handle.is_open())
2044  {
2045  while (std::getline(la_handle, line))
2046  {
2047  // Look for the system dependent dynamic library filename to open
2048  if (line.find("dlname=") != std::string::npos)
2049  // Magic numbers are computed from length of this string "dlname=' and line minus that
2050  // string plus quotes"
2051  dl_lib_filename = line.substr(8, line.size() - 9);
2052 
2053  if (line.find("dependency_libs=") != std::string::npos)
2054  {
2055  if (load_dependencies)
2056  {
2057  pcrecpp::StringPiece input(line);
2058  pcrecpp::StringPiece depend_library;
2059  while (re_deps.FindAndConsume(&input, &depend_library))
2060  // Recurse here to load dependent libraries in depth-first order
2061  loadLibraryAndDependencies(depend_library.as_string(), params, load_dependencies);
2062  }
2063 
2064  // There's only one line in the .la file containing the dependency libs so break after
2065  // finding it
2066  break;
2067  }
2068  }
2069  la_handle.close();
2070  }
2071 
2072  // This should only occur if we have static linkage.
2073  if (dl_lib_filename.empty())
2074  return;
2075 
2076  const auto & [dir, file_name] = MooseUtils::splitFileName(library_filename);
2077 
2078  // Time to load the library, First see if we've already loaded this particular dynamic library
2079  // 1) make sure we haven't already loaded this library
2080  // AND 2) make sure we have a library name (we won't for static linkage)
2081  // Note: Here was are going to assume uniqueness based on the filename alone. This has significant
2082  // implications for applications that have "diamond" inheritance of libraries (usually
2083  // modules). We will only load one of those libraries, versions be damned.
2084  auto dyn_lib_it = _lib_handles.find(file_name);
2085  if (dyn_lib_it == _lib_handles.end())
2086  {
2087  // Assemble the actual filename using the base path of the *.la file and the dl_lib_filename
2088  const auto dl_lib_full_path = MooseUtils::pathjoin(dir, dl_lib_filename);
2089 
2090  MooseUtils::checkFileReadable(dl_lib_full_path, false, /*throw_on_unreadable=*/true);
2091 
2092 #ifdef LIBMESH_HAVE_DLOPEN
2093  void * const lib_handle = dlopen(dl_lib_full_path.c_str(), RTLD_LAZY);
2094 #else
2095  void * const lib_handle = nullptr;
2096 #endif
2097 
2098  if (!lib_handle)
2099  mooseError("The library file \"",
2100  dl_lib_full_path,
2101  "\" exists and has proper permissions, but cannot by dynamically loaded.\nThis "
2102  "generally means that the loader was unable to load one or more of the "
2103  "dependencies listed in the supplied library (see otool or ldd).\n",
2104  dlerror());
2105 
2106  DynamicLibraryInfo lib_info;
2107  lib_info.library_handle = lib_handle;
2108  lib_info.full_path = library_filename;
2109 
2110  auto insert_ret = _lib_handles.insert(std::make_pair(file_name, lib_info));
2111  mooseAssert(insert_ret.second == true, "Error inserting into lib_handles map");
2112 
2113  dyn_lib_it = insert_ret.first;
2114  }
2115 
2116  // Library has been loaded, check to see if we've called the requested registration method
2117  const auto registration_method = params.get<std::string>("registration_method");
2118  auto & entry_sym_from_curr_lib = dyn_lib_it->second.entry_symbols;
2119 
2120  if (entry_sym_from_curr_lib.find(registration_method) == entry_sym_from_curr_lib.end())
2121  {
2122  // get the pointer to the method in the library. The dlsym()
2123  // function returns a null pointer if the symbol cannot be found,
2124  // we also explicitly set the pointer to NULL if dlsym is not
2125  // available.
2126 #ifdef LIBMESH_HAVE_DLOPEN
2127  void * registration_handle =
2128  dlsym(dyn_lib_it->second.library_handle, registration_method.c_str());
2129 #else
2130  void * registration_handle = nullptr;
2131 #endif
2132 
2133  if (registration_handle)
2134  {
2135  switch (params.get<RegistrationType>("reg_type"))
2136  {
2137  case APPLICATION:
2138  {
2139  using register_app_t = void (*)();
2140  register_app_t * const reg_ptr = reinterpret_cast<register_app_t *>(&registration_handle);
2141  (*reg_ptr)();
2142  break;
2143  }
2144  case REGALL:
2145  {
2146  using register_app_t = void (*)(Factory *, ActionFactory *, Syntax *);
2147  register_app_t * const reg_ptr = reinterpret_cast<register_app_t *>(&registration_handle);
2148  (*reg_ptr)(params.get<Factory *>("factory"),
2149  params.get<ActionFactory *>("action_factory"),
2150  params.get<Syntax *>("syntax"));
2151  break;
2152  }
2153  default:
2154  mooseError("Unhandled RegistrationType");
2155  }
2156 
2157  entry_sym_from_curr_lib.insert(registration_method);
2158  }
2159  else
2160  {
2161 
2162 #if defined(DEBUG) && defined(LIBMESH_HAVE_DLOPEN)
2163  // We found a dynamic library that doesn't have a dynamic
2164  // registration method in it. This shouldn't be an error, so
2165  // we'll just move on.
2166  if (!registration_handle)
2167  mooseWarning("Unable to find extern \"C\" method \"",
2168  registration_method,
2169  "\" in library: ",
2170  dyn_lib_it->first,
2171  ".\n",
2172  "This doesn't necessarily indicate an error condition unless you believe that "
2173  "the method should exist in that library.\n",
2174  dlerror());
2175 #endif
2176  }
2177  }
2178 }
2179 
2180 std::set<std::string>
2182 {
2183  // Return the paths but not the open file handles
2184  std::set<std::string> paths;
2185  for (const auto & it : _lib_handles)
2186  paths.insert(it.first);
2187 
2188  return paths;
2189 }
2190 
2191 std::set<std::string>
2192 MooseApp::getLibrarySearchPaths(const std::string & library_path) const
2193 {
2194  std::set<std::string> paths;
2195 
2196  if (!library_path.empty())
2197  {
2198  std::vector<std::string> tmp_paths;
2199  MooseUtils::tokenize(library_path, tmp_paths, 1, ":");
2200 
2201  paths.insert(tmp_paths.begin(), tmp_paths.end());
2202  }
2203 
2204  char * moose_lib_path_env = std::getenv("MOOSE_LIBRARY_PATH");
2205  if (moose_lib_path_env)
2206  {
2207  std::string moose_lib_path(moose_lib_path_env);
2208  std::vector<std::string> tmp_paths;
2209  MooseUtils::tokenize(moose_lib_path, tmp_paths, 1, ":");
2210 
2211  paths.insert(tmp_paths.begin(), tmp_paths.end());
2212  }
2213 
2214  return paths;
2215 }
2216 
2219 {
2221 }
2222 
2223 std::string
2225 {
2226  return std::string("");
2227 }
2228 
2229 void
2231 {
2232  _restart = value;
2233 }
2234 
2235 void
2237 {
2238  _recover = value;
2239 }
2240 
2241 void
2243 {
2244  TIME_SECTION("createMinimalApp", 3, "Creating Minimal App");
2245 
2246  // SetupMeshAction
2247  {
2248  // Build the Action parameters
2249  InputParameters action_params = _action_factory.getValidParams("SetupMeshAction");
2250  action_params.set<std::string>("type") = "GeneratedMesh";
2251 
2252  // Create The Action
2253  std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
2254  _action_factory.create("SetupMeshAction", "Mesh", action_params));
2255 
2256  // Set the object parameters
2257  InputParameters & params = action->getObjectParams();
2258  params.set<MooseEnum>("dim") = "1";
2259  params.set<unsigned int>("nx") = 1;
2260 
2261  // Add Action to the warehouse
2263  }
2264 
2265  // Executioner
2266  {
2267  // Build the Action parameters
2268  InputParameters action_params = _action_factory.getValidParams("CreateExecutionerAction");
2269  action_params.set<std::string>("type") = "Transient";
2270 
2271  // Create the action
2272  std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
2273  _action_factory.create("CreateExecutionerAction", "Executioner", action_params));
2274 
2275  // Set the object parameters
2276  InputParameters & params = action->getObjectParams();
2277  params.set<unsigned int>("num_steps") = 1;
2278  params.set<Real>("dt") = 1;
2279 
2280  // Add Action to the warehouse
2282  }
2283 
2284  // Problem
2285  {
2286  // Build the Action parameters
2287  InputParameters action_params = _action_factory.getValidParams("CreateProblemDefaultAction");
2288  action_params.set<bool>("_solve") = false;
2289 
2290  // Create the action
2291  std::shared_ptr<Action> action = std::static_pointer_cast<Action>(
2292  _action_factory.create("CreateProblemDefaultAction", "Problem", action_params));
2293 
2294  // Add Action to the warehouse
2296  }
2297 
2298  // Outputs
2299  {
2300  // Build the Action parameters
2301  InputParameters action_params = _action_factory.getValidParams("CommonOutputAction");
2302  action_params.set<bool>("console") = false;
2303 
2304  // Create action
2305  std::shared_ptr<Action> action =
2306  _action_factory.create("CommonOutputAction", "Outputs", action_params);
2307 
2308  // Add Action to the warehouse
2310  }
2311 
2313 }
2314 
2315 bool
2316 MooseApp::hasRelationshipManager(const std::string & name) const
2317 {
2318  return std::find_if(_relationship_managers.begin(),
2319  _relationship_managers.end(),
2320  [&name](const std::shared_ptr<RelationshipManager> & rm)
2321  { return rm->name() == name; }) != _relationship_managers.end();
2322 }
2323 
2324 namespace
2325 {
2326 void
2327 donateForWhom(const RelationshipManager & donor, RelationshipManager & acceptor)
2328 {
2329  auto & existing_for_whom = acceptor.forWhom();
2330 
2331  // Take all the for_whoms from the donor, and give them to the acceptor
2332  for (auto & fw : donor.forWhom())
2333  {
2334  if (std::find(existing_for_whom.begin(), existing_for_whom.end(), fw) ==
2335  existing_for_whom.end())
2336  acceptor.addForWhom(fw);
2337  }
2338 }
2339 }
2340 
2341 bool
2342 MooseApp::addRelationshipManager(std::shared_ptr<RelationshipManager> new_rm)
2343 {
2344  // We prefer to always add geometric RMs. There is no hurt to add RMs for replicated mesh
2345  // since MeshBase::delete_remote_elements{} is a no-op (empty) for replicated mesh.
2346  // The motivation here is that MooseMesh::_use_distributed_mesh may not be properly set
2347  // at the time we are adding geometric relationship managers. We deleted the following
2348  // old logic to add all geometric RMs regardless of there is a distributed mesh or not.
2349  // Otherwise, all geometric RMs will be improperly ignored for a distributed mesh generator.
2350 
2351  // if (!_action_warehouse.mesh()->isDistributedMesh() && !_split_mesh &&
2352  // (relationship_manager->isType(Moose::RelationshipManagerType::GEOMETRIC) &&
2353  // !(relationship_manager->isType(Moose::RelationshipManagerType::ALGEBRAIC) ||
2354  // relationship_manager->isType(Moose::RelationshipManagerType::COUPLING))))
2355  // return false;
2356 
2357  bool add = true;
2358 
2359  std::set<std::shared_ptr<RelationshipManager>> rms_to_erase;
2360 
2361  for (const auto & existing_rm : _relationship_managers)
2362  {
2363  if (*existing_rm >= *new_rm)
2364  {
2365  add = false;
2366  donateForWhom(*new_rm, *existing_rm);
2367  break;
2368  }
2369  // The new rm did not provide less or the same amount/type of ghosting as the existing rm, but
2370  // what about the other way around?
2371  else if (*new_rm >= *existing_rm)
2372  rms_to_erase.emplace(existing_rm);
2373  }
2374 
2375  if (add)
2376  {
2377  _relationship_managers.emplace(new_rm);
2378  for (const auto & rm_to_erase : rms_to_erase)
2379  {
2380  donateForWhom(*rm_to_erase, *new_rm);
2381  removeRelationshipManager(rm_to_erase);
2382  }
2383  }
2384 
2385  // Inform the caller whether the object was added or not
2386  return add;
2387 }
2388 
2389 const std::string &
2391 {
2392  static const std::string suffix = "-mesh.cpr";
2393  return suffix;
2394 }
2395 
2396 std::filesystem::path
2397 MooseApp::metaDataFolderBase(const std::filesystem::path & folder_base,
2398  const std::string & map_suffix)
2399 {
2400  return RestartableDataIO::restartableDataFolder(folder_base /
2401  std::filesystem::path("meta_data" + map_suffix));
2402 }
2403 
2404 std::filesystem::path
2405 MooseApp::restartFolderBase(const std::filesystem::path & folder_base) const
2406 {
2407  auto folder = folder_base;
2408  folder += "-restart-" + std::to_string(processor_id());
2410 }
2411 
2412 const hit::Node *
2414 {
2415  if (const auto action = _action_warehouse.getCurrentAction())
2416  return action->parameters().getHitNode();
2417  return nullptr;
2418 }
2419 
2420 bool
2421 MooseApp::hasRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const
2422 {
2423  auto it = _template_to_clones.find(&template_rm);
2424  // C++ does short circuiting so we're safe here
2425  return (it != _template_to_clones.end()) && (it->second.find(&mesh) != it->second.end());
2426 }
2427 
2429 MooseApp::getRMClone(const RelationshipManager & template_rm, const MeshBase & mesh) const
2430 {
2431  auto outer_it = _template_to_clones.find(&template_rm);
2432  if (outer_it == _template_to_clones.end())
2433  mooseError("The template rm does not exist in our _template_to_clones map");
2434 
2435  auto & mesh_to_clone_map = outer_it->second;
2436  auto inner_it = mesh_to_clone_map.find(&mesh);
2437  if (inner_it == mesh_to_clone_map.end())
2438  mooseError("We should have the mesh key in our mesh");
2439 
2440  return *inner_it->second;
2441 }
2442 
2443 void
2444 MooseApp::removeRelationshipManager(std::shared_ptr<RelationshipManager> rm)
2445 {
2446  auto * const mesh = _action_warehouse.mesh().get();
2447  if (!mesh)
2448  mooseError("The MooseMesh should exist");
2449 
2450  const MeshBase * const undisp_lm_mesh = mesh->getMeshPtr();
2451  RelationshipManager * undisp_clone = nullptr;
2452  if (undisp_lm_mesh && hasRMClone(*rm, *undisp_lm_mesh))
2453  {
2454  undisp_clone = &getRMClone(*rm, *undisp_lm_mesh);
2455  const_cast<MeshBase *>(undisp_lm_mesh)->remove_ghosting_functor(*undisp_clone);
2456  }
2457 
2458  auto & displaced_mesh = _action_warehouse.displacedMesh();
2459  MeshBase * const disp_lm_mesh = displaced_mesh ? &displaced_mesh->getMesh() : nullptr;
2460  RelationshipManager * disp_clone = nullptr;
2461  if (disp_lm_mesh && hasRMClone(*rm, *disp_lm_mesh))
2462  {
2463  disp_clone = &getRMClone(*rm, *disp_lm_mesh);
2464  disp_lm_mesh->remove_ghosting_functor(*disp_clone);
2465  }
2466 
2467  if (_executioner)
2468  {
2469  auto & problem = feProblem();
2470  if (undisp_clone)
2471  {
2472  problem.removeAlgebraicGhostingFunctor(*undisp_clone);
2473  problem.removeCouplingGhostingFunctor(*undisp_clone);
2474  }
2475 
2476  auto * dp = problem.getDisplacedProblem().get();
2477  if (dp && disp_clone)
2478  dp->removeAlgebraicGhostingFunctor(*disp_clone);
2479  }
2480 
2482  _relationship_managers.erase(rm);
2483 }
2484 
2487  MooseMesh & moose_mesh,
2488  MeshBase & mesh,
2489  const DofMap * const dof_map)
2490 {
2491  auto & mesh_to_clone = _template_to_clones[&template_rm];
2492  auto it = mesh_to_clone.find(&mesh);
2493  if (it != mesh_to_clone.end())
2494  {
2495  // We've already created a clone for this mesh
2496  auto & clone_rm = *it->second;
2497  if (!clone_rm.dofMap() && dof_map)
2498  // We didn't have a DofMap before, but now we do, so we should re-init
2499  clone_rm.init(moose_mesh, mesh, dof_map);
2500  else if (clone_rm.dofMap() && dof_map && (clone_rm.dofMap() != dof_map))
2501  mooseError("Attempting to create and initialize an existing clone with a different DofMap. "
2502  "This should not happen.");
2503 
2504  return clone_rm;
2505  }
2506 
2507  // It's possible that this method is going to get called for multiple different MeshBase
2508  // objects. If that happens, then we *cannot* risk having a MeshBase object with a ghosting
2509  // functor that is init'd with another MeshBase object. So the safe thing to do is to make a
2510  // different RM for every MeshBase object that gets called here. Then the
2511  // RelationshipManagers stored here in MooseApp are serving as a template only
2512  auto pr = mesh_to_clone.emplace(
2513  std::make_pair(&const_cast<const MeshBase &>(mesh),
2514  dynamic_pointer_cast<RelationshipManager>(template_rm.clone())));
2515  mooseAssert(pr.second, "An insertion should have happened");
2516  auto & clone_rm = *pr.first->second;
2517  clone_rm.init(moose_mesh, mesh, dof_map);
2518  return clone_rm;
2519 }
2520 
2521 void
2522 MooseApp::attachRelationshipManagers(MeshBase & mesh, MooseMesh & moose_mesh)
2523 {
2524  for (auto & rm : _relationship_managers)
2525  {
2527  {
2528  if (rm->attachGeometricEarly())
2529  mesh.add_ghosting_functor(createRMFromTemplateAndInit(*rm, moose_mesh, mesh));
2530  else
2531  {
2532  // If we have a geometric ghosting functor that can't be attached early, then we have to
2533  // prevent the mesh from deleting remote elements
2534  moose_mesh.allowRemoteElementRemoval(false);
2535 
2536  if (const MeshBase * const moose_mesh_base = moose_mesh.getMeshPtr())
2537  {
2538  if (moose_mesh_base != &mesh)
2539  mooseError("The MooseMesh MeshBase and the MeshBase we're trying to attach "
2540  "relationship managers to are different");
2541  }
2542  else
2543  // The MeshBase isn't attached to the MooseMesh yet, so have to tell it not to remove
2544  // remote elements independently
2545  mesh.allow_remote_element_removal(false);
2546  }
2547  }
2548  }
2549 }
2550 
2551 void
2553  bool attach_geometric_rm_final)
2554 {
2555  for (auto & rm : _relationship_managers)
2556  {
2557  if (!rm->isType(rm_type))
2558  continue;
2559 
2560  // RM is already attached (this also handles the geometric early case)
2561  if (_attached_relationship_managers[rm_type].count(rm.get()))
2562  continue;
2563 
2565  {
2566  // The problem is not built yet - so the ActionWarehouse currently owns the mesh
2567  MooseMesh * const mesh = _action_warehouse.mesh().get();
2568 
2569  // "attach_geometric_rm_final = true" inidicate that it is the last chance to attach
2570  // geometric RMs. Therefore, we need to attach them.
2571  if (!rm->attachGeometricEarly() && !attach_geometric_rm_final)
2572  // Will attach them later (during algebraic). But also, we need to tell the mesh that we
2573  // shouldn't be deleting remote elements yet
2574  mesh->allowRemoteElementRemoval(false);
2575  else
2576  {
2577  MeshBase & undisp_mesh_base = mesh->getMesh();
2578  const DofMap * const undisp_sys_dof_map =
2579  _executioner ? &feProblem().getSolverSystem(0).dofMap() : nullptr;
2580  undisp_mesh_base.add_ghosting_functor(
2581  createRMFromTemplateAndInit(*rm, *mesh, undisp_mesh_base, undisp_sys_dof_map));
2582 
2583  // In the final stage, if there is a displaced mesh, we need to
2584  // clone ghosting functors for displacedMesh
2585  if (auto & disp_moose_mesh = _action_warehouse.displacedMesh();
2586  attach_geometric_rm_final && disp_moose_mesh)
2587  {
2588  MeshBase & disp_mesh_base = _action_warehouse.displacedMesh()->getMesh();
2589  const DofMap * disp_sys_dof_map = nullptr;
2590  if (_executioner && feProblem().getDisplacedProblem())
2591  disp_sys_dof_map = &feProblem().getDisplacedProblem()->solverSys(0).dofMap();
2592  disp_mesh_base.add_ghosting_functor(
2593  createRMFromTemplateAndInit(*rm, *disp_moose_mesh, disp_mesh_base, disp_sys_dof_map));
2594  }
2595  else if (_action_warehouse.displacedMesh())
2596  mooseError("The displaced mesh should not yet exist at the time that we are attaching "
2597  "early geometric relationship managers.");
2598 
2599  // Mark this RM as attached
2600  mooseAssert(!_attached_relationship_managers[rm_type].count(rm.get()), "Already attached");
2601  _attached_relationship_managers[rm_type].insert(rm.get());
2602  }
2603  }
2604  else // rm_type is algebraic or coupling
2605  {
2606  if (!_executioner && !_executor)
2607  mooseError("We must have an executioner by now or else we do not have to data to add "
2608  "algebraic or coupling functors to in MooseApp::attachRelationshipManagers");
2609 
2610  // Now we've built the problem, so we can use it
2611  auto & problem = feProblem();
2612  auto & undisp_moose_mesh = problem.mesh();
2613  auto & undisp_sys = feProblem().getSolverSystem(0);
2614  auto & undisp_sys_dof_map = undisp_sys.dofMap();
2615  auto & undisp_mesh = undisp_moose_mesh.getMesh();
2616 
2617  if (rm->useDisplacedMesh() && problem.getDisplacedProblem())
2618  {
2620  // We actually need to add this to the FEProblemBase NonlinearSystemBase's DofMap
2621  // because the DisplacedProblem "nonlinear" DisplacedSystem doesn't have any matrices
2622  // for which to do coupling. It's actually horrifying to me that we are adding a
2623  // coupling functor, that is going to determine its couplings based on a displaced
2624  // MeshBase object, to a System associated with the undisplaced MeshBase object (there
2625  // is only ever one EquationSystems object per MeshBase object and visa versa). So here
2626  // I'm left with the choice of whether to pass in a MeshBase object that is *not* the
2627  // MeshBase object that will actually determine the couplings or to pass in the MeshBase
2628  // object that is inconsistent with the System DofMap that we are adding the coupling
2629  // functor for! Let's err on the side of *libMesh* consistency and pass properly paired
2630  // MeshBase-DofMap
2631  problem.addCouplingGhostingFunctor(
2632  createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
2633  /*to_mesh = */ false);
2634 
2635  else if (rm_type == Moose::RelationshipManagerType::ALGEBRAIC)
2636  {
2637  auto & displaced_problem = *problem.getDisplacedProblem();
2638  auto & disp_moose_mesh = displaced_problem.mesh();
2639  auto & disp_mesh = disp_moose_mesh.getMesh();
2640  const DofMap * const disp_nl_dof_map = &displaced_problem.solverSys(0).dofMap();
2641  displaced_problem.addAlgebraicGhostingFunctor(
2642  createRMFromTemplateAndInit(*rm, disp_moose_mesh, disp_mesh, disp_nl_dof_map),
2643  /*to_mesh = */ false);
2644  }
2645  }
2646  else // undisplaced
2647  {
2649  problem.addCouplingGhostingFunctor(
2650  createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
2651  /*to_mesh = */ false);
2652 
2653  else if (rm_type == Moose::RelationshipManagerType::ALGEBRAIC)
2654  problem.addAlgebraicGhostingFunctor(
2655  createRMFromTemplateAndInit(*rm, undisp_moose_mesh, undisp_mesh, &undisp_sys_dof_map),
2656  /*to_mesh = */ false);
2657  }
2658 
2659  // Mark this RM as attached
2660  mooseAssert(!_attached_relationship_managers[rm_type].count(rm.get()), "Already attached");
2661  _attached_relationship_managers[rm_type].insert(rm.get());
2662  }
2663  }
2664 }
2665 
2666 std::vector<std::pair<std::string, std::string>>
2668 {
2669  std::vector<std::pair<std::string, std::string>> info_strings;
2670  info_strings.reserve(_relationship_managers.size());
2671 
2672  for (const auto & rm : _relationship_managers)
2673  {
2674  std::stringstream oss;
2675  oss << rm->getInfo();
2676 
2677  auto & for_whom = rm->forWhom();
2678 
2679  if (!for_whom.empty())
2680  {
2681  oss << " for ";
2682 
2683  std::copy(for_whom.begin(), for_whom.end(), infix_ostream_iterator<std::string>(oss, ", "));
2684  }
2685 
2686  info_strings.emplace_back(std::make_pair(Moose::stringify(rm->getType()), oss.str()));
2687  }
2688 
2689  // List the libMesh GhostingFunctors - Not that in libMesh all of the algebraic and coupling
2690  // Ghosting Functors are also attached to the mesh. This should catch them all.
2691  const auto & mesh = _action_warehouse.getMesh();
2692  if (mesh)
2693  {
2694  // Let us use an ordered map to avoid stochastic console behaviors.
2695  // I believe we won't have many RMs, and there is no performance issue.
2696  // Deterministic behaviors are good for setting up regression tests
2697  std::map<std::string, unsigned int> counts;
2698 
2699  for (auto & gf : as_range(mesh->getMesh().ghosting_functors_begin(),
2700  mesh->getMesh().ghosting_functors_end()))
2701  {
2702  const auto * gf_ptr = dynamic_cast<const RelationshipManager *>(gf);
2703  if (!gf_ptr)
2704  // Count how many occurences of the same Ghosting Functor types we are encountering
2705  counts[demangle(typeid(*gf).name())]++;
2706  }
2707 
2708  for (const auto & pair : counts)
2709  info_strings.emplace_back(std::make_pair(
2710  "Default", pair.first + (pair.second > 1 ? " x " + std::to_string(pair.second) : "")));
2711  }
2712 
2713  // List the libMesh GhostingFunctors - Not that in libMesh all of the algebraic and coupling
2714  // Ghosting Functors are also attached to the mesh. This should catch them all.
2715  const auto & d_mesh = _action_warehouse.getDisplacedMesh();
2716  if (d_mesh)
2717  {
2718  // Let us use an ordered map to avoid stochastic console behaviors.
2719  // I believe we won't have many RMs, and there is no performance issue.
2720  // Deterministic behaviors are good for setting up regression tests
2721  std::map<std::string, unsigned int> counts;
2722 
2723  for (auto & gf : as_range(d_mesh->getMesh().ghosting_functors_begin(),
2724  d_mesh->getMesh().ghosting_functors_end()))
2725  {
2726  const auto * gf_ptr = dynamic_cast<const RelationshipManager *>(gf);
2727  if (!gf_ptr)
2728  // Count how many occurences of the same Ghosting Functor types we are encountering
2729  counts[demangle(typeid(*gf).name())]++;
2730  }
2731 
2732  for (const auto & pair : counts)
2733  info_strings.emplace_back(
2734  std::make_pair("Default",
2735  pair.first + (pair.second > 1 ? " x " + std::to_string(pair.second) : "") +
2736  " for DisplacedMesh"));
2737  }
2738 
2739  return info_strings;
2740 }
2741 
2742 void
2744 {
2745  for (auto map_iter = _restartable_meta_data.begin(); map_iter != _restartable_meta_data.end();
2746  ++map_iter)
2747  {
2748  const RestartableDataMapName & name = map_iter->first;
2749  const RestartableDataMap & meta_data = map_iter->second.first;
2750 
2751  std::vector<std::string> not_declared;
2752 
2753  for (const auto & data : meta_data)
2754  if (!data.declared())
2755  not_declared.push_back(data.name());
2756 
2757  if (!not_declared.empty())
2758  {
2759  std::ostringstream oss;
2760  std::copy(
2761  not_declared.begin(), not_declared.end(), infix_ostream_iterator<std::string>(oss, ", "));
2762 
2763  mooseError("The following '",
2764  name,
2765  "' meta-data properties were retrieved but never declared: ",
2766  oss.str());
2767  }
2768  }
2769 }
2770 
2771 const RestartableDataMapName MooseApp::MESH_META_DATA = "MeshMetaData";
2773 
2776 {
2777  auto iter = _restartable_meta_data.find(name);
2778  if (iter == _restartable_meta_data.end())
2779  mooseError("Unable to find RestartableDataMap object for the supplied name '",
2780  name,
2781  "', did you call registerRestartableDataMapName in the application constructor?");
2782  return iter->second.first;
2783 }
2784 
2785 bool
2787 {
2788  return _restartable_meta_data.count(name);
2789 }
2790 
2791 void
2793 {
2794  if (!suffix.empty())
2795  std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
2796  suffix.insert(0, "_");
2797  _restartable_meta_data.emplace(
2798  std::make_pair(name, std::make_pair(RestartableDataMap(), suffix)));
2799 }
2800 
2801 const std::string &
2803 {
2804  const auto it = _restartable_meta_data.find(name);
2805  if (it == _restartable_meta_data.end())
2806  mooseError("MooseApp::getRestartableDataMapName: The name '", name, "' is not registered");
2807  return it->second.second;
2808 }
2809 
2810 PerfGraph &
2812 {
2814 
2815  auto perf_graph =
2816  std::make_unique<RestartableData<PerfGraph>>("perf_graph",
2817  this,
2818  type() + " (" + name() + ')',
2819  *this,
2820  getParam<bool>("perf_graph_live_all"),
2821  !getParam<bool>("disable_perf_graph_live"));
2822 
2823  return dynamic_cast<RestartableData<PerfGraph> &>(
2824  registerRestartableData(std::move(perf_graph), 0, false))
2825  .set();
2826 }
2827 
2830 {
2832 
2833  auto solution_invalidity =
2834  std::make_unique<RestartableData<SolutionInvalidity>>("solution_invalidity", nullptr, *this);
2835 
2836  return dynamic_cast<RestartableData<SolutionInvalidity> &>(
2837  registerRestartableData(std::move(solution_invalidity), 0, false))
2838  .set();
2839 }
2840 
2841 bool
2843 {
2844  return _action_warehouse.getCurrentTaskName() == "create_added_mesh_generators" ||
2846 }
std::list< std::string > getCheckpointFiles() const
Extract all possible checkpoint file names.
Definition: MooseApp.C:1746
virtual bool constructingMeshGenerators() const
Whether this app is constructing mesh generators.
Definition: MooseApp.C:2842
std::list< std::string > getCheckpointDirectories() const
Get all checkpoint directories.
Definition: MooseApp.C:1714
OStreamProxy err
RelationshipManager & createRMFromTemplateAndInit(const RelationshipManager &template_rm, MooseMesh &moose_mesh, MeshBase &mesh, const DofMap *dof_map=nullptr)
Take an input relationship manager, clone it, and then initialize it with provided mesh and optional ...
Definition: MooseApp.C:2486
static const std::string & checkpointSuffix()
The file suffix for the checkpoint mesh.
Definition: MooseApp.C:2390
std::string getFileName(bool stripLeadingPath=true) const
Return the primary (first) filename that was parsed Note: When stripLeadingPath is false...
Definition: MooseApp.C:1760
std::string docsDir(const std::string &app_name)
Returns the directory of any installed docs/site.
Definition: MooseUtils.C:120
Parser & parser()
Definition: MooseApp.C:1346
void build()
Parse an input file (or text string if provided) consisting of hit syntax and setup objects in the MO...
Definition: Builder.C:406
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:1338
virtual std::string getPrintableName() const
Get printable name of the application.
Definition: MooseApp.h:107
unsigned int _multiapp_level
Level of multiapp, the master is level 0. This used by the Console to indent output.
Definition: MooseApp.h:1405
virtual std::string getInstallableInputs() const
Method to retrieve the installable inputs from a given applications <app>Revision.h file.
Definition: MooseApp.C:1578
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:1155
void setOutputPosition(const Point &p)
Tell the app to output in a specific position.
Definition: MooseApp.C:1703
const std::string _type
The string representation of the type of this object as registered (see registerApp(AppName)) ...
Definition: MooseApp.h:1094
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:1175
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition: MooseApp.h:805
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:1252
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:1236
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 ...
Definition: MooseUtils.h:779
bool hasRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname) const
Definition: MooseApp.C:1852
virtual void setupOptions()
Setup options based on InputParameters.
Definition: MooseApp.C:681
PerfGraph & createRecoverablePerfGraph()
Creates a recoverable PerfGraph.
Definition: MooseApp.C:2811
std::string libNameToAppName(const std::string &library_name) const
Converts a library name to an application name:
Definition: MooseApp.C:1788
const unsigned int invalid_uint
RelationshipManagerType
Main types of Relationship Managers.
Definition: MooseTypes.h:876
const std::shared_ptr< Parser > _parser
Parser for parsing the input file.
Definition: MooseApp.h:1140
std::string getFrameworkVersion() const
Returns the framework version.
Definition: MooseApp.C:663
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:368
void setRecover(bool value)
Definition: MooseApp.C:2236
void buildFullTree(const std::string &search_string)
Use MOOSE Factories to construct a full parse tree for documentation or echoing input.
Definition: Builder.C:678
std::vector< std::pair< std::string, std::string > > getRelationshipManagerInfo() const
Returns the Relationship managers info suitable for printing.
Definition: MooseApp.C:2667
bool hasRMClone(const RelationshipManager &template_rm, const MeshBase &mesh) const
Definition: MooseApp.C:2421
bool _file_base_set_by_user
Whether or not file base is set through input or setOutputFileBase by MultiApp.
Definition: MooseApp.h:1103
const Action * getCurrentAction() const
bool _output_position_set
Whether or not an output position has been set for this app.
Definition: MooseApp.h:1106
Generic factory class for build all sorts of objects.
Definition: Factory.h:28
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
const std::vector< std::string > & getCommandLineSyntax(const std::string &name) const
std::unique_ptr< TheWarehouse > _the_warehouse
The combined warehouse for storing any MooseObject based object.
Definition: MooseApp.h:1402
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:1308
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:299
InputParameters & parameters()
Get the parameters of the object.
Definition: MooseApp.h:122
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:990
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:2397
bool _warnings_are_errors
Variable to toggle any warning into an error (includes deprecated code warnings)
Definition: Moose.C:644
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:98
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
Definition: MooseApp.C:2218
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.
Definition: MooseUtils.h:806
static const RestartableDataMapName MESH_META_DATA
Definition: MooseApp.h:95
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:1392
void dynamicRegistration(const Parameters &params)
Helper method for dynamic loading of objects.
Definition: MooseApp.C:2018
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:214
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:333
virtual std::string appBinaryName() const
Definition: MooseApp.h:109
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:1066
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:1147
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:2429
void setFinalTask(const std::string &task)
void registerRestartableNameWithFilter(const std::string &name, Moose::RESTARTABLE_FILTER filter)
NOTE: This is an internal function meant for MOOSE use only!
Definition: MooseApp.C:1193
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:1488
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition: Factory.C:110
void removeRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Purge this relationship manager from meshes and DofMaps and finally from us.
Definition: MooseApp.C:2444
Real _start_time
The time at which to start the simulation.
Definition: MooseApp.h:1115
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:1405
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:1353
std::filesystem::path restartFolderBase(const std::filesystem::path &folder_base) const
The file suffix for restartable data.
Definition: MooseApp.C:2405
std::pair< std::filesystem::path, std::filesystem::path > splitFileName(const T &full_file)
Function for splitting path and filename.
Definition: MooseUtils.h:231
if(subdm)
unsigned int multiAppLevel() const
The MultiApp Level.
Definition: MooseApp.h:794
MeshBase & mesh
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:67
const std::string _name
The name of this object.
Definition: MooseApp.h:1088
bool hasRelationshipManager(const std::string &name) const
Returns a Boolean indicating whether a RelationshipManater exists with the same name.
Definition: MooseApp.C:2316
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:794
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:1245
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:313
const Parallel::Communicator & comm() const
bool isParamValid(const std::string &name) const
Definition: MooseApp.h:163
bool hasRestartableDataMap(const RestartableDataMapName &name) const
Definition: MooseApp.C:2786
void addActionBlock(std::shared_ptr< Action > blk)
This method add an Action instance to the warehouse.
Syntax _syntax
Syntax of the input file.
Definition: MooseApp.h:1124
Syntax & syntax()
Returns a writable reference to the syntax object.
Definition: MooseApp.h:209
std::map< std::string, std::shared_ptr< Executor > > _executors
Pointers to all of the Executors for this run.
Definition: MooseApp.h:1170
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:1903
ExecuteMooseObjectWarehouse< MultiApp > & getMultiAppWarehouse()
bool _trap_fpe
Whether or not FPE trapping should be turned on.
Definition: MooseApp.h:1233
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
Returns the MPI processor ID of the current processor.
Definition: MooseApp.h:406
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:209
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:2413
ActionWarehouse _action_warehouse
Where built actions are stored.
Definition: MooseApp.h:1134
std::string realpath(const std::string &path)
Wrapper around PetscGetRealPath, which is a cross-platform replacement for realpath.
Definition: MooseUtils.C:1220
RestartableDataReader _rd_reader
Definition: MooseApp.h:1419
void checkMetaDataIntegrity() const
Function to check the integrity of the restartable meta data structure.
Definition: MooseApp.C:2743
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:96
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition: MooseApp.C:1167
bool isSplitMesh() const
Whether or not this is a split mesh operation.
Definition: MooseApp.C:1173
RestartableDataMap & getRestartableDataMap(const RestartableDataMapName &name)
Return a reference to restartable data for the specific type flag.
Definition: MooseApp.C:2775
std::unique_ptr< SystemInfo > _sys_info
System Information.
Definition: MooseApp.h:1195
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.
virtual const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:57
Base class for actions.
Definition: Action.h:38
std::string hostname()
Get the hostname the current process is running on.
Definition: MooseUtils.C:610
FEProblemBase & feProblem() const
Definition: MooseApp.C:1320
std::shared_ptr< Action > create(const std::string &action, const std::string &action_name, InputParameters &parameters)
Definition: ActionFactory.C:39
InputParameters emptyInputParameters()
void allowRemoteElementRemoval(bool allow_removal)
Set whether to allow remote element removal.
Definition: MooseMesh.C:3662
std::vector< RestartableDataMap > _restartable_data
Where the restartable data is held (indexed on tid)
Definition: MooseApp.h:1146
std::string camelCaseToUnderscore(const std::string &camel_case_name)
Function for converting a camel case name to a name containing underscores.
Definition: MooseUtils.C:554
void setOutputFileBase(const std::string &output_file_base)
Override the selection of the output file base name.
Definition: MooseApp.C:1075
Storage for restartable data that is ordered based on insertion order.
std::shared_ptr< MooseMesh > & mesh()
TODO: delete this later - it is a temporary hack for dealing with inter-system dependencies.
Definition: Attributes.h:294
MeshGeneratorSystem _mesh_generator_system
The system that manages the MeshGenerators.
Definition: MooseApp.h:1417
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:2552
const MeshBase * getMeshPtr() const
Definition: MooseMesh.C:3193
bool _start_time_set
Whether or not an start time has been set.
Definition: MooseApp.h:1112
virtual DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:1138
bool isParamSetByAddParam(const std::string &name) const
Returns whether or not the parameter was set due to addParam.
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:1881
void addMainCommandLineParams(InputParameters &params)
Adds the command line parameters needed from within main, which will also need to be added to MooseAp...
Definition: MooseMain.C:26
bool copyInputs() const
Handles the copy_inputs input parameter logic: Checks to see whether the passed argument is valid (a ...
Definition: MooseApp.C:1584
bool showInputs() const
Prints a message showing the installable inputs for a given application (if getInstallableInputs has ...
Definition: MooseApp.C:1547
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition: MooseApp.C:2342
RestartableDataValue & getRestartableMetaData(const std::string &name, const RestartableDataMapName &metaname, THREAD_ID tid)
Definition: MooseApp.C:1862
std::shared_ptr< NullExecutor > _null_executor
Used to return an executor that does nothing.
Definition: MooseApp.h:1186
const std::string & getLastInputFileName() const
Definition: MooseApp.C:1059
virtual void preBackup()
Insertion point for other apps that is called before backup()
Definition: MooseApp.h:724
InputParameters & getObjectParams()
Retreive 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:1482
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:758
T command_line_value(const std::string &, T)
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:1121
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:1224
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void indentMessage(const std::string &prefix, std::string &message, const char *color=COLOR_CYAN, bool dont_indent_first_line=true, const std::string &post_prefix=": ")
Indents the supplied message given the prefix and color.
Definition: MooseUtils.C:724
std::unique_ptr< Backup > backup()
Backs up the application memory in a Backup.
Definition: MooseApp.C:1219
bool _deprecated_is_error
Variable to toggle only deprecated warnings as errors.
Definition: Moose.C:645
RESTARTABLE_FILTER
The filter type applied to a particular piece of "restartable" data.
Definition: MooseTypes.h:704
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:1800
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:547
bool runInputs() const
Handles the run input parameter logic: Checks to see whether a directory exists in user space and lau...
Definition: MooseApp.C:1648
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:256
An inteface for the _console for outputting to the Console object.
void setRestart(bool value)
Sets the restart/recover flags.
Definition: MooseApp.C:2230
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:1164
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:1131
std::string runTestsExecutable()
Returns the location of either a local repo run_tests script - or an installed test executor script i...
Definition: MooseUtils.C:64
void disableLivePrint()
Completely disables Live Print (cannot be restarted)
Definition: PerfGraph.C:63
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:1269
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:566
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:31
RegistrationType
Enumeration for holding the valid types of dynamic registrations allowed.
Definition: MooseApp.h:1395
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:1221
void buildJsonSyntaxTree(JsonSyntaxTree &tree) const
Use MOOSE Factories to construct a parameter tree for documentation or echoing input.
Definition: Builder.C:564
Point _output_position
The output position.
Definition: MooseApp.h:1109
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:350
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:1208
virtual std::string getVersion() const
Returns the current version of the framework or application (default: framework version).
Definition: MooseApp.C:669
SolutionInvalidity & createRecoverableSolutionInvalidity()
Creates a recoverable SolutionInvalidity.
Definition: MooseApp.C:2829
bool _heap_profiling
Memory profiling.
Definition: MooseApp.h:1440
const MooseMesh *const _master_displaced_mesh
The displaced mesh from master app.
Definition: MooseApp.h:1414
std::string getPrimaryFileName(bool stripLeadingPath=true) const
Return the primary (first) filename that was parsed.
Definition: Builder.C:197
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:62
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:1476
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:2192
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
The SolutionInvalidity will contain all the information about the occurrence(s) of solution invalidit...
std::unordered_map< std::string, DynamicLibraryInfo > _lib_handles
The library archive (name only), registration method and the handle to the method.
Definition: MooseApp.h:1268
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:17
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
void releaseSharedObjects(const MooseObject &moose_object, THREAD_ID tid=0)
Releases any shared resources created as a side effect of creating an object through the Factory::cre...
Definition: Factory.C:126
const std::string & getCurrentTaskName() const
const std::string & getRestartableDataMapName(const RestartableDataMapName &name) const
Definition: MooseApp.C:2802
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
Helper class that hands out input streams to a stringstream.
bool hasRecoverFileBase() const
Definition: MooseApp.C:1185
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:1446
bool hasRestartRecoverFileBase() const
Return true if the recovery file base is set.
Definition: MooseApp.C:1179
void registerRestartableDataMapName(const RestartableDataMapName &name, std::string suffix="")
Reserve a location for storing custom RestartableDataMap objects.
Definition: MooseApp.C:2792
void restore(const std::filesystem::path &folder_base, const bool for_restart)
Restore an application from file.
Definition: MooseApp.C:1234
InputParameters _pars
Parameters of this object.
Definition: MooseApp.h:1091
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:1896
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition: MooseUtils.C:58
const T & getParam(const std::string &name)
Retrieve a parameter for the object.
Definition: MooseApp.h:1465
void addCommandLineParam(const std::string &name, const std::string &syntax, const std::string &doc_string)
virtual void executeExecutioner()
Execute the Executioner that was built.
Definition: MooseApp.C:1130
bool _distributed_mesh_on_command_line
This variable indicates that DistributedMesh should be used for the libMesh mesh underlying MooseMesh...
Definition: MooseApp.h:1218
void addExecutor(const std::string &type, const std::string &name, const InputParameters &params)
Definition: MooseApp.C:1326
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:261
Moose::Builder _builder
Builder for building app related parser tree.
Definition: MooseApp.h:1143
const std::shared_ptr< MooseMesh > & getDisplacedMesh() const
bool _test_checkpoint_half_transient
Whether or not this simulation should only run half its transient (useful for testing recovery) ...
Definition: MooseApp.h:1239
std::string RestartableDataMapName
Definition: MooseTypes.h:203
std::set< std::shared_ptr< RelationshipManager > > _relationship_managers
The relationship managers that have been added.
Definition: MooseApp.h:1248
OutputWarehouse _output_warehouse
OutputWarehouse object for this App.
Definition: MooseApp.h:1137
std::string _output_file_base
The output file basename.
Definition: MooseApp.h:1100
std::streambuf * _output_buffer_cache
Cache output buffer so the language server can turn it off then back on.
Definition: MooseApp.h:1431
const std::shared_ptr< Parallel::Communicator > _comm
The MPI communicator this App is going to use.
Definition: MooseApp.h:1097
static void addAppParam(InputParameters &params)
Definition: MooseApp.C:85
bool _cpu_profiling
CPU profiling.
Definition: MooseApp.h:1437
Concrete definition of a parameter value for a specified type.
void build()
Builds all auto-buildable tasks.
void registerAll(Factory &f, ActionFactory &af, Syntax &s)
Register objects that are in MOOSE.
virtual void runInputFile()
Actually build everything in the input file.
Definition: MooseApp.C:1091
void errorCheck(const Parallel::Communicator &comm, bool warn_unused, bool err_unused)
Definition: Builder.C:497
bool setColorConsole(bool use_color, bool force=false)
Turns color escape sequences on/off for info written to stdout.
Definition: Moose.C:638
virtual std::string header() const
Returns a string to be printed at the beginning of a simulation.
Definition: MooseApp.C:2224
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
std::vector< std::string > getConstructedObjects() const
Get a list of all constructed Moose Object types.
Definition: Factory.C:244
static const std::string MESH_META_DATA_SUFFIX
Definition: MooseApp.h:96
SolverSystem & getSolverSystem(unsigned int sys_num)
Get non-constant reference to a solver system.
Factory _factory
Definition: MooseApp.h:1205
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:1128
virtual std::unique_ptr< GhostingFunctor > clone() const
std::string getCurrentWorkingDir()
Returns the current working directory as a string.
Definition: MooseUtils.C:422
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
const std::vector< std::string > & getInputFileNames() const
Definition: MooseApp.C:1052
Tracks whether the object is on the displaced mesh.
Definition: Attributes.h:481
InputStreams clear()
Clears the contents of the reader (header stream, data stream, header)
MooseApp(InputParameters parameters)
Constructor is protected so that this object is constructed through the AppFactory object...
Definition: MooseApp.C:358
void makedirs(const std::string &dir_name, bool throw_on_failure=false)
Recursively make directories.
Definition: MooseUtils.C:435
std::unique_ptr< Backup > finalizeRestore()
Finalizes (closes) the restoration process done in restore().
Definition: MooseApp.C:1276
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.
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:1989
void loadLibraryAndDependencies(const std::string &library_filename, const Parameters &params, bool load_dependencies=true)
Recursively loads libraries and dependencies in the proper order to fully register a MOOSE applicatio...
Definition: MooseApp.C:2031
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:706
void setDeclared(const SetDeclaredKey)
Sets that this restartable value has been declared.
std::string getPrintableVersion() const
Non-virtual method for printing out the version string in a consistent format.
Definition: MooseApp.C:675
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:240
void createMinimalApp()
Method for creating the minimum required actions for an application (no input file) ...
Definition: MooseApp.C:2242
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition: MooseApp.C:1161
DataNames _recoverable_data_names
Data names that will only be read from the restart file during RECOVERY.
Definition: MooseApp.h:1152
Executor * getExecutor() const
Definition: MooseApp.h:319
bool _ready_to_exit
Definition: MooseApp.h:1209
The PerfGraph will hold the master list of all registered performance segments and the head PerfNode...
Definition: PerfGraph.h:43
const MooseMesh *const _master_mesh
The mesh from master app.
Definition: MooseApp.h:1411
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:1314
bool _split_mesh
Whether or not we are performing a split mesh operation (–split-mesh)
Definition: MooseApp.h:1227
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:1183
Abstract definition of a RestartableData value.
Class for parsing input files.
Definition: Parser.h:112
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:1766
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:1772
static char addKnownLabel(const std::string &label)
addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
Definition: Registry.C:82
virtual ~MooseApp()
Definition: MooseApp.C:631
unsigned int THREAD_ID
Definition: MooseTypes.h:198
void setStartTime(Real time)
Set the starting time for the simulation.
Definition: MooseApp.C:1753
std::shared_ptr< Executor > _executor
Pointer to the Executor of this run.
Definition: MooseApp.h:1167
The Executor class directs the execution flow of simulations.
Definition: Executor.h:26
std::string findTestRoot()
Searches in the current working directory and then recursively up in each parent directory looking fo...
Definition: MooseUtils.C:74
void errorCheck()
Runs post-initialization error checking that cannot be run correctly unless the simulation has been f...
Definition: MooseApp.C:1116
std::set< std::string > getLoadedLibraryPaths() const
Return the paths of loaded libraries.
Definition: MooseApp.C:2181
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:1932
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:1455