https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MultiApp.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10// MOOSE includes
11#include "MultiApp.h"
12
13#include "AppFactory.h"
14#include "AuxiliarySystem.h"
15#include "DisplacedProblem.h"
16#include "Console.h"
17#include "Executioner.h"
18#include "FEProblem.h"
19#include "MooseMesh.h"
20#include "MooseUtils.h"
21#include "OutputWarehouse.h"
22#include "SetupInterface.h"
23#include "UserObject.h"
24#include "CommandLine.h"
25#include "Conversion.h"
26#include "NonlinearSystemBase.h"
27#include "DelimitedFileReader.h"
29#include "MultiAppTransfer.h"
30#include "Positions.h"
31#include "Transient.h"
32#include "Backup.h"
33#include "Parser.h"
34
35#include "libmesh/mesh_tools.h"
36#include "libmesh/numeric_vector.h"
37
38// C++ includes
39#include <algorithm>
40#include <fstream>
41#include <iomanip>
42#include <iterator>
43#include <set>
44
45// Call to "uname"
46#ifdef LIBMESH_HAVE_SYS_UTSNAME_H
47#include <sys/utsname.h>
48#endif
49
52{
55
56 params.addParam<bool>("use_displaced_mesh",
57 false,
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.");
63
64 std::ostringstream app_types_strings;
65 for (const auto & name_bi_pair : AppFactory::instance().registeredObjects())
66 app_types_strings << name_bi_pair.first << " ";
67 MooseEnum app_types_options(app_types_strings.str(), "", true);
68
69 // Dynamic loading
70 params.addParam<MooseEnum>("app_type",
71 app_types_options,
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",
76 "",
77 "Path to search for dynamic libraries (please "
78 "avoid committing absolute paths in addition to "
79 "MOOSE_LIBRARY_PATH)");
80 params.addParam<std::string>(
81 "library_name",
82 "",
83 "The file name of the library (*.la file) that will be dynamically loaded.");
84 params.addParam<bool>("library_load_dependencies",
85 false,
86 "Tells MOOSE to manually load library dependencies. This should not be "
87 "necessary and is here for debugging/troubleshooting.");
88
89 // Subapp positions
90 params.addParam<std::vector<Point>>(
91 "positions",
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");
103 params.addParam<bool>(
104 "output_in_position",
105 false,
106 "If true this will cause the output from the MultiApp to be 'moved' by its position vector");
107 params.addParam<bool>(
108 "run_in_position",
109 false,
110 "If true this will cause the mesh from the MultiApp to be 'moved' by its position vector");
111
112 params.addRequiredParam<std::vector<FileName>>(
113 "input_files",
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",
118 0.01,
119 "Relative amount to 'inflate' the bounding box of this MultiApp.");
120 params.addParam<Point>("bounding_box_padding",
121 RealVectorValue(),
122 "Additional padding added to the dimensions of the bounding box. The "
123 "values are added to the x, y and z dimension respectively.");
124
125 params.addPrivateParam<MPI_Comm>("_mpi_comm");
126
127 // Set the default execution time
128 params.set<ExecFlagEnum>("execute_on", true) = EXEC_TIMESTEP_BEGIN;
129 // Add the POST_ADAPTIVITY execution flag.
130#ifdef LIBMESH_ENABLE_AMR
131 ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on");
133 params.setDocString("execute_on", exec_enum.getDocString());
134#endif
135
136 params.addRangeCheckedParam<processor_id_type>(
137 "max_procs_per_app",
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");
143 params.addRangeCheckedParam<processor_id_type>(
144 "min_procs_per_app",
145 1,
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.");
149 params.addParam<bool>(
150 "wait_for_first_app_init",
151 false,
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.");
156
157 params.addParam<Real>("global_time_offset",
158 0,
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.");
162
163 // Resetting subapps
164 params.addParam<std::vector<Real>>(
165 "reset_time",
166 {},
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>>(
171 "reset_apps",
172 {},
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.");
177
178 // Moving subapps
179 params.addParam<Real>(
180 "move_time",
181 std::numeric_limits<Real>::max(),
182 "The time at which Apps designated by move_apps are moved to move_positions.");
183
184 params.addParam<std::vector<unsigned int>>(
185 "move_apps",
186 {},
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.");
191
192 params.addParam<std::vector<CLIArgString>>(
193 "cli_args",
194 {},
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.");
197
198 params.addParam<std::vector<FileName>>(
199 "cli_args_files",
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.");
203
204 // Fixed point iterations
205 params.addRangeCheckedParam<Real>("relaxation_factor",
206 1.0,
207 "relaxation_factor>0 & relaxation_factor<2",
208 "Fraction of newly computed value to keep."
209 "Set between 0 and 2.");
210 params.addDeprecatedParam<std::vector<std::string>>(
211 "relaxed_variables",
212 {},
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",
217 {},
218 "List of subapp variables to use coupling algorithm on during Multiapp coupling iterations");
219 params.addParam<std::vector<PostprocessorName>>(
220 "transformed_postprocessors",
221 {},
222 "List of subapp postprocessors to use coupling "
223 "algorithm on during Multiapp coupling iterations");
224 params.addParam<bool>("keep_solution_during_restore",
225 false,
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",
230 false,
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");
234 params.addParam<bool>(
235 "no_restore",
236 false,
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.");
240 params.addParam<unsigned int>(
241 "max_multiapp_level",
242 10,
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");
245
246 params.addDeprecatedParam<bool>("clone_master_mesh",
247 false,
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",
251 false,
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.");
255
256 params.addParam<unsigned int>("execution_order_group",
257 0,
258 "Execution order group. If Problem/num_concurrent_multiapps>1, "
259 "multiple multiapps may be executed synchronously.");
260
261 params.addPrivateParam<bool>("use_positions", true);
262 params.declareControllable("enable");
263 params.declareControllable("cli_args", {EXEC_PRE_MULTIAPP_SETUP});
264 params.registerBase("MultiApp");
265
266 params.addParamNamesToGroup("use_displaced_mesh wait_for_first_app_init max_multiapp_level",
267 "Advanced");
268 params.addParamNamesToGroup("positions positions_file positions_objects run_in_position "
269 "output_in_position",
270 "Positions / transformations of the MultiApp frame of reference");
271 params.addParamNamesToGroup("min_procs_per_app max_procs_per_app", "Parallelism");
272 params.addParamNamesToGroup("reset_time reset_apps", "Reset MultiApp");
273 params.addParamNamesToGroup("move_time move_apps move_positions", "Timed move of MultiApps");
274 params.addParamNamesToGroup("relaxation_factor transformed_variables transformed_postprocessors "
275 "keep_solution_during_restore keep_aux_solution_during_restore "
276 "no_restore",
277 "Fixed point iteration");
278 params.addParamNamesToGroup("library_name library_path library_load_dependencies",
279 "Dynamic loading");
280 params.addParamNamesToGroup("cli_args cli_args_files", "Passing command line argument");
281 return params;
282}
283
285 : MooseObject(parameters),
286 SetupInterface(this),
287 Restartable(this, "MultiApps"),
288 PerfGraphInterface(this, std::string("MultiApp::") + _name),
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")),
297 _total_num_apps(0),
298 _my_num_apps(0),
299 _first_local_app(0),
300 _orig_comm(_communicator.get()),
301 _my_communicator(),
302 _my_comm(_my_communicator.get()),
303 _my_rank(0),
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),
317 _has_an_app(true),
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"))
329{
330 if (parameters.isParamSetByUser("cli_args") && parameters.isParamValid("cli_args") &&
331 parameters.isParamValid("cli_args_files"))
332 paramError("cli_args",
333 "'cli_args' and 'cli_args_files' cannot be specified simultaneously in MultiApp ");
334
335 if (!_use_positions && (isParamValid("positions") || isParamValid("positions_file") ||
336 isParamValid("positions_objects")))
337 paramError("use_positions",
338 "This MultiApps has been set to not use positions, "
339 "but a 'positions' parameter has been set.");
340
341 if ((_reset_apps.size() > 0 && _reset_times.size() == 0) ||
342 (_reset_apps.size() == 0 && _reset_times.size() > 0))
343 mooseError("reset_time and reset_apps may only be specified together");
344
345 // Check that the reset times are sorted by the user
346 auto sorted_times = _reset_times;
347 std::sort(sorted_times.begin(), sorted_times.end());
348 if (_reset_times.size() && _reset_times != sorted_times)
349 paramError("reset_time", "List of reset times must be sorted in increasing order");
350}
351
352void
353MultiApp::init(unsigned int num_apps, bool batch_mode)
354{
355 auto config = rankConfig(
357 init(num_apps, config);
358}
359
360void
361MultiApp::init(unsigned int num_apps, const LocalRankConfig & config)
362{
363 TIME_SECTION(_init_timer);
364
365 _total_num_apps = num_apps;
366 _rank_config = config;
367 buildComm();
369
370 _has_bounding_box.resize(_my_num_apps, false);
371 _reset_happened.resize(_reset_times.size(), false);
373
374 if ((_cli_args.size() > 1) && (_total_num_apps != _cli_args.size()))
375 paramError("cli_args",
376 "The number of items supplied must be 1 or equal to the number of sub apps.");
377
378 // if cliArgs() != _cli_args, then cliArgs() was overridden and we need to check it
379 auto cla = cliArgs();
380 if (cla != std::vector<std::string>(_cli_args.begin(), _cli_args.end()))
381 {
382 if ((cla.size() > 1) && (_total_num_apps != cla.size()))
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");
386 }
387}
388
389void
391{
392 // We need to count the apps to be able to partition them, either here in init(),
393 // or in the FEProblem before calling initialSetup()
394 if (_use_positions)
395 {
397 // This counts the apps and partitions them. The partitioning can be changed
398 // if the apps are not created straight away
399 init(_positions.size());
400 }
401
403 return;
404
405 mooseAssert(_use_positions,
406 "The number of apps is currently determined by the positions when creating child "
407 "apps immediately after multiapp construction");
408 createApps();
409}
410
411void
413{
414 if (!_has_an_app)
415 return;
416
417 TIME_SECTION("createApps", 2, "Instantiating Sub-Apps", false);
418
419 // Read commandLine arguments that will be used when creating apps
421
423
424 _apps.resize(_my_num_apps);
425
426 // If the user provided an unregistered app type, see if we can load it dynamically
427 if (!AppFactory::instance().isRegistered(_app_type))
429 getParam<std::string>("library_path"),
430 getParam<std::string>("library_name"),
431 getParam<bool>("library_load_dependencies"));
432
433 bool rank_did_quiet_init = false;
434 unsigned int local_app = libMesh::invalid_uint;
436 {
437 if (hasLocalApp(0))
438 {
439 rank_did_quiet_init = true;
440 local_app = globalAppToLocal(0);
441 createLocalApp(local_app);
442 }
443
444 MPI_Barrier(_orig_comm);
445 }
446
447 for (unsigned int i = 0; i < _my_num_apps; i++)
448 {
449 if (rank_did_quiet_init && i == local_app)
450 continue;
452 }
453}
454
455void
456MultiApp::createLocalApp(const unsigned int i)
457{
459}
460
461void
463{
464 // Sub-apps are created here (rather than right after constructing the MultiApp) when:
465 // - using concurrent multiapps as the partitioning is only assigned after all
466 // MultiApps have been constructed and child apps have been counted
467 // - using sampler-type multiapps as the partitioning is also handled by the sampler
469 createApps();
470}
471
472void
474{
475 if (isParamValid("cli_args_files"))
476 {
477 _cli_args_from_file.clear();
478
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");
481
482 // If we use parameter "cli_args_files", at least one file should be provided
483 if (!cli_args_files.size())
484 paramError("cli_args_files", "You need to provide at least one commandLine argument file ");
485
486 // If we multiple input files, then we need to check if the number of input files
487 // match with the number of argument files
488 if (cli_args_files.size() != 1 && cli_args_files.size() != input_files.size())
489 paramError("cli_args_files",
490 "The number of commandLine argument files ",
491 cli_args_files.size(),
492 " for MultiApp ",
493 name(),
494 " must either be only one or match the number of input files ",
495 input_files.size());
496
497 // Go through all argument 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++)
500 {
501 std::string cli_args_file = cli_args_files[p_file_it];
502 // Clear up
503 cli_args.clear();
504 // Read the file on the root processor then broadcast it
505 if (processor_id() == 0)
506 {
507 MooseUtils::checkFileReadable(cli_args_file);
508
509 std::ifstream is(cli_args_file.c_str());
510 // Read by line rather than space separated like the cli_args parameter
511 std::string line;
512 while (std::getline(is, line))
513 cli_args.push_back(line);
514
515 // We do not allow empty files
516 if (!cli_args.size())
517 paramError("cli_args_files",
518 "There is no commandLine argument in the commandLine argument file ",
519 cli_args_file);
520
521 // If we have position files, we need to
522 // make sure the number of commandLine argument strings
523 // match with the number of positions
524 if (_npositions_inputfile.size())
525 {
526 auto num_positions = _npositions_inputfile[p_file_it];
527 // Check if the number of commandLine argument strings equal to
528 // the number of positions
529 if (cli_args.size() == 1)
530 for (MooseIndex(num_positions) num = 0; num < num_positions; num++)
531 _cli_args_from_file.push_back(cli_args.front());
532 else if (cli_args.size() == num_positions)
533 for (auto && cli_arg : cli_args)
534 _cli_args_from_file.push_back(cli_arg);
535 else if (cli_args.size() != num_positions)
536 paramError("cli_args_files",
537 "The number of commandLine argument strings ",
538 cli_args.size(),
539 " in the file ",
540 cli_args_file,
541 " must either be only one or match the number of positions ",
542 num_positions);
543 }
544 else
545 {
546 // If we do not have position files, we will check if the number of
547 // commandLine argument strings match with the total number of subapps
548 for (auto && cli_arg : cli_args)
549 _cli_args_from_file.push_back(cli_arg);
550 }
551 }
552 }
553
554 // Broad cast all arguments to everyone
556 }
557
558 if (_cli_args_from_file.size() && _cli_args_from_file.size() != 1 &&
560 mooseError(" The number of commandLine argument strings ",
561 _cli_args_from_file.size(),
562 " must either be only one or match the total "
563 "number of sub apps ",
565
566 if (_cli_args_from_file.size() && cliArgs().size())
567 mooseError("Cannot set commandLine arguments from both input_file and external files");
568}
569
570void
572{
573 if (_move_apps.size() != _move_positions.size())
574 mooseError("The number of apps to move and the positions to move them to must be the same for "
575 "MultiApp ",
576 _name);
577
578 if (isParamValid("positions") + isParamValid("positions_file") +
579 isParamValid("positions_objects") >
580 1)
581 mooseError("Only one 'positions' parameter may be specified");
582
583 if (isParamValid("positions"))
584 {
585 _positions = getParam<std::vector<Point>>("positions");
586
587 if (_positions.size() < _input_files.size())
588 mooseError("Not enough positions for the number of input files provided in MultiApp ",
589 name());
590 }
591 else if (isParamValid("positions_file"))
592 {
593 std::vector<FileName> positions_files = getParam<std::vector<FileName>>("positions_file");
594 std::vector<FileName> input_files = getParam<std::vector<FileName>>("input_files");
595
596 if (input_files.size() != 1 && positions_files.size() != input_files.size())
597 mooseError("Number of input_files for MultiApp ",
598 name(),
599 " must either be only one or match the number of positions_file files");
600
601 // Clear out the _input_files because we're going to rebuild it
602 if (input_files.size() != 1)
603 _input_files.clear();
604
605 for (unsigned int p_file_it = 0; p_file_it < positions_files.size(); p_file_it++)
606 {
607 std::string positions_file = positions_files[p_file_it];
608 MooseUtils::DelimitedFileReader file(positions_file, &_communicator);
610 file.read();
611
612 const std::vector<Point> & data = file.getDataAsPoints();
613 for (const auto & d : data)
614 _positions.push_back(d);
615
616 // Save the number of positions for this input file
617 _npositions_inputfile.push_back(data.size());
618
619 for (unsigned int i = 0; i < data.size(); ++i)
620 if (input_files.size() != 1)
621 _input_files.push_back(input_files[p_file_it]);
622 }
623 }
624 else if (isParamValid("positions_objects"))
625 {
626 const auto & positions_param_objs = getParam<std::vector<PositionsName>>("positions_objects");
627 const auto & input_files = getParam<std::vector<FileName>>("input_files");
628
629 if (input_files.size() != 1 && positions_param_objs.size() != input_files.size())
630 mooseError("Number of input_files for MultiApp ",
631 name(),
632 " must either be only one or match the number of positions_objects specified");
633
634 // Clear out the _input_files because we're going to rebuild it
635 if (input_files.size() != 1)
636 _input_files.clear();
637
638 // Keeps track of where each positions object start in terms of subapp numbers
639 unsigned int offset = 0;
640
641 for (const auto p_obj_it : index_range(positions_param_objs))
642 {
643 const std::string & positions_name = positions_param_objs[p_obj_it];
644 auto positions_obj = &_fe_problem.getPositionsObject(positions_name);
645
646 const auto & data = positions_obj->getPositions(true);
647
648 // Append all positions from this object
649 for (const auto & d : data)
650 _positions.push_back(d);
651
652 // Save the number of positions for this input file
653 _npositions_inputfile.push_back(data.size());
654
655 if (!positions_obj)
656 paramError("positions_objects",
657 "'" + positions_name + "' is not of the expected type. Should be a Positions");
658
659 // Keep track of which positions is tied to what subapp
660 for (unsigned int i = 0; i < data.size(); ++i)
661 {
662 if (input_files.size() != 1)
663 _input_files.push_back(input_files[p_obj_it]);
664 _positions_objs.push_back(positions_obj);
665 _positions_index_offsets.push_back(offset);
666 }
667 offset += data.size();
668 }
669 }
670 else
671 {
672 _positions = {Point()};
673
674 if (_positions.size() < _input_files.size())
675 mooseError("Not enough positions for the number of input files provided in MultiApp ",
676 name());
677 }
678
679 mooseAssert(_input_files.size() == 1 || _positions.size() == _input_files.size(),
680 "Number of positions and input files are not the same!");
681}
682
683void
684MultiApp::preTransfer(Real /*dt*/, Real target_time)
685{
686 // Get a transient executioner to get a user-set tolerance
687 Real timestep_tol = 1e-13;
688 if (dynamic_cast<TransientBase *>(_fe_problem.getMooseApp().getExecutioner()))
689 timestep_tol =
690 dynamic_cast<TransientBase *>(_fe_problem.getMooseApp().getExecutioner())->timestepTol();
691
692 // Determination on whether we need to backup the app due to changes below
693 bool backup_apps = false;
694
695 // First, see if any Apps need to be reset
696 for (unsigned int i = 0; i < _reset_times.size(); i++)
697 {
698 if (!_reset_happened[i] && (target_time + timestep_tol >= _reset_times[i]))
699 {
700 _reset_happened[i] = true;
701 if (_reset_apps.size() > 0)
702 for (auto & app : _reset_apps)
703 resetApp(app);
704
705 // If we reset an application, then we delete the old objects, including the coordinate
706 // transformation classes. Consequently we need to reset the coordinate transformation classes
707 // in the associated transfer classes
708 for (auto * const transfer : _associated_transfers)
709 transfer->getAppInfo();
710
711 // Similarly we need to transform the mesh again
713 for (const auto i : make_range(_my_num_apps))
714 {
715 auto app_ptr = _apps[i];
716 auto & mesh = app_ptr->getExecutioner()->feProblem().mesh();
717 if (usingPositions())
718 app_ptr->getExecutioner()->feProblem().coordTransform().transformMesh(
720 else
721 app_ptr->getExecutioner()->feProblem().coordTransform().transformMesh(mesh,
722 Point(0, 0, 0));
723
724 // Transforming marks mesh->spatial_dimension() as invalid,
725 // so we reprepare before trying to print that later.
726 mesh.getMesh().complete_preparation();
727 }
728
729 // If the time step covers multiple reset times, set them all as having 'happened'
730 for (unsigned int j = i; j < _reset_times.size(); j++)
731 if (target_time + timestep_tol >= _reset_times[j])
732 _reset_happened[j] = true;
733
734 // Backup in case the next solve fails
735 backup_apps = true;
736
737 break;
738 }
739 }
740
741 // Now move any apps that should be moved
742 if (_use_positions && !_move_happened && target_time + timestep_tol >= _move_time)
743 {
744 _move_happened = true;
745 for (unsigned int i = 0; i < _move_apps.size(); i++)
747
748 // Backup in case the next solve fails
749 backup_apps = true;
750 }
751
752 if (backup_apps)
753 backup();
754}
755
758{
759 if (!_has_an_app)
760 mooseError("No app for ", name(), " on processor ", _orig_rank);
761
762 return _apps[globalAppToLocal(app)]->getExecutioner();
763}
764
765void
767{
768 for (const auto & app_ptr : _apps)
769 {
770 auto * executioner = app_ptr->getExecutioner();
771 mooseAssert(executioner, "Executioner is nullptr");
772
773 executioner->feProblem().execute(EXEC_FINAL);
774 executioner->feProblem().outputStep(EXEC_FINAL);
775 }
776}
777
778void
780{
781 for (const auto & app_ptr : _apps)
782 {
783 auto * executioner = app_ptr->getExecutioner();
784 mooseAssert(executioner, "Executioner is nullptr");
785
786 executioner->postExecute();
787 }
788}
789
790void
792{
793 TIME_SECTION(_backup_timer);
794
796 _console << "Backed up MultiApp ... ";
797
798 for (unsigned int i = 0; i < _my_num_apps; i++)
799 _sub_app_backups[i] = _apps[i]->backup();
800
802 _console << name() << std::endl;
803}
804
805void
807{
808 TIME_SECTION(_restore_timer);
809
810 if (force || needsRestoration())
811 {
812 // Must be restarting / recovering from main app so hold off on restoring
813 // Instead - the restore will happen in sub-apps' initialSetup()
814 // Note that _backups was already populated by dataLoad() in the main app
816 return;
817
818 // We temporarily copy and store solutions for all subapps
820 {
822
823 for (unsigned int i = 0; i < _my_num_apps; i++)
824 {
825 _end_solutions[i].resize(_apps[i]->getExecutioner()->feProblem().numSolverSystems());
826 for (unsigned int j = 0; j < _apps[i]->getExecutioner()->feProblem().numSolverSystems();
827 j++)
828 {
829 _end_solutions[i][j] = _apps[i]
830 ->getExecutioner()
831 ->feProblem()
832 .getSolverSystem(/*solver_sys=*/j)
833 .solution()
834 .clone();
835 }
836 auto & sub_multiapps =
837 _apps[i]->getExecutioner()->feProblem().getMultiAppWarehouse().getObjects();
838
839 // multiapps of each subapp should do the same things
840 // It is implemented recursively
841 for (auto & multi_app : sub_multiapps)
842 multi_app->keepSolutionDuringRestore(_keep_solution_during_restore);
843 }
844 }
845
846 // We temporarily copy and store solutions for all subapps
848 {
850
851 for (unsigned int i = 0; i < _my_num_apps; i++)
854 }
855
857 _console << "Restoring MultiApp ... ";
858
859 for (unsigned int i = 0; i < _my_num_apps; i++)
860 {
861 _apps[i]->restore(std::move(_sub_app_backups[i]), false);
862 _sub_app_backups[i] = _apps[i]->finalizeRestore();
863 mooseAssert(_sub_app_backups[i], "Should have a backup");
864 }
865
867 _console << name() << std::endl;
868
869 // Now copy the latest solutions back for each subapp
871 {
872 for (unsigned int i = 0; i < _my_num_apps; i++)
873 {
874 for (unsigned int j = 0; j < _apps[i]->getExecutioner()->feProblem().numSolverSystems();
875 j++)
876 {
877 _apps[i]->getExecutioner()->feProblem().getSolverSystem(/*solver_sys=*/j).solution() =
878 *_end_solutions[i][j];
879
880 // We need to synchronize solution so that local_solution has the right values
881 _apps[i]->getExecutioner()->feProblem().getSolverSystem(/*solver_sys=*/j).update();
882 }
883 }
884
885 _end_solutions.clear();
886 }
887 // Now copy the latest auxiliary solutions back for each subapp
889 {
890 for (unsigned int i = 0; i < _my_num_apps; i++)
891 {
892 _apps[i]->getExecutioner()->feProblem().getAuxiliarySystem().solution() =
894
895 // We need to synchronize solution so that local_solution has the right values
896 _apps[i]->getExecutioner()->feProblem().getAuxiliarySystem().update();
897 }
898
899 _end_aux_solutions.clear();
900 }
901
902 // Make sure the displaced mesh on the multiapp is up-to-date with displacement variables
903 for (const auto & app_ptr : _apps)
904 if (app_ptr->feProblem().getDisplacedProblem())
905 app_ptr->feProblem().getDisplacedProblem()->updateMesh();
906
907 // If we are restoring due to a failed solve, make sure reset the solved state in the sub-apps
909 for (auto & app_ptr : _apps)
910 app_ptr->getExecutioner()->fixedPointSolve().clearFixedPointStatus();
911 }
912 else
913 {
914 for (unsigned int i = 0; i < _my_num_apps; i++)
915 {
916 for (auto & sub_app :
917 _apps[i]->getExecutioner()->feProblem().getMultiAppWarehouse().getObjects())
918 sub_app->restore(false);
919 }
920 }
921}
922
923void
924MultiApp::keepSolutionDuringRestore(bool keep_solution_during_restore)
925{
926 if (_pars.isParamSetByUser("keep_solution_during_restore"))
927 paramError("keep_solution_during_restore",
928 "This parameter should only be provided in parent app");
929
930 _keep_solution_during_restore = keep_solution_during_restore;
931}
932
933void
934MultiApp::transformBoundingBox(BoundingBox & box, const MultiAppCoordTransform & transform)
935{
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);
942
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)}};
951
952 // transform each corner
953 for (auto & corner : box_corners)
954 corner = transform(corner);
955
956 // Create new bounding box
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))
960 for (const auto d : make_range(Moose::dim))
961 {
962 const Point & pt = box_corners[p];
963 if (new_box_min(d) > pt(d))
964 new_box_min(d) = pt(d);
965
966 if (new_box_max(d) < pt(d))
967 new_box_max(d) = pt(d);
968 }
969 box.first = new_box_min;
970 box.second = new_box_max;
971}
972
973BoundingBox
975 bool displaced_mesh,
976 const MultiAppCoordTransform * const coord_transform)
977{
978 if (!_has_an_app)
979 mooseError("No app for ", name(), " on processor ", _orig_rank);
980
981 unsigned int local_app = globalAppToLocal(app);
982 FEProblemBase & fe_problem_base = _apps[local_app]->getExecutioner()->feProblem();
983 MooseMesh & mesh = (displaced_mesh && fe_problem_base.getDisplacedProblem().get() != NULL)
984 ? fe_problem_base.getDisplacedProblem()->mesh()
985 : fe_problem_base.mesh();
986
987 {
989 if (displaced_mesh)
991 else
992 {
993 if (!_has_bounding_box[local_app])
994 {
996 _has_bounding_box[local_app] = true;
997 }
998 }
999 }
1000 BoundingBox bbox = _bounding_box[local_app];
1001
1002 Point min = bbox.min();
1003 min -= _bounding_box_padding;
1004 Point max = bbox.max();
1005 max += _bounding_box_padding;
1006
1007 Point inflation_amount = (max - min) * _inflation;
1008
1009 Point inflated_min = min - inflation_amount;
1010 Point inflated_max = max + inflation_amount;
1011
1012 Point shifted_min = inflated_min;
1013 Point shifted_max = inflated_max;
1014
1015 if ((!coord_transform || coord_transform->skipCoordinateCollapsing()) &&
1016 fe_problem_base.getCoordSystem(*(mesh.meshSubdomains().begin())) == Moose::COORD_RZ)
1017 {
1018 // If the problem is RZ then we're going to invent a box that would cover the whole "3D" app
1019 // FIXME: Assuming all subdomains are the same coordinate system type!
1020 shifted_min(0) = -inflated_max(0);
1021 shifted_min(1) = inflated_min(1);
1022 shifted_min(2) = -inflated_max(0);
1023
1024 shifted_max(0) = inflated_max(0);
1025 shifted_max(1) = inflated_max(1);
1026 shifted_max(2) = inflated_max(0);
1027 }
1028
1029 if (coord_transform)
1030 {
1031 BoundingBox transformed_bbox(shifted_min, shifted_max);
1032 transformBoundingBox(transformed_bbox, *coord_transform);
1033 return transformed_bbox;
1034 }
1035 else
1036 {
1037 // This is where the app is located. We need to shift by this amount.
1038 Point p = position(app);
1039
1040 // Shift them to the position they're supposed to be
1041 shifted_min += p;
1042 shifted_max += p;
1043 return BoundingBox(shifted_min, shifted_max);
1044 }
1045}
1046
1049{
1050 if (!_has_an_app)
1051 mooseError("No app for ", name(), " on processor ", _orig_rank);
1052
1053 unsigned int local_app = globalAppToLocal(app);
1054
1055 return _apps[local_app]->getExecutioner()->feProblem();
1056}
1057
1058FEProblem &
1059MultiApp::appProblem(unsigned int app)
1060{
1062 "MultiApp::appProblem() is deprecated, call MultiApp::appProblemBase() instead.\n");
1063 if (!_has_an_app)
1064 mooseError("No app for ", name(), " on processor ", _orig_rank);
1065
1066 unsigned int local_app = globalAppToLocal(app);
1067
1068 return dynamic_cast<FEProblem &>(_apps[local_app]->getExecutioner()->feProblem());
1069}
1070
1071const UserObject &
1072MultiApp::appUserObjectBase(unsigned int app, const std::string & name)
1073{
1074 if (!_has_an_app)
1075 mooseError("No app for ", MultiApp::name(), " on processor ", _orig_rank);
1076
1078}
1079
1080Real
1081MultiApp::appPostprocessorValue(unsigned int app, const std::string & name)
1082{
1083 if (!_has_an_app)
1084 mooseError("No app for ", MultiApp::name(), " on processor ", _orig_rank);
1085
1087}
1088
1089NumericVector<Number> &
1090MultiApp::appTransferVector(unsigned int app, std::string var_name)
1091{
1092 return *(appProblemBase(app).getSystem(var_name).solution);
1093}
1094
1095bool
1100
1101bool
1102MultiApp::hasLocalApp(unsigned int global_app) const
1103{
1104 if (_has_an_app && global_app >= _first_local_app &&
1105 global_app <= _first_local_app + (_my_num_apps - 1))
1106 return true;
1107
1108 return false;
1109}
1110
1111MooseApp *
1112MultiApp::localApp(unsigned int local_app)
1113{
1114 mooseAssert(local_app < _apps.size(), "Index out of range: " + Moose::stringify(local_app));
1115 return _apps[local_app].get();
1116}
1117
1118void
1119MultiApp::resetApp(unsigned int global_app, Real time)
1120{
1121 TIME_SECTION(_reset_timer);
1122
1124
1125 if (hasLocalApp(global_app))
1126 {
1127 unsigned int local_app = globalAppToLocal(global_app);
1128
1129 // Extract the file numbers from the output, so that the numbering is maintained after reset
1130 std::map<std::string, unsigned int> m = _apps[local_app]->getOutputWarehouse().getFileNumbers();
1131
1132 createApp(local_app, time);
1133
1134 // Reset the file numbers of the newly reset apps
1135 _apps[local_app]->getOutputWarehouse().setFileNumbers(m);
1136 }
1137}
1138
1139void
1140MultiApp::moveApp(unsigned int global_app, Point p)
1141{
1142 if (_use_positions)
1143 {
1144 _positions[global_app] = p;
1145
1146 if (hasLocalApp(global_app))
1147 {
1148 unsigned int local_app = globalAppToLocal(global_app);
1149
1151 _apps[local_app]->setOutputPosition(p);
1152 if (_run_in_position)
1153 paramError("run_in_position", "Moving apps and running apps in position is not supported");
1154 }
1155 }
1156}
1157
1158void
1160{
1162 for (unsigned int i = 0; i < _apps.size(); i++)
1163 _apps[i]->setOutputPosition(_app.getOutputPosition() + _positions[_first_local_app + i]);
1164}
1165
1166void
1167MultiApp::createApp(unsigned int i, Real start_time)
1168{
1169 // Delete the old app if we're resetting
1170 if (_apps[i])
1171 _apps[i].reset();
1172
1173 // Define the app name
1174 const std::string multiapp_name = getMultiAppName(name(), _first_local_app + i, _total_num_apps);
1175 std::string full_name;
1176
1177 // Only add parent name if the parent is not the main app
1178 if (_app.multiAppLevel() > 0)
1179 full_name = _app.name() + "_" + multiapp_name;
1180 else
1181 full_name = multiapp_name;
1182
1184 app_params.set<FEProblemBase *>("_parent_fep") = &_fe_problem;
1185 app_params.set<std::unique_ptr<Backup> *>("_initial_backup") = &_sub_app_backups[i];
1186
1187 // Build the CommandLine with the relevant options for this subapp and add the
1188 // cli args from the input file
1189 std::vector<std::string> input_cli_args;
1190 if (cliArgs().size() > 0 || _cli_args_from_file.size() > 0)
1191 input_cli_args = getCommandLineArgs(i);
1192 // FullSolveMultiApp (and its derived classes) always performs a complete fresh
1193 // solve on every execution, so the parent's recovery-related global CLI params
1194 // must not be propagated to those sub-apps.
1195 const std::set<std::string> recover_exclude =
1197 ? std::set<std::string>{}
1198 : std::set<std::string>{"recover", "test_checkpoint_half_transient"};
1199 // This will mark all hit CLI command line parameters that are passed to subapps
1200 // as used within the parent app (_app)
1201 auto app_cli = _app.commandLine()->initSubAppCommandLine(
1202 name(), multiapp_name, input_cli_args, recover_exclude);
1203 app_cli->parse();
1204
1206 _console << COLOR_CYAN << "Creating MultiApp " << name() << " of type " << _app_type
1207 << " of level " << _app.multiAppLevel() + 1 << " and number " << _first_local_app + i
1208 << " on processor " << processor_id() << " with full name " << full_name
1209 << COLOR_DEFAULT << std::endl;
1210 app_params.set<unsigned int>("_multiapp_level") = _app.multiAppLevel() + 1;
1211 app_params.set<unsigned int>("_multiapp_number") = _first_local_app + i;
1212 app_params.set<const MooseMesh *>("_master_mesh") = &_fe_problem.mesh();
1213#ifdef MOOSE_MFEM_ENABLED
1214 // MFEM device must only be set once across all apps
1215 // FIXME: this required that the base app is an MFEM app; itwill
1216 // still fail if multiple MFEM sub-apps are launched from a libMesh base app
1217 if (i == 0)
1218 {
1219 app_params.set<std::shared_ptr<mfem::Device>>("_mfem_device") =
1221 const auto & mfem_device_set = _app.getMFEMDevices(Moose::PassKey<MultiApp>());
1222 app_params.set<std::set<std::string>>("_mfem_devices") = mfem_device_set;
1223 }
1224 else
1225 {
1226 app_params.set<std::shared_ptr<mfem::Device>>("_mfem_device") =
1227 _apps[0]->getMFEMDevice(Moose::PassKey<MultiApp>());
1228 const auto & mfem_device_set = _apps[0]->getMFEMDevices(Moose::PassKey<MultiApp>());
1229 app_params.set<std::set<std::string>>("_mfem_devices") = mfem_device_set;
1230 }
1231#endif
1232 if (getParam<bool>("clone_master_mesh") || getParam<bool>("clone_parent_mesh"))
1233 {
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;
1240 app_params.set<const MooseMesh *>("_master_displaced_mesh") = &displaced_problem->mesh();
1241 }
1242
1243 // If only one input file was provided, use it for all the solves
1244 const auto input_index = _input_files.size() == 1 ? 0 : _first_local_app + i;
1245 const auto & input_file = _input_files[input_index];
1246
1247 // create new parser tree for the application and parse
1248 auto parser = std::make_unique<Parser>(input_file);
1249 parser->setCommandLineParams(app_cli->buildHitParams());
1250 parser->parse();
1251
1252 // Checks on app type
1253 const auto & app_type = parser->getAppType();
1254 if (app_type.empty() && _app_type.empty())
1255 mooseWarning("The application type is not specified for ",
1256 full_name,
1257 ". Please use [Application] block to specify the application type.");
1258 if (!app_type.empty() && app_type != _app_type && !AppFactory::instance().isRegistered(app_type))
1259 mooseError("In the ",
1260 full_name,
1261 ", '",
1262 app_type,
1263 "' is not a registered application. The registered application is named: '",
1264 _app_type,
1265 "'. Please double check the [Application] block to make sure the correct "
1266 "application is provided. \n");
1267
1268 if (parser->getAppType().empty())
1269 parser->setAppType(_app_type);
1270
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);
1273 _apps[i] = AppFactory::instance().create(_app_type, full_name, app_params, _my_comm);
1274 auto & app = _apps[i];
1275
1276 app->setGlobalTimeOffset(start_time);
1277 app->setOutputFileNumbers(_app.getOutputWarehouse().getFileNumbers());
1278 app->setRestart(_app.isRestarting());
1279 app->setRecover(propagateRecoverToSubApps() && _app.isRecovering());
1280
1281 if (_use_positions && getParam<bool>("output_in_position"))
1282 app->setOutputPosition(_app.getOutputPosition() + _positions[_first_local_app + i]);
1284 paramError("run_in_position",
1285 "Sub-apps are already displaced, so they are already output in position");
1286
1287 // Update the MultiApp level for the app that was just created
1288 app->setupOptions();
1289 // if multiapp does not have file base in Outputs input block, output file base will
1290 // be empty here since setupOptions() does not set the default file base with the multiapp
1291 // input file name. Parent app will create the default file base for multiapp by taking the
1292 // output base of the parent app problem and appending the name of the multiapp plus a number to
1293 // it
1294 if (app->getOutputFileBase().empty())
1297 if (_app.multiAppLevel() > getParam<unsigned int>("max_multiapp_level"))
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.");
1301
1302 // Transfer coupling relaxation information to the subapps
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");
1306 // Handle deprecated parameter
1307 if (!parameters().isParamSetByAddParam("relaxed_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");
1312
1313 app->runInputFile();
1314 auto fixed_point_solve = &(_apps[i]->getExecutioner()->fixedPointSolve());
1315 if (fixed_point_solve)
1316 fixed_point_solve->allocateStorage(false);
1317
1318 // Transform the app mesh if requested
1319 if (_run_in_position)
1320 {
1321 auto & mesh = app->getExecutioner()->feProblem().mesh();
1322 if (usingPositions())
1323 app->getExecutioner()->feProblem().coordTransform().transformMesh(
1325 else
1326 app->getExecutioner()->feProblem().coordTransform().transformMesh(mesh, Point(0, 0, 0));
1327
1328 // Transforming marks mesh->spatial_dimension() as invalid, so we
1329 // reprepare before trying to print that later.
1330 mesh.getMesh().complete_preparation();
1331 }
1332}
1333
1334std::vector<std::string>
1335MultiApp::getCommandLineArgs(const unsigned int local_app)
1336{
1337 const auto cla = cliArgs();
1338 auto cli_args_param = _cli_args_param;
1339 std::string combined_args;
1340
1341 // Single set of args from cliArgs() to be provided to all apps
1342 if (cla.size() == 1)
1343 combined_args = cla[0];
1344 // Single "cli_args_files" file to be provided to all apps
1345 else if (_cli_args_from_file.size() == 1)
1346 {
1347 cli_args_param = "cli_args_files";
1348 combined_args = _cli_args_from_file[0];
1349 }
1350 // Unique set of args from cliArgs() to be provided to each app
1351 else if (cla.size())
1352 combined_args = cla[local_app + _first_local_app];
1353 // Unique set of args from "cli_args_files" to be provided to all apps
1354 else
1355 {
1356 cli_args_param = "cli_args_files";
1357 combined_args = _cli_args_from_file[local_app + _first_local_app];
1358 }
1359
1360 // Remove all of the beginning and end whitespace so we can recognize truly empty
1361 combined_args = MooseUtils::trim(combined_args);
1362
1363 // MooseUtils::split will return a single empty entry if there is nothing,
1364 // so exit early if we have nothing
1365 if (combined_args.empty())
1366 return {};
1367
1368 // Split the argument into a vector of arguments, and make sure
1369 // that we don't have any empty arguments
1370 const auto args = MooseUtils::split(combined_args, ";");
1371 for (const auto & arg : args)
1372 {
1373 if (arg.empty())
1374 {
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.";
1377 if (cli_args_param)
1378 paramError(*cli_args_param, error);
1379 else
1380 mooseError(error);
1381 }
1382 }
1383
1384 return args;
1385}
1386
1388rankConfig(processor_id_type rank,
1389 processor_id_type nprocs,
1390 dof_id_type napps,
1391 processor_id_type min_app_procs,
1392 processor_id_type max_app_procs,
1393 bool batch_mode)
1394{
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");
1399
1400 mooseAssert(rank < nprocs, "rank must be smaller than the number of procs");
1401
1402 // A "slot" is a group of procs/ranks that are grouped together to run a
1403 // single (sub)app/sim in parallel.
1404
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(
1408 nprocs / slot_size,
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;
1416
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++)
1421 {
1422 if (slot < nslots)
1423 slot_for_rank[rankiter] = cast_int<int>(slot);
1424 else
1425 slot_for_rank[rankiter] = -1;
1426 procs_in_slot++;
1427 // this slot keeps growing until we reach slot size plus possibly an extra
1428 // proc if there were any leftover from the slotization of nprocs - this
1429 // must also make sure we don't go over max app procs.
1430 if (procs_in_slot == slot_size + 1 * (slot < leftover_procs && slot_size < max_app_procs))
1431 {
1432 procs_in_slot = 0;
1433 slot++;
1434 }
1435 }
1436
1437 if (slot_for_rank[rank] < 0)
1438 // ranks assigned a negative slot don't have any apps running on them.
1439 return {0, 0, 0, 0, false, 0};
1440 const processor_id_type slot_num = cast_int<processor_id_type>(slot_for_rank[rank]);
1441
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);
1444
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])
1448 {
1449 my_first_rank = cast_int<processor_id_type>(slot_for_rank[rankiter + 1]);
1450 break;
1451 }
1452
1453 dof_id_type app_index = 0;
1454 for (processor_id_type slot = 0; slot < slot_num; slot++)
1455 {
1456 const dof_id_type num_slot_apps = apps_per_slot + 1 * (slot < leftover_apps);
1457 app_index += num_slot_apps;
1458 }
1459
1460 if (batch_mode)
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};
1463}
1464
1465void
1467{
1468 int ierr;
1469
1470 ierr = MPI_Comm_size(_communicator.get(), &_orig_num_procs);
1471 mooseCheckMPIErr(ierr);
1472 ierr = MPI_Comm_rank(_communicator.get(), &_orig_rank);
1473 mooseCheckMPIErr(ierr);
1474
1475#ifdef LIBMESH_HAVE_SYS_UTSNAME_H
1476 struct utsname sysInfo;
1477 uname(&sysInfo);
1478 _node_name = sysInfo.nodename;
1479#else
1480 _node_name = "Unknown";
1481#endif
1482
1483 int rank;
1484 ierr = MPI_Comm_rank(_communicator.get(), &rank);
1485 mooseCheckMPIErr(ierr);
1486
1489
1492 mooseError("Internal error, a processor has an undefined app.");
1493
1494 if (_has_an_app)
1495 {
1497 ierr = MPI_Comm_rank(_my_comm, &_my_rank);
1498 mooseCheckMPIErr(ierr);
1499 }
1500 else
1501 {
1502 _communicator.split(MPI_UNDEFINED, rank, _my_communicator);
1503 _my_rank = 0;
1504 }
1505}
1506
1507unsigned int
1508MultiApp::globalAppToLocal(unsigned int global_app)
1509{
1510 if (global_app >= _first_local_app && global_app <= _first_local_app + (_my_num_apps - 1))
1511 return global_app - _first_local_app;
1512
1513 std::stringstream ss;
1514 ss << "Requesting app " << global_app << ", but processor " << processor_id() << " ";
1515 if (_my_num_apps == 0)
1516 ss << "does not own any apps";
1517 else if (_my_num_apps == 1)
1518 ss << "owns app " << _first_local_app;
1519 else
1520 ss << "owns apps " << _first_local_app << "-" << _first_local_app + (_my_num_apps - 1);
1521 ss << ".";
1522 mooseError("Invalid global_app!\n", ss.str());
1523 return 0;
1524}
1525
1526void
1530
1531void
1533{
1534 _associated_transfers.push_back(&transfer);
1535}
1536
1537void
1539{
1540 for (unsigned int i = 0; i < _my_num_apps; ++i)
1542}
1543
1544std::vector<std::string>
1546{
1547 // So that we can error out with paramError("cli_args", ...);
1548 _cli_args_param = "cli_args";
1549 return std::vector<std::string>(_cli_args.begin(), _cli_args.end());
1550}
1551
1552void
1554{
1555 const std::string multiapp_name =
1557 _apps[index]->setOutputFileBase(_app.getOutputFileBase() + "_" + multiapp_name);
1558}
1559
1560std::string
1561MultiApp::getMultiAppName(const std::string & base_name, dof_id_type index, dof_id_type total)
1562{
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();
1567}
1568
1569const Point &
1570MultiApp::position(unsigned int app) const
1571{
1572 // If we're not using positions, it won't have changed
1573 if (_positions_objs.empty())
1574 return _positions[app];
1575 else
1576 // Find which Positions object is specifying it, and query a potentially updated value
1577 return _positions_objs[app]->getPosition(app - _positions_index_offsets[app], false);
1578}
1579
1580void
1581dataStore(std::ostream & stream, SubAppBackups & backups, void * context)
1582{
1583 MultiApp * multi_app = static_cast<MultiApp *>(context);
1584 mooseAssert(multi_app, "Not set");
1585
1586 multi_app->backup();
1587
1588 dataStore(stream, cast_ref<std::vector<std::unique_ptr<Backup>> &>(backups), nullptr);
1589}
1590
1591void
1592dataLoad(std::istream & stream, SubAppBackups & backups, void * context)
1593{
1594 MultiApp * multi_app = static_cast<MultiApp *>(context);
1595 mooseAssert(multi_app, "Not set");
1596
1597 dataLoad(stream, cast_ref<std::vector<std::unique_ptr<Backup>> &>(backups), nullptr);
1598
1599 multi_app->restore();
1600}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
const ExecFlagType EXEC_PRE_MULTIAPP_SETUP
Definition Moose.C:57
const ExecFlagType EXEC_TIMESTEP_BEGIN
Definition Moose.C:38
const ExecFlagType EXEC_POST_ADAPTIVITY
Definition Moose.C:61
const ExecFlagType EXEC_INITIAL
Definition Moose.C:31
const ExecFlagType EXEC_FINAL
Definition Moose.C:49
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...
Definition MultiApp.C:1388
void dataStore(std::ostream &stream, SubAppBackups &backups, void *context)
Definition MultiApp.C:1581
void dataLoad(std::istream &stream, SubAppBackups &backups, void *context)
Definition MultiApp.C:1592
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...
Definition MultiApp.C:1388
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.
Definition AppFactory.h:168
InputParameters getValidParams(const std::string &name)
Get valid parameters for the object.
Definition AppFactory.C:35
const auto & registeredObjects() const
Returns a reference to the map from names to AppFactoryBuildInfo pointers.
Definition AppFactory.h:163
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.
Definition AppFactory.C:64
static AppFactory & instance()
Get the instance of the AppFactory.
Definition AppFactory.C:20
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.
Definition Executioner.h:37
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.
Definition FEProblem.h:21
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void declareControllable(const std::string &name, std::set< ExecFlagType > execute_flags={})
Declare the given parameters as controllable.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
bool isParamSetByAddParam(const std::string &name) const
Returns whether or not the parameter was set due to addParam.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
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 registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another,...
Base class for MOOSE-based applications.
Definition MooseApp.h:110
Point getOutputPosition() const
Get the output position.
Definition MooseApp.h:288
std::string getOutputFileBase(bool for_non_moose_build_output=false) const
Get the output file base name.
Definition MooseApp.C:1537
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
Definition MooseApp.C:2414
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition MooseApp.C:1680
unsigned int multiAppLevel() const
The MultiApp Level.
Definition MooseApp.h:855
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition MooseApp.C:2020
const std::set< std::string > & getMFEMDevices(Moose::PassKey< MultiApp >) const
Get the configured MFEM devices.
Definition MooseApp.h:1814
std::shared_ptr< mfem::Device > getMFEMDevice(Moose::PassKey< MultiApp >)
Get the MFEM device object.
Definition MooseApp.h:1134
void dynamicAppRegistration(const std::string &app_name, std::string library_path, const std::string &library_name, bool lib_load_deps)
Definition MooseApp.C:2586
std::shared_ptr< CommandLine > commandLine() const
Get the command line.
Definition MooseApp.h:424
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition MooseApp.C:1674
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
const InputParameters & _pars
The object's parameters.
Definition MooseBase.h:384
const std::string & _name
The name of this class.
Definition MooseBase.h:381
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
Definition MooseBase.h:87
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
Every object that can be built by the factory should be derived from this class.
Definition MooseObject.h:31
static InputParameters validParams()
Definition MooseObject.C:25
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
Utility class for reading delimited data (e.g., CSV data).
const std::vector< Point > getDataAsPoints() const
Get the data in Point format.
void read()
Perform the actual data reading.
This class contains transformation information that only exists in a context in which there are multi...
void skipCoordinateCollapsing(bool skip_coordinate_collapsing)
set whether coordinate collapsing operations should be skipped
Base class for all MultiAppTransfer objects.
A MultiApp represents one or more MOOSE applications that are running simultaneously.
Definition MultiApp.h:140
std::vector< Real > _reset_times
The times at which to reset apps.
Definition MultiApp.h:613
virtual void postExecute()
Method called at the end of the simulation (after finalize).
Definition MultiApp.C:779
libMesh::Parallel::Communicator _my_communicator
The communicator object that holds the MPI_Comm that we're going to use.
Definition MultiApp.h:568
virtual void finalize()
Method called towards the end of the simulation to execute on final.
Definition MultiApp.C:766
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...
Definition MultiApp.C:684
std::vector< std::string > _cli_args_from_file
CommandLine arguments from files.
Definition MultiApp.h:640
const bool & _wait_for_first_app_init
Whether to create the first app on rank 0 while all other MPI ranks are idle.
Definition MultiApp.h:547
bool usingPositions() const
Whether or not this MultiApp is using positions to track the number and location of the child applica...
Definition MultiApp.h:396
virtual std::vector< std::string > cliArgs() const
function that provides cli_args to subapps
Definition MultiApp.C:1545
void buildComm()
Create an MPI communicator suitable for each app.
Definition MultiApp.C:1466
Real _inflation
Relative bounding box inflation.
Definition MultiApp.h:595
std::vector< unsigned int > _positions_index_offsets
The offsets, in case multiple Positions objects are specified.
Definition MultiApp.h:533
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...
Definition MultiApp.C:924
bool _output_in_position
Whether or not to move the output of the MultiApp into position.
Definition MultiApp.h:607
std::vector< bool > _has_bounding_box
Flag if this multi-app computed its bounding box (valid only for non-displaced meshes)
Definition MultiApp.h:589
processor_id_type _min_procs_per_app
Minimum number of processors to give to each app.
Definition MultiApp.h:604
const PerfID _init_timer
Definition MultiApp.h:672
virtual void resetApp(unsigned int global_app, Real time=0.0)
"Reset" the App corresponding to the global App number passed in.
Definition MultiApp.C:1119
FEProblemBase & appProblemBase(unsigned int app)
Get the FEProblemBase for the global app desired.
Definition MultiApp.C:1048
bool isFirstLocalRank() const
Definition MultiApp.C:1096
std::string _app_type
The type of application to build.
Definition MultiApp.h:526
int _my_rank
The mpi "rank" of this processor in the sub communicator.
Definition MultiApp.h:583
virtual void restore(bool force=true)
Restore the state of every Sub App.
Definition MultiApp.C:806
virtual void moveApp(unsigned int global_app, Point p)
Move the global_app to Point p.
Definition MultiApp.C:1140
const Real _global_time_offset
The offset time so the MultiApp local time relative to the global time.
Definition MultiApp.h:610
Real _move_time
The time at which to move apps.
Definition MultiApp.h:622
bool needsRestoration()
Whether or not this MultiApp should be restored at the beginning of each Picard iteration.
Definition MultiApp.h:242
void init(unsigned int num_apps, const LocalRankConfig &config)
Build communicators and reserve backups using a custom rank configuration.
Definition MultiApp.C:361
const PerfID _backup_timer
Definition MultiApp.h:673
void createApp(unsigned int i, Real start_time)
Helper function for creating an App instance.
Definition MultiApp.C:1167
MultiApp(const InputParameters &parameters)
Definition MultiApp.C:284
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.
Definition MultiApp.C:1561
int _orig_num_procs
The number of processors in the original comm.
Definition MultiApp.h:574
std::vector< libMesh::BoundingBox > _bounding_box
This multi-app's bounding box.
Definition MultiApp.h:592
std::vector< unsigned int > _npositions_inputfile
Number of positions for each input file.
Definition MultiApp.h:550
std::optional< std::string > _cli_args_param
The parameter that was used to set the command line args, if any.
Definition MultiApp.h:679
virtual void initialSetup() override
Method to be called in main-app initial setup for create sub-apps if using positions is false.
Definition MultiApp.C:462
std::vector< MultiAppTransfer * > _associated_transfers
Transfers associated with this multiapp.
Definition MultiApp.h:662
MPI_Comm & _my_comm
The MPI communicator this object is going to use.
Definition MultiApp.h:571
bool hasLocalApp(unsigned int global_app) const
Whether or not the given global app number is on this processor.
Definition MultiApp.C:1102
virtual void preRunInputFile()
call back executed right before app->runInputFile()
Definition MultiApp.C:1527
const PerfID _restore_timer
Definition MultiApp.h:674
void possiblyCreateChildApplications()
Called just after construction to allow derived classes to set _positions and create sub-apps accordi...
Definition MultiApp.C:390
unsigned int _first_local_app
The number of the first app on this processor.
Definition MultiApp.h:562
Point _bounding_box_padding
Additional padding added to the bounding box, useful for 1D meshes.
Definition MultiApp.h:598
std::vector< const Positions * > _positions_objs
The positions of all of the apps, using the Positions system.
Definition MultiApp.h:531
const Point & position(unsigned int app) const
The physical position of a global App number.
Definition MultiApp.C:1570
bool _has_an_app
Whether or not this processor as an App at all
Definition MultiApp.h:634
processor_id_type _max_procs_per_app
Maximum number of processors to give to each app.
Definition MultiApp.h:601
bool _move_happened
Whether or not the move has happened.
Definition MultiApp.h:631
void createApps()
Create the provided number of apps.
Definition MultiApp.C:412
bool _keep_aux_solution_during_restore
Flag indicates if or not restart the auxiliary system from the latest auxiliary solution.
Definition MultiApp.h:646
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...
Definition MultiApp.h:653
std::vector< unsigned int > _move_apps
The apps to be moved.
Definition MultiApp.h:625
int _orig_rank
The mpi "rank" of this processor in the original communicator.
Definition MultiApp.h:577
FEProblem & appProblem(unsigned int app)
Get the FEProblem for the global app is part of.
Definition MultiApp.C:1059
virtual void backup()
Save off the state of every Sub App.
Definition MultiApp.C:791
const bool _use_positions
Toggle use of "positions".
Definition MultiApp.h:537
void readCommandLineArguments()
Fill command line arguments for sub apps.
Definition MultiApp.C:473
bool _keep_solution_during_restore
Flag indicates if or not restart from the latest solution.
Definition MultiApp.h:643
static InputParameters validParams()
Definition MultiApp.C:51
Real appPostprocessorValue(unsigned int app, const std::string &name)
Get a Postprocessor value for a specified global app.
Definition MultiApp.C:1081
void addAssociatedTransfer(MultiAppTransfer &transfer)
Add a transfer that is associated with this multiapp.
Definition MultiApp.C:1532
const MPI_Comm & _orig_comm
The original comm handle.
Definition MultiApp.h:565
FEProblemBase & _fe_problem
The FEProblemBase this MultiApp is part of.
Definition MultiApp.h:523
unsigned int _total_num_apps
The total number of apps to simulate.
Definition MultiApp.h:556
unsigned int globalAppToLocal(unsigned int global_app)
Map a global App number to the local number.
Definition MultiApp.C:1508
SubAppBackups & _sub_app_backups
The cached subapp backups (passed from the parent app)
Definition MultiApp.h:668
const bool _create_child_apps_on_initial_setup
Whether we create child apps during the initialSetup() call or immediately after the multiapps constr...
Definition MultiApp.h:541
std::vector< std::shared_ptr< MooseApp > > _apps
Pointers to each of the Apps.
Definition MultiApp.h:586
std::vector< bool > _reset_happened
Whether or not apps have been reset at each time.
Definition MultiApp.h:619
MooseApp * localApp(unsigned int local_app)
Get the local MooseApp object.
Definition MultiApp.C:1112
void setAppOutputFileBase()
Sets all the app's output file bases.
Definition MultiApp.C:1538
virtual std::vector< std::string > getCommandLineArgs(const unsigned int local_app)
Definition MultiApp.C:1335
const UserObject & appUserObjectBase(unsigned int app, const std::string &name)
Get a UserObject base for a specific global app.
Definition MultiApp.C:1072
LocalRankConfig _rank_config
The app configuration resulting from calling init.
Definition MultiApp.h:659
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...
Definition MultiApp.h:656
virtual bool propagateRecoverToSubApps() const
Whether or not to propagate the parent's recover state (the –recover and –test-checkpoint-half-transi...
Definition MultiApp.h:454
std::string _node_name
Node Name.
Definition MultiApp.h:580
virtual void fillPositions()
must fill in _positions with the positions of the sub-aps
Definition MultiApp.C:571
unsigned int _my_num_apps
The number of apps this object is involved in simulating.
Definition MultiApp.h:559
virtual Executioner * getExecutioner(unsigned int app)
Definition MultiApp.C:757
const PerfID _reset_timer
Definition MultiApp.h:675
const std::vector< CLIArgString > & _cli_args
CommandLine arguments (controllable!)
Definition MultiApp.h:637
std::vector< FileName > _input_files
The input file for each app's simulation.
Definition MultiApp.h:544
virtual void createLocalApp(const unsigned int i)
Create the i-th local app.
Definition MultiApp.C:456
std::vector< Point > _move_positions
The new positions for the apps to be moved.
Definition MultiApp.h:628
std::vector< Point > _positions
The positions of all of the apps, using input constant vectors (to be deprecated)
Definition MultiApp.h:529
virtual libMesh::NumericVector< libMesh::Number > & appTransferVector(unsigned int app, std::string var_name)
Get the vector to transfer to for this MultiApp.
Definition MultiApp.C:1090
virtual void parentOutputPositionChanged()
For apps outputting in position we need to change their output positions if their parent app moves.
Definition MultiApp.C:1159
const bool _run_in_position
Whether to run the child apps with their meshes transformed with the coordinate transforms.
Definition MultiApp.h:665
static void transformBoundingBox(libMesh::BoundingBox &box, const MultiAppCoordTransform &transform)
Transform a bounding box according to the transformations in the provided coordinate transformation o...
Definition MultiApp.C:934
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...
Definition MultiApp.C:974
std::vector< unsigned int > _reset_apps
The apps to be reset.
Definition MultiApp.h:616
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...
Definition Positions.C:116
A class for creating restricted objects.
Definition Restartable.h:29
static InputParameters validParams()
void mooseWarning(Args &&... args) const
void mooseDeprecated(Args &&... args) const
Helper class for holding Sub-app backups.
Definition MultiApp.h:125
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
NumericVector< Number > & solution()
Definition SystemBase.h:212
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.
Definition UserObject.h:20
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
MeshBase & mesh
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)
Definition MooseUtils.C:317
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:175
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
@ COORD_RZ
Definition MooseTypes.h:866
libMesh::BoundingBox create_bounding_box(const MeshBase &mesh)
const unsigned int invalid_uint
Holds app partitioning information relevant to the a particular rank for a multiapp scenario.
Definition MultiApp.h:47
bool is_first_local_rank
This is true if this rank is the primary/zero rank for a (sub)app slot.
Definition MultiApp.h:71
dof_id_type num_local_apps
The number of (sub)apps that should/will be run locally on this rank.
Definition MultiApp.h:58
dof_id_type first_local_app_index
The (global) index of the first local app for this rank.
Definition MultiApp.h:64