35#include "libmesh/mesh_tools.h"
36#include "libmesh/numeric_vector.h"
46#ifdef LIBMESH_HAVE_SYS_UTSNAME_H
47#include <sys/utsname.h>
56 params.
addParam<
bool>(
"use_displaced_mesh",
58 "Whether or not this object should use the "
59 "displaced mesh for computation. Note that "
60 "in the case this is true but no "
61 "displacements are provided in the Mesh block "
62 "the undisplaced mesh will still be used.");
64 std::ostringstream app_types_strings;
66 app_types_strings << name_bi_pair.first <<
" ";
67 MooseEnum app_types_options(app_types_strings.str(),
"",
true);
72 "The type of application to build (applications not "
73 "registered can be loaded with dynamic libraries. Parent "
74 "application type will be used if not provided.");
75 params.
addParam<std::string>(
"library_path",
77 "Path to search for dynamic libraries (please "
78 "avoid committing absolute paths in addition to "
79 "MOOSE_LIBRARY_PATH)");
83 "The file name of the library (*.la file) that will be dynamically loaded.");
84 params.
addParam<
bool>(
"library_load_dependencies",
86 "Tells MOOSE to manually load library dependencies. This should not be "
87 "necessary and is here for debugging/troubleshooting.");
92 "The positions of the App locations. Each set of 3 values will represent a "
93 "Point. This and 'positions_file' cannot be both supplied. If this and "
94 "'positions_file'/'_objects' are not supplied, a single position (0,0,0) will be used");
95 params.
addParam<std::vector<FileName>>(
"positions_file",
96 "Filename(s) that should be looked in for positions. Each"
97 " set of 3 values in that file will represent a Point. "
98 "This and 'positions(_objects)' cannot be both supplied");
99 params.
addParam<std::vector<PositionsName>>(
"positions_objects",
100 "The name of a Positions object that will contain "
101 "the locations of the sub-apps created. This and "
102 "'positions(_file)' cannot be both supplied");
104 "output_in_position",
106 "If true this will cause the output from the MultiApp to be 'moved' by its position vector");
110 "If true this will cause the mesh from the MultiApp to be 'moved' by its position vector");
114 "The input file for each App. If this parameter only contains one input file "
115 "it will be used for all of the Apps. When using 'positions_from_file' it is "
116 "also admissable to provide one input_file per file.");
117 params.
addParam<Real>(
"bounding_box_inflation",
119 "Relative amount to 'inflate' the bounding box of this MultiApp.");
120 params.
addParam<Point>(
"bounding_box_padding",
122 "Additional padding added to the dimensions of the bounding box. The "
123 "values are added to the x, y and z dimension respectively.");
130#ifdef LIBMESH_ENABLE_AMR
133 params.
setDocString(
"execute_on", exec_enum.getDocString());
138 std::numeric_limits<processor_id_type>::max(),
139 "max_procs_per_app > 0",
140 "Maximum number of processors to give to each App in this "
141 "MultiApp. Useful for restricting small solves to just a few "
142 "procs so they don't get spread out");
146 "min_procs_per_app > 0",
147 "Minimum number of processors to give to each App in this "
148 "MultiApp. Useful for larger, distributed mesh solves.");
150 "wait_for_first_app_init",
152 "Create the first sub-application on rank 0, then MPI_Barrier before "
153 "creating the next N-1 apps (on all ranks). "
154 "This is only needed if your sub-application needs to perform some setup "
155 "actions in quiet, without other sub-applications working at the same time.");
157 params.
addParam<Real>(
"global_time_offset",
159 "The time offset relative to the parent application for the purpose of "
160 "starting a subapp at a different time from the parent application. The "
161 "global time will be ahead by the offset specified here.");
167 "The time(s) at which to reset Apps given by the 'reset_apps' parameter. "
168 "Resetting an App means that it is destroyed and recreated, possibly "
169 "modeling the insertion of 'new' material for that app.");
170 params.
addParam<std::vector<unsigned int>>(
173 "The Apps that will be reset when 'reset_time' is hit. These are the App "
174 "'numbers' starting with 0 corresponding to the order of the App positions. "
175 "Resetting an App means that it is destroyed and recreated, possibly modeling "
176 "the insertion of 'new' material for that app.");
181 std::numeric_limits<Real>::max(),
182 "The time at which Apps designated by move_apps are moved to move_positions.");
184 params.
addParam<std::vector<unsigned int>>(
187 "Apps, designated by their 'numbers' starting with 0 corresponding to the order "
188 "of the App positions, to be moved at move_time to move_positions");
189 params.
addParam<std::vector<Point>>(
190 "move_positions", {},
"The positions corresponding to each move_app.");
192 params.
addParam<std::vector<CLIArgString>>(
195 "Additional command line arguments to pass to the sub apps. If one set is provided the "
196 "arguments are applied to all, otherwise there must be a set for each sub app.");
198 params.
addParam<std::vector<FileName>>(
200 "File names that should be looked in for additional command line arguments "
201 "to pass to the sub apps. Each line of a file is set to each sub app. If only "
202 "one line is provided, it will be applied to all sub apps.");
207 "relaxation_factor>0 & relaxation_factor<2",
208 "Fraction of newly computed value to keep."
209 "Set between 0 and 2.");
213 "Use transformed_variables.",
214 "List of subapp variables to relax during Multiapp coupling iterations");
215 params.
addParam<std::vector<std::string>>(
216 "transformed_variables",
218 "List of subapp variables to use coupling algorithm on during Multiapp coupling iterations");
219 params.
addParam<std::vector<PostprocessorName>>(
220 "transformed_postprocessors",
222 "List of subapp postprocessors to use coupling "
223 "algorithm on during Multiapp coupling iterations");
224 params.
addParam<
bool>(
"keep_solution_during_restore",
226 "This is useful when doing MultiApp coupling iterations. It takes the "
227 "final solution from the previous coupling iteration"
228 "and re-uses it as the initial guess for the next coupling iteration");
229 params.
addParam<
bool>(
"keep_aux_solution_during_restore",
231 "This is useful when doing MultiApp coupling iterations. It takes the "
232 "final auxiliary solution from the previous coupling iteration"
233 "and re-uses it as the initial guess for the next coupling iteration");
237 "True to turn off restore for this multiapp. This is useful when doing steady-state "
238 "Picard iterations where we want to use the solution of previous Picard iteration as the "
239 "initial guess of the current Picard iteration.");
241 "max_multiapp_level",
243 "Integer set by user that will stop the simulation if the multiapp level "
244 "exceeds it. Useful for preventing infinite loops with multiapp simulations");
248 "True to clone parent app mesh and use it for this MultiApp.",
249 "clone_master_mesh is deprecated, use clone_parent_mesh instead");
250 params.
addParam<
bool>(
"clone_parent_mesh",
252 "True to clone parent app mesh and use it for this MultiApp. In this "
253 "situation, all MeshGenerator parameters in the 'input_files' are ignored, "
254 "as well as nearly all parameters at the root level of the 'Mesh' block.");
256 params.
addParam<
unsigned int>(
"execution_order_group",
258 "Execution order group. If Problem/num_concurrent_multiapps>1, "
259 "multiple multiapps may be executed synchronously.");
269 "output_in_position",
270 "Positions / transformations of the MultiApp frame of reference");
274 params.
addParamNamesToGroup(
"relaxation_factor transformed_variables transformed_postprocessors "
275 "keep_solution_during_restore keep_aux_solution_during_restore "
277 "Fixed point iteration");
289 _fe_problem(*getCheckedPointerParam<
FEProblemBase *>(
"_fe_problem_base")),
290 _app_type(isParamValid(
"app_type") ?
std::string(getParam<
MooseEnum>(
"app_type"))
291 : _fe_problem.getMooseApp().type()),
292 _use_positions(getParam<bool>(
"use_positions")),
293 _create_child_apps_on_initial_setup(!_use_positions ||
294 _fe_problem.numConcurrentMultiApps() > 1),
295 _input_files(getParam<
std::vector<FileName>>(
"input_files")),
296 _wait_for_first_app_init(getParam<bool>(
"wait_for_first_app_init")),
300 _orig_comm(_communicator.get()),
302 _my_comm(_my_communicator.get()),
304 _inflation(getParam<Real>(
"bounding_box_inflation")),
305 _bounding_box_padding(getParam<Point>(
"bounding_box_padding")),
306 _max_procs_per_app(getParam<processor_id_type>(
"max_procs_per_app")),
307 _min_procs_per_app(getParam<processor_id_type>(
"min_procs_per_app")),
308 _output_in_position(getParam<bool>(
"output_in_position")),
309 _global_time_offset(getParam<Real>(
"global_time_offset")),
310 _reset_times(getParam<
std::vector<Real>>(
"reset_time")),
311 _reset_apps(getParam<
std::vector<unsigned
int>>(
"reset_apps")),
312 _reset_happened(false),
313 _move_time(getParam<Real>(
"move_time")),
314 _move_apps(getParam<
std::vector<unsigned
int>>(
"move_apps")),
315 _move_positions(getParam<
std::vector<Point>>(
"move_positions")),
316 _move_happened(false),
318 _cli_args(getParam<
std::vector<CLIArgString>>(
"cli_args")),
319 _keep_solution_during_restore(getParam<bool>(
"keep_solution_during_restore")),
320 _keep_aux_solution_during_restore(getParam<bool>(
"keep_aux_solution_during_restore")),
321 _no_restore(getParam<bool>(
"no_restore")),
322 _run_in_position(getParam<bool>(
"run_in_position")),
323 _sub_app_backups(declareRestartableDataWithContext<
SubAppBackups>(
"sub_app_backups", this)),
324 _solve_step_timer(registerTimedSection(
"solveStep", 3,
"Executing MultiApps", false)),
325 _init_timer(registerTimedSection(
"init", 3,
"Initializing MultiApp")),
326 _backup_timer(registerTimedSection(
"backup", 3,
"Backing Up MultiApp")),
327 _restore_timer(registerTimedSection(
"restore", 3,
"Restoring MultiApp")),
328 _reset_timer(registerTimedSection(
"resetApp", 3,
"Resetting MultiApp"))
333 "'cli_args' and 'cli_args_files' cannot be specified simultaneously in MultiApp ");
338 "This MultiApps has been set to not use positions, "
339 "but a 'positions' parameter has been set.");
343 mooseError(
"reset_time and reset_apps may only be specified together");
347 std::sort(sorted_times.begin(), sorted_times.end());
349 paramError(
"reset_time",
"List of reset times must be sorted in increasing order");
357 init(num_apps, config);
376 "The number of items supplied must be 1 or equal to the number of sub apps.");
383 mooseError(
"The number of items supplied as command line argument to subapps must be 1 or "
384 "equal to the number of sub apps. Note: you use a multiapp that provides its own "
385 "command line parameters so the error is not in cli_args");
406 "The number of apps is currently determined by the positions when creating child "
407 "apps immediately after multiapp construction");
417 TIME_SECTION(
"createApps", 2,
"Instantiating Sub-Apps",
false);
429 getParam<std::string>(
"library_path"),
430 getParam<std::string>(
"library_name"),
431 getParam<bool>(
"library_load_dependencies"));
433 bool rank_did_quiet_init =
false;
439 rank_did_quiet_init =
true;
449 if (rank_did_quiet_init && i == local_app)
479 std::vector<FileName> cli_args_files = getParam<std::vector<FileName>>(
"cli_args_files");
480 std::vector<FileName> input_files = getParam<std::vector<FileName>>(
"input_files");
483 if (!cli_args_files.size())
484 paramError(
"cli_args_files",
"You need to provide at least one commandLine argument file ");
488 if (cli_args_files.size() != 1 && cli_args_files.size() != input_files.size())
490 "The number of commandLine argument files ",
491 cli_args_files.size(),
494 " must either be only one or match the number of input files ",
498 std::vector<std::string> cli_args;
499 for (
unsigned int p_file_it = 0; p_file_it < cli_args_files.size(); p_file_it++)
501 std::string cli_args_file = cli_args_files[p_file_it];
509 std::ifstream is(cli_args_file.c_str());
512 while (std::getline(is, line))
513 cli_args.push_back(line);
516 if (!cli_args.size())
518 "There is no commandLine argument in the commandLine argument file ",
529 if (cli_args.size() == 1)
530 for (MooseIndex(num_positions) num = 0; num < num_positions; num++)
532 else if (cli_args.size() == num_positions)
533 for (
auto && cli_arg : cli_args)
535 else if (cli_args.size() != num_positions)
537 "The number of commandLine argument strings ",
541 " must either be only one or match the number of positions ",
548 for (
auto && cli_arg : cli_args)
560 mooseError(
" The number of commandLine argument strings ",
562 " must either be only one or match the total "
563 "number of sub apps ",
567 mooseError(
"Cannot set commandLine arguments from both input_file and external files");
574 mooseError(
"The number of apps to move and the positions to move them to must be the same for "
581 mooseError(
"Only one 'positions' parameter may be specified");
585 _positions = getParam<std::vector<Point>>(
"positions");
588 mooseError(
"Not enough positions for the number of input files provided in MultiApp ",
593 std::vector<FileName> positions_files = getParam<std::vector<FileName>>(
"positions_file");
594 std::vector<FileName> input_files = getParam<std::vector<FileName>>(
"input_files");
596 if (input_files.size() != 1 && positions_files.size() != input_files.size())
597 mooseError(
"Number of input_files for MultiApp ",
599 " must either be only one or match the number of positions_file files");
602 if (input_files.size() != 1)
605 for (
unsigned int p_file_it = 0; p_file_it < positions_files.size(); p_file_it++)
607 std::string positions_file = positions_files[p_file_it];
613 for (
const auto & d : data)
619 for (
unsigned int i = 0; i < data.size(); ++i)
620 if (input_files.size() != 1)
626 const auto & positions_param_objs = getParam<std::vector<PositionsName>>(
"positions_objects");
627 const auto & input_files = getParam<std::vector<FileName>>(
"input_files");
629 if (input_files.size() != 1 && positions_param_objs.size() != input_files.size())
630 mooseError(
"Number of input_files for MultiApp ",
632 " must either be only one or match the number of positions_objects specified");
635 if (input_files.size() != 1)
639 unsigned int offset = 0;
641 for (
const auto p_obj_it : index_range(positions_param_objs))
643 const std::string & positions_name = positions_param_objs[p_obj_it];
649 for (
const auto & d : data)
657 "'" + positions_name +
"' is not of the expected type. Should be a Positions");
660 for (
unsigned int i = 0; i < data.size(); ++i)
662 if (input_files.size() != 1)
667 offset += data.size();
675 mooseError(
"Not enough positions for the number of input files provided in MultiApp ",
680 "Number of positions and input files are not the same!");
687 Real timestep_tol = 1e-13;
693 bool backup_apps =
false;
709 transfer->getAppInfo();
715 auto app_ptr =
_apps[i];
716 auto &
mesh = app_ptr->getExecutioner()->feProblem().mesh();
718 app_ptr->getExecutioner()->feProblem().coordTransform().transformMesh(
721 app_ptr->getExecutioner()->feProblem().coordTransform().transformMesh(
mesh,
726 mesh.getMesh().complete_preparation();
745 for (
unsigned int i = 0; i <
_move_apps.size(); i++)
768 for (
const auto & app_ptr :
_apps)
770 auto * executioner = app_ptr->getExecutioner();
771 mooseAssert(executioner,
"Executioner is nullptr");
774 executioner->feProblem().outputStep(
EXEC_FINAL);
781 for (
const auto & app_ptr :
_apps)
783 auto * executioner = app_ptr->getExecutioner();
784 mooseAssert(executioner,
"Executioner is nullptr");
786 executioner->postExecute();
796 _console <<
"Backed up MultiApp ... ";
826 for (
unsigned int j = 0; j <
_apps[i]->getExecutioner()->feProblem().numSolverSystems();
836 auto & sub_multiapps =
837 _apps[i]->getExecutioner()->feProblem().getMultiAppWarehouse().getObjects();
841 for (
auto & multi_app : sub_multiapps)
857 _console <<
"Restoring MultiApp ... ";
874 for (
unsigned int j = 0; j <
_apps[i]->getExecutioner()->feProblem().numSolverSystems();
877 _apps[i]->getExecutioner()->feProblem().getSolverSystem(j).solution() =
881 _apps[i]->getExecutioner()->feProblem().getSolverSystem(j).update();
892 _apps[i]->getExecutioner()->feProblem().getAuxiliarySystem().solution() =
896 _apps[i]->getExecutioner()->feProblem().getAuxiliarySystem().update();
903 for (
const auto & app_ptr :
_apps)
904 if (app_ptr->feProblem().getDisplacedProblem())
905 app_ptr->feProblem().getDisplacedProblem()->updateMesh();
909 for (
auto & app_ptr :
_apps)
910 app_ptr->getExecutioner()->fixedPointSolve().clearFixedPointStatus();
916 for (
auto & sub_app :
917 _apps[i]->getExecutioner()->feProblem().getMultiAppWarehouse().getObjects())
918 sub_app->restore(
false);
928 "This parameter should only be provided in parent app");
936 const Real min_x = box.first(0);
937 const Real max_x = box.second(0);
938 const Real min_y = box.first(1);
939 const Real max_y = box.second(1);
940 const Real min_z = box.first(2);
941 const Real max_z = box.second(2);
943 std::array<Point, 8> box_corners = {{Point(min_x, min_y, min_z),
944 Point(max_x, min_y, min_z),
945 Point(min_x, max_y, min_z),
946 Point(max_x, max_y, min_z),
947 Point(min_x, min_y, max_z),
948 Point(max_x, min_y, max_z),
949 Point(min_x, max_y, max_z),
950 Point(max_x, max_y, max_z)}};
953 for (
auto & corner : box_corners)
954 corner = transform(corner);
957 Point new_box_min = box_corners[0];
958 Point new_box_max = new_box_min;
959 for (
const auto p : make_range(1, 8))
962 const Point & pt = box_corners[p];
963 if (new_box_min(d) > pt(d))
964 new_box_min(d) = pt(d);
966 if (new_box_max(d) < pt(d))
967 new_box_max(d) = pt(d);
969 box.first = new_box_min;
970 box.second = new_box_max;
985 : fe_problem_base.
mesh();
1002 Point min = bbox.min();
1004 Point max = bbox.max();
1007 Point inflation_amount = (max - min) *
_inflation;
1009 Point inflated_min = min - inflation_amount;
1010 Point inflated_max = max + inflation_amount;
1012 Point shifted_min = inflated_min;
1013 Point shifted_max = inflated_max;
1020 shifted_min(0) = -inflated_max(0);
1021 shifted_min(1) = inflated_min(1);
1022 shifted_min(2) = -inflated_max(0);
1024 shifted_max(0) = inflated_max(0);
1025 shifted_max(1) = inflated_max(1);
1026 shifted_max(2) = inflated_max(0);
1029 if (coord_transform)
1031 BoundingBox transformed_bbox(shifted_min, shifted_max);
1033 return transformed_bbox;
1043 return BoundingBox(shifted_min, shifted_max);
1055 return _apps[local_app]->getExecutioner()->feProblem();
1062 "MultiApp::appProblem() is deprecated, call MultiApp::appProblemBase() instead.\n");
1068 return dynamic_cast<FEProblem &
>(
_apps[local_app]->getExecutioner()->feProblem());
1089NumericVector<Number> &
1115 return _apps[local_app].get();
1130 std::map<std::string, unsigned int> m =
_apps[local_app]->getOutputWarehouse().getFileNumbers();
1135 _apps[local_app]->getOutputWarehouse().setFileNumbers(m);
1151 _apps[local_app]->setOutputPosition(p);
1153 paramError(
"run_in_position",
"Moving apps and running apps in position is not supported");
1162 for (
unsigned int i = 0; i <
_apps.size(); i++)
1175 std::string full_name;
1179 full_name =
_app.
name() +
"_" + multiapp_name;
1181 full_name = multiapp_name;
1189 std::vector<std::string> input_cli_args;
1195 const std::set<std::string> recover_exclude =
1197 ? std::set<std::string>{}
1198 : std::set<std::string>{
"recover",
"test_checkpoint_half_transient"};
1202 name(), multiapp_name, input_cli_args, recover_exclude);
1208 <<
" on processor " <<
processor_id() <<
" with full name " << full_name
1209 << COLOR_DEFAULT << std::endl;
1213#ifdef MOOSE_MFEM_ENABLED
1219 app_params.
set<std::shared_ptr<mfem::Device>>(
"_mfem_device") =
1222 app_params.
set<std::set<std::string>>(
"_mfem_devices") = mfem_device_set;
1226 app_params.
set<std::shared_ptr<mfem::Device>>(
"_mfem_device") =
1229 app_params.
set<std::set<std::string>>(
"_mfem_devices") = mfem_device_set;
1232 if (getParam<bool>(
"clone_master_mesh") || getParam<bool>(
"clone_parent_mesh"))
1235 _console << COLOR_CYAN <<
"Cloned parent app mesh will be used for MultiApp " <<
name()
1236 << COLOR_DEFAULT << std::endl;
1237 app_params.
set<
bool>(
"_use_master_mesh") =
true;
1248 auto parser = std::make_unique<Parser>(input_file);
1249 parser->setCommandLineParams(app_cli->buildHitParams());
1253 const auto & app_type = parser->getAppType();
1254 if (app_type.empty() &&
_app_type.empty())
1255 mooseWarning(
"The application type is not specified for ",
1257 ". Please use [Application] block to specify the application type.");
1263 "' is not a registered application. The registered application is named: '",
1265 "'. Please double check the [Application] block to make sure the correct "
1266 "application is provided. \n");
1268 if (parser->getAppType().empty())
1271 app_params.
set<std::shared_ptr<Parser>>(
"_parser") = std::move(parser);
1272 app_params.
set<std::shared_ptr<CommandLine>>(
"_command_line") = std::move(app_cli);
1274 auto & app =
_apps[i];
1276 app->setGlobalTimeOffset(start_time);
1285 "Sub-apps are already displaced, so they are already output in position");
1288 app->setupOptions();
1294 if (app->getOutputFileBase().empty())
1298 mooseError(
"Maximum multiapp level has been reached. This is likely caused by an infinite loop "
1299 "in your multiapp system. If additional multiapp levels are needed, "
1300 "max_multiapp_level can be specified in the MuliApps block.");
1303 _apps[i]->fixedPointConfig().sub_relaxation_factor = getParam<Real>(
"relaxation_factor");
1304 _apps[i]->fixedPointConfig().sub_transformed_vars =
1305 getParam<std::vector<std::string>>(
"transformed_variables");
1308 _apps[i]->fixedPointConfig().sub_transformed_vars =
1309 getParam<std::vector<std::string>>(
"relaxed_variables");
1310 _apps[i]->fixedPointConfig().sub_transformed_pps =
1311 getParam<std::vector<PostprocessorName>>(
"transformed_postprocessors");
1313 app->runInputFile();
1314 auto fixed_point_solve = &(
_apps[i]->getExecutioner()->fixedPointSolve());
1315 if (fixed_point_solve)
1316 fixed_point_solve->allocateStorage(
false);
1321 auto &
mesh = app->getExecutioner()->feProblem().mesh();
1323 app->getExecutioner()->feProblem().coordTransform().transformMesh(
1326 app->getExecutioner()->feProblem().coordTransform().transformMesh(
mesh, Point(0, 0, 0));
1330 mesh.getMesh().complete_preparation();
1334std::vector<std::string>
1339 std::string combined_args;
1342 if (cla.size() == 1)
1343 combined_args = cla[0];
1347 cli_args_param =
"cli_args_files";
1351 else if (cla.size())
1356 cli_args_param =
"cli_args_files";
1365 if (combined_args.empty())
1371 for (
const auto & arg : args)
1375 const auto error =
"An empty MultiApp command line argument was provided. Your "
1376 "combined command line string has a ';' with no argument after it.";
1389 processor_id_type nprocs,
1391 processor_id_type min_app_procs,
1392 processor_id_type max_app_procs,
1395 if (min_app_procs > nprocs)
1396 mooseError(
"minimum number of procs per app is higher than the available number of procs");
1397 else if (min_app_procs > max_app_procs)
1398 mooseError(
"minimum number of procs per app must be lower than the max procs per app");
1400 mooseAssert(rank < nprocs,
"rank must be smaller than the number of procs");
1405 const processor_id_type slot_size =
1406 std::max(std::min(cast_int<processor_id_type>(nprocs / napps), max_app_procs), min_app_procs);
1407 const processor_id_type nslots = std::min(
1409 cast_int<processor_id_type>(std::min(
1410 static_cast<dof_id_type
>(std::numeric_limits<processor_id_type>::max()), napps)));
1411 mooseAssert(nprocs >= (nslots * slot_size),
1412 "Ensure that leftover procs is represented by an unsigned type");
1413 const processor_id_type leftover_procs = nprocs - nslots * slot_size;
1414 const dof_id_type apps_per_slot = napps / nslots;
1415 const dof_id_type leftover_apps = napps % nslots;
1417 std::vector<int> slot_for_rank(nprocs);
1418 processor_id_type slot = 0;
1419 processor_id_type procs_in_slot = 0;
1420 for (processor_id_type rankiter = 0; rankiter <= rank; rankiter++)
1423 slot_for_rank[rankiter] = cast_int<int>(slot);
1425 slot_for_rank[rankiter] = -1;
1430 if (procs_in_slot == slot_size + 1 * (slot < leftover_procs && slot_size < max_app_procs))
1437 if (slot_for_rank[rank] < 0)
1439 return {0, 0, 0, 0,
false, 0};
1440 const processor_id_type slot_num = cast_int<processor_id_type>(slot_for_rank[rank]);
1442 const bool is_first_local_rank = rank == 0 || (slot_for_rank[rank - 1] != slot_for_rank[rank]);
1443 const dof_id_type n_local_apps = apps_per_slot + 1 * (slot_num < leftover_apps);
1445 processor_id_type my_first_rank = 0;
1446 for (processor_id_type rankiter = rank; rankiter > 0; rankiter--)
1447 if (slot_for_rank[rank] != slot_for_rank[rankiter])
1449 my_first_rank = cast_int<processor_id_type>(slot_for_rank[rankiter + 1]);
1453 dof_id_type app_index = 0;
1454 for (processor_id_type slot = 0; slot < slot_num; slot++)
1456 const dof_id_type num_slot_apps = apps_per_slot + 1 * (slot < leftover_apps);
1457 app_index += num_slot_apps;
1461 return {n_local_apps, app_index, 1, slot_num, is_first_local_rank, my_first_rank};
1462 return {n_local_apps, app_index, n_local_apps, app_index, is_first_local_rank, my_first_rank};
1471 mooseCheckMPIErr(ierr);
1473 mooseCheckMPIErr(ierr);
1475#ifdef LIBMESH_HAVE_SYS_UTSNAME_H
1476 struct utsname sysInfo;
1485 mooseCheckMPIErr(ierr);
1492 mooseError(
"Internal error, a processor has an undefined app.");
1498 mooseCheckMPIErr(ierr);
1513 std::stringstream ss;
1514 ss <<
"Requesting app " << global_app <<
", but processor " <<
processor_id() <<
" ";
1516 ss <<
"does not own any apps";
1522 mooseError(
"Invalid global_app!\n", ss.str());
1544std::vector<std::string>
1555 const std::string multiapp_name =
1563 std::ostringstream multiapp_name;
1564 multiapp_name << base_name << std::setw(std::ceil(std::log10(total))) << std::setprecision(0)
1565 << std::setfill(
'0') << std::right << index;
1566 return multiapp_name.str();
1584 mooseAssert(multi_app,
"Not set");
1588 dataStore(stream, cast_ref<std::vector<std::unique_ptr<Backup>> &>(backups),
nullptr);
1595 mooseAssert(multi_app,
"Not set");
1597 dataLoad(stream, cast_ref<std::vector<std::unique_ptr<Backup>> &>(backups),
nullptr);
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
const ExecFlagType EXEC_PRE_MULTIAPP_SETUP
const ExecFlagType EXEC_TIMESTEP_BEGIN
const ExecFlagType EXEC_POST_ADAPTIVITY
const ExecFlagType EXEC_INITIAL
const ExecFlagType EXEC_FINAL
LocalRankConfig rankConfig(processor_id_type rank, processor_id_type nprocs, dof_id_type napps, processor_id_type min_app_procs, processor_id_type max_app_procs, bool batch_mode)
Returns app partitioning information relevant to the given rank for a multiapp scenario with the give...
void dataStore(std::ostream &stream, SubAppBackups &backups, void *context)
void dataLoad(std::istream &stream, SubAppBackups &backups, void *context)
LocalRankConfig rankConfig(processor_id_type rank, processor_id_type nprocs, dof_id_type napps, processor_id_type min_app_procs, processor_id_type max_app_procs, bool batch_mode=false)
Returns app partitioning information relevant to the given rank for a multiapp scenario with the give...
std::shared_ptr< DisplacedProblem > displaced_problem
void ErrorVector unsigned int
bool isRegistered(const std::string &app_name) const
Returns a Boolean indicating whether an application type has been registered.
InputParameters getValidParams(const std::string &name)
Get valid parameters for the object.
const auto & registeredObjects() const
Returns a reference to the map from names to AppFactoryBuildInfo pointers.
static std::unique_ptr< MooseApp > create(const std::string &app_type, const std::vector< std::string > &cli_args={})
Create an app with no input and command line arguments.
static AppFactory & instance()
Get the instance of the AppFactory.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
A MultiMooseEnum object to hold "execute_on" flags.
void addAvailableFlags(const ExecFlagType &flag, Args... flags)
Add additional execute_on flags to the list of possible flags.
Executioners are objects that do the actual work of solving your problem.
virtual bool lastSolveConverged() const =0
Whether or not the last solve converged.
FEProblemBase & feProblem()
Return a reference to this Executioner's FEProblemBase instance.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
bool verboseMultiApps() const
Whether or not to use verbose printing for MultiApps.
AuxiliarySystem & getAuxiliarySystem()
const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name, std::size_t t_index=0) const
Get a read-only reference to the value associated with a Postprocessor that exists.
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
const Positions & getPositionsObject(const std::string &name) const
Get the Positions object by its name.
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
virtual MooseMesh & mesh() override
const UserObject & getUserObjectBase(const std::string &name, const THREAD_ID tid=0) const
Get the user object by its name.
virtual libMesh::System & getSystem(const std::string &var_name) override
Returns the equation system containing the variable provided.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Base class for MOOSE-based applications.
Point getOutputPosition() const
Get the output position.
std::string getOutputFileBase(bool for_non_moose_build_output=false) const
Get the output file base name.
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
bool isRestarting() const
Whether or not this is a "restart" calculation.
unsigned int multiAppLevel() const
The MultiApp Level.
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
const std::set< std::string > & getMFEMDevices(Moose::PassKey< MultiApp >) const
Get the configured MFEM devices.
std::shared_ptr< mfem::Device > getMFEMDevice(Moose::PassKey< MultiApp >)
Get the MFEM device object.
void dynamicAppRegistration(const std::string &app_name, std::string library_path, const std::string &library_name, bool lib_load_deps)
std::shared_ptr< CommandLine > commandLine() const
Get the command line.
bool isRecovering() const
Whether or not this is a "recover" calculation.
const InputParameters & parameters() const
Get the parameters of the object.
const std::string & name() const
Get the name of the class.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
const InputParameters & _pars
The object's parameters.
const std::string & _name
The name of this class.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Every object that can be built by the factory should be derived from this class.
static InputParameters validParams()
MooseApp & _app
The MOOSE application this is associated with.
Utility class for reading delimited data (e.g., CSV data).
const std::vector< Point > getDataAsPoints() const
Get the data in Point format.
void setFormatFlag(FormatFlag value)
void read()
Perform the actual data reading.
Base class for all MultiAppTransfer objects.
A MultiApp represents one or more MOOSE applications that are running simultaneously.
std::vector< Real > _reset_times
The times at which to reset apps.
virtual void postExecute()
Method called at the end of the simulation (after finalize).
libMesh::Parallel::Communicator _my_communicator
The communicator object that holds the MPI_Comm that we're going to use.
virtual void finalize()
Method called towards the end of the simulation to execute on final.
virtual void preTransfer(Real dt, Real target_time)
Gets called just before transfers are done to the MultiApp (Which is just before the MultiApp is solv...
std::vector< std::string > _cli_args_from_file
CommandLine arguments from files.
const bool & _wait_for_first_app_init
Whether to create the first app on rank 0 while all other MPI ranks are idle.
bool usingPositions() const
Whether or not this MultiApp is using positions to track the number and location of the child applica...
virtual std::vector< std::string > cliArgs() const
function that provides cli_args to subapps
void buildComm()
Create an MPI communicator suitable for each app.
Real _inflation
Relative bounding box inflation.
std::vector< unsigned int > _positions_index_offsets
The offsets, in case multiple Positions objects are specified.
void keepSolutionDuringRestore(bool keep_solution_during_restore)
Preserve the solution from the previous simulation, and it is used as an initial guess for the next r...
bool _output_in_position
Whether or not to move the output of the MultiApp into position.
std::vector< bool > _has_bounding_box
Flag if this multi-app computed its bounding box (valid only for non-displaced meshes)
processor_id_type _min_procs_per_app
Minimum number of processors to give to each app.
virtual void resetApp(unsigned int global_app, Real time=0.0)
"Reset" the App corresponding to the global App number passed in.
FEProblemBase & appProblemBase(unsigned int app)
Get the FEProblemBase for the global app desired.
bool isFirstLocalRank() const
std::string _app_type
The type of application to build.
int _my_rank
The mpi "rank" of this processor in the sub communicator.
virtual void restore(bool force=true)
Restore the state of every Sub App.
virtual void moveApp(unsigned int global_app, Point p)
Move the global_app to Point p.
const Real _global_time_offset
The offset time so the MultiApp local time relative to the global time.
Real _move_time
The time at which to move apps.
bool needsRestoration()
Whether or not this MultiApp should be restored at the beginning of each Picard iteration.
void init(unsigned int num_apps, const LocalRankConfig &config)
Build communicators and reserve backups using a custom rank configuration.
const PerfID _backup_timer
void createApp(unsigned int i, Real start_time)
Helper function for creating an App instance.
MultiApp(const InputParameters ¶meters)
static std::string getMultiAppName(const std::string &base_name, dof_id_type index, dof_id_type total)
Helper for constructing the name of the multiapp.
int _orig_num_procs
The number of processors in the original comm.
std::vector< libMesh::BoundingBox > _bounding_box
This multi-app's bounding box.
std::vector< unsigned int > _npositions_inputfile
Number of positions for each input file.
std::optional< std::string > _cli_args_param
The parameter that was used to set the command line args, if any.
virtual void initialSetup() override
Method to be called in main-app initial setup for create sub-apps if using positions is false.
std::vector< MultiAppTransfer * > _associated_transfers
Transfers associated with this multiapp.
MPI_Comm & _my_comm
The MPI communicator this object is going to use.
bool hasLocalApp(unsigned int global_app) const
Whether or not the given global app number is on this processor.
virtual void preRunInputFile()
call back executed right before app->runInputFile()
const PerfID _restore_timer
void possiblyCreateChildApplications()
Called just after construction to allow derived classes to set _positions and create sub-apps accordi...
unsigned int _first_local_app
The number of the first app on this processor.
Point _bounding_box_padding
Additional padding added to the bounding box, useful for 1D meshes.
std::vector< const Positions * > _positions_objs
The positions of all of the apps, using the Positions system.
const Point & position(unsigned int app) const
The physical position of a global App number.
bool _has_an_app
Whether or not this processor as an App at all
processor_id_type _max_procs_per_app
Maximum number of processors to give to each app.
bool _move_happened
Whether or not the move has happened.
void createApps()
Create the provided number of apps.
bool _keep_aux_solution_during_restore
Flag indicates if or not restart the auxiliary system from the latest auxiliary solution.
std::vector< std::vector< std::unique_ptr< libMesh::NumericVector< Real > > > > _end_solutions
The solution from the end of the previous solve, this is cloned from the Nonlinear solution during re...
std::vector< unsigned int > _move_apps
The apps to be moved.
int _orig_rank
The mpi "rank" of this processor in the original communicator.
FEProblem & appProblem(unsigned int app)
Get the FEProblem for the global app is part of.
virtual void backup()
Save off the state of every Sub App.
const bool _use_positions
Toggle use of "positions".
void readCommandLineArguments()
Fill command line arguments for sub apps.
bool _keep_solution_during_restore
Flag indicates if or not restart from the latest solution.
static InputParameters validParams()
Real appPostprocessorValue(unsigned int app, const std::string &name)
Get a Postprocessor value for a specified global app.
void addAssociatedTransfer(MultiAppTransfer &transfer)
Add a transfer that is associated with this multiapp.
const MPI_Comm & _orig_comm
The original comm handle.
FEProblemBase & _fe_problem
The FEProblemBase this MultiApp is part of.
unsigned int _total_num_apps
The total number of apps to simulate.
unsigned int globalAppToLocal(unsigned int global_app)
Map a global App number to the local number.
SubAppBackups & _sub_app_backups
The cached subapp backups (passed from the parent app)
const bool _create_child_apps_on_initial_setup
Whether we create child apps during the initialSetup() call or immediately after the multiapps constr...
std::vector< std::shared_ptr< MooseApp > > _apps
Pointers to each of the Apps.
std::vector< bool > _reset_happened
Whether or not apps have been reset at each time.
MooseApp * localApp(unsigned int local_app)
Get the local MooseApp object.
void setAppOutputFileBase()
Sets all the app's output file bases.
virtual std::vector< std::string > getCommandLineArgs(const unsigned int local_app)
const UserObject & appUserObjectBase(unsigned int app, const std::string &name)
Get a UserObject base for a specific global app.
LocalRankConfig _rank_config
The app configuration resulting from calling init.
std::vector< std::unique_ptr< NumericVector< Real > > > _end_aux_solutions
The auxiliary solution from the end of the previous solve, this is cloned from the auxiliary solution...
virtual bool propagateRecoverToSubApps() const
Whether or not to propagate the parent's recover state (the –recover and –test-checkpoint-half-transi...
std::string _node_name
Node Name.
virtual void fillPositions()
must fill in _positions with the positions of the sub-aps
unsigned int _my_num_apps
The number of apps this object is involved in simulating.
virtual Executioner * getExecutioner(unsigned int app)
const PerfID _reset_timer
const std::vector< CLIArgString > & _cli_args
CommandLine arguments (controllable!)
std::vector< FileName > _input_files
The input file for each app's simulation.
virtual void createLocalApp(const unsigned int i)
Create the i-th local app.
std::vector< Point > _move_positions
The new positions for the apps to be moved.
std::vector< Point > _positions
The positions of all of the apps, using input constant vectors (to be deprecated)
virtual libMesh::NumericVector< libMesh::Number > & appTransferVector(unsigned int app, std::string var_name)
Get the vector to transfer to for this MultiApp.
virtual void parentOutputPositionChanged()
For apps outputting in position we need to change their output positions if their parent app moves.
const bool _run_in_position
Whether to run the child apps with their meshes transformed with the coordinate transforms.
static void transformBoundingBox(libMesh::BoundingBox &box, const MultiAppCoordTransform &transform)
Transform a bounding box according to the transformations in the provided coordinate transformation o...
virtual libMesh::BoundingBox getBoundingBox(unsigned int app, bool displaced_mesh, const MultiAppCoordTransform *coord_transform=nullptr)
Get the BoundingBox for the mesh associated with app The bounding box will be shifted to be in the co...
std::vector< unsigned int > _reset_apps
The apps to be reset.
std::map< std::string, unsigned int > getFileNumbers()
Extracts the file numbers from the output objects.
Interface for objects interacting with the PerfGraph.
const std::vector< Point > & getPositions(bool initial) const
{ Getters for the positions vector for the desired dimension 1D will be the only one guaranteed to su...
A class for creating restricted objects.
static InputParameters validParams()
void mooseWarning(Args &&... args) const
void mooseDeprecated(Args &&... args) const
Helper class for holding Sub-app backups.
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
NumericVector< Number > & solution()
void split(int color, int key, Communicator &target) const
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
Base class for transient executioners that use a FixedPointSolve solve object for multiapp-main app i...
Base class for user-specific data.
virtual std::unique_ptr< NumericVector< T > > clone() const=0
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
processor_id_type n_processors() const
std::unique_ptr< NumericVector< Number > > solution
std::vector< std::string > split(const std::string &str, const std::string &delimiter, std::size_t max_count)
std::string trim(const std::string &str, const std::string &white_space=" \t\n\v\f\r")
Standard scripting language trim function.
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
std::string stringify(const T &t)
conversion to string
const unsigned int invalid_uint
Holds app partitioning information relevant to the a particular rank for a multiapp scenario.
bool is_first_local_rank
This is true if this rank is the primary/zero rank for a (sub)app slot.
dof_id_type num_local_apps
The number of (sub)apps that should/will be run locally on this rank.
dof_id_type first_local_app_index
The (global) index of the first local app for this rank.