23#include "libmesh/mesh_tools.h"
24#include "libmesh/numeric_vector.h"
33 params.
addClassDescription(
"MultiApp for performing coupled simulations with the parent and "
34 "sub-application both progressing in time.");
38 "Set to true to allow this MultiApp to take smaller "
39 "timesteps than the rest of the simulation. More "
40 "than one timestep will be performed for each "
41 "parent application timestep");
43 params.
addParam<
bool>(
"interpolate_transfers",
45 "Only valid when sub_cycling. This allows "
46 "transferred values to be interpolated "
47 "over the time frame the MultiApp is "
48 "executing over when sub_cycling");
50 params.
addParam<
bool>(
"detect_steady_state",
52 "If true, then if/while sub-cycling ('sub_cycling = true'), a steady-state "
53 "check will be performed for each child app, allowing them to skip to the "
54 "end of the parent time step if steady conditions are detected.");
56 params.
addParam<
bool>(
"output_sub_cycles",
false,
"If true then every sub-cycle will be output.");
58 "print_sub_cycles",
true,
"Toggle the display of sub-cycles on the screen.");
61 "max_failures", 0,
"Maximum number of solve failures tolerated while sub_cycling.");
64 "output_sub_cycles print_sub_cycles max_failures",
67 params.
addParam<
bool>(
"tolerate_failure",
69 "If true this MultiApp won't participate in dt "
70 "decisions and will always be fast-forwarded to "
76 "If true this will allow failed solves to attempt to 'catch up' using smaller timesteps.");
78 params.
addParam<Real>(
"max_catch_up_steps",
80 "Maximum number of steps to allow an app to take "
81 "when trying to catch back up after a failed "
92 _sub_cycling(getParam<bool>(
"sub_cycling")),
93 _interpolate_transfers(getParam<bool>(
"interpolate_transfers")),
94 _detect_steady_state(getParam<bool>(
"detect_steady_state")),
95 _output_sub_cycles(getParam<bool>(
"output_sub_cycles")),
96 _max_failures(getParam<unsigned
int>(
"max_failures")),
97 _tolerate_failure(getParam<bool>(
"tolerate_failure")),
99 _catch_up(getParam<bool>(
"catch_up")),
100 _max_catch_up_steps(getParam<Real>(
"max_catch_up_steps")),
101 _first(declareRecoverableData<bool>(
"first", true)),
102 _auto_advance(false),
103 _print_sub_cycles(getParam<bool>(
"print_sub_cycles"))
110 " is set to interpolate_transfers but is not sub_cycling! That is not valid!");
117 " \"sub_cycling\" and \"catch_up\" cannot both be set to true simultaneously.");
123 " it doesn't make any sense to keep a solution during restore when doing "
124 "sub_cycling. Consider trying \"catch_up\" steps instead");
130 " \"keep_solution_during_restore\" requires \"catch_up = true\". Either disable "
131 "\"keep_solution_during_restart\" or set \"catch_up = true\"");
137 " both \"sub_cycling\" and \"tolerate_failure\" are set to true. \"tolerate_failure\""
138 " will be ignored.");
141NumericVector<Number> &
184 _console << COLOR_CYAN <<
"Solving MultiApp '" <<
name() <<
"' with target time " << target_time
185 <<
" and dt " << dt <<
" with auto-advance " << (auto_advance ?
"on" :
"off")
186 << COLOR_DEFAULT << std::endl;
192 bool return_value =
true;
200 mooseCheckMPIErr(ierr);
209 Real app_time_offset =
_apps[i]->getGlobalTimeOffset();
223 "The target time (time a multiapp must reach at the end of the time step) "
224 "is desynchronized between this app and subapp ",
226 ".\n If this is desired: use the 'global_time_offset' multiapp parameter to "
227 "declare a constant offset\n"
228 "If the apps should (eventually) be synchronized in time, please either: \n"
229 " - match the 'start_time' in the main app and the multiapp, in the Executioner "
231 " - set 'sub_cycling' to true in the multiapp parameters\n"
232 "This message will only print once for all apps and all time steps."));
237 Real time_old = ex->
getTime() + app_time_offset;
242 System & libmesh_aux_system = aux_system.
system();
244 NumericVector<Number> & solution = *libmesh_aux_system.
solution;
245 NumericVector<Number> & transfer_old = libmesh_aux_system.get_vector(
"transfer_old");
250 transfer_old = solution;
252 transfer_old.close();
270 bool at_steady =
false;
282 bool local_first =
_first;
285 while ((!at_steady && ex->
getTime() + app_time_offset + ex->
timestepTol() < target_time) ||
288 if (local_first !=
true)
299 Real future_time = ex->
getTime() + app_time_offset + ex->
getDT();
302 Real step_percent = (future_time - time_old) / (target_time - time_old);
304 Real one_minus_step_percent = 1.0 - step_percent;
309 System & libmesh_aux_system = aux_system.
system();
311 NumericVector<Number> & solution = *libmesh_aux_system.
solution;
312 NumericVector<Number> & transfer = libmesh_aux_system.get_vector(
"transfer");
313 NumericVector<Number> & transfer_old = libmesh_aux_system.get_vector(
"transfer_old");
317 transfer_old.close();
322 (transfer_old(dof) * one_minus_step_percent) +
323 (transfer(dof) * step_percent));
345 std::stringstream oss;
356 _console <<
"Detected Steady State! Fast-forwarding to " << target_time << std::endl;
363 ex->
endStep(target_time - app_time_offset);
384 ex->
endStep(target_time - app_time_offset);
417 _console <<
"Starting time step catch up!" << std::endl;
419 bool caught_up =
false;
421 unsigned int catch_up_step = 0;
424 Real catch_up_dt = dt / 2;
425 Real catch_up_time = 0;
430 _console <<
"Solving " <<
name() <<
" catch up step " << catch_up_step
435 if (catch_up_time + catch_up_dt > dt)
436 catch_up_dt = dt - catch_up_time;
444 catch_up_time += catch_up_dt;
445 if (std::abs(catch_up_time - dt) <
475 _console <<
"Starting Catch Up!" << std::endl;
477 bool caught_up =
false;
479 unsigned int catch_up_step = 0;
481 Real catch_up_dt = dt / 2;
487 _console <<
"Solving " <<
name() <<
" catch up step " << catch_up_step
500 if (current_time + app_time_offset +
534 _console <<
"Successfully Solved MultiApp " <<
name() <<
"." << std::endl;
539 _console <<
"Failed to Solve MultiApp " <<
name() <<
", attempting to recover." << std::endl;
540 return_value =
false;
558 Real app_time_offset =
_apps[i]->getGlobalTimeOffset();
562 if (
_apps[i]->getStartTime() + app_time_offset < target_time)
578 if (recurse_through_multiapp_levels)
593 return std::numeric_limits<Real>::max();
595 Real smallest_dt = std::numeric_limits<Real>::max();
605 Real dt = ex->
getDT();
607 smallest_dt = std::min(dt, smallest_dt);
614 return std::numeric_limits<Real>::max();
622 unsigned int global_app,
650 auto & app =
_apps[i];
653 mooseError(
"MultiApp ",
name(),
" is not using a Transient Executioner!");
666 System & libmesh_aux_system = aux_system.
system();
669 libmesh_aux_system.
add_vector(
"transfer_old",
false);
672 libmesh_aux_system.
add_vector(
"transfer",
false);
675 if (app->hasInitialBackupMesh())
677 app->restoreMeshFromInitialBackup(problem.
mesh());
const ExecFlagType EXEC_FORCED
const ExecFlagType EXEC_TIMESTEP_END
const ExecFlagType EXEC_TIMESTEP_BEGIN
registerMooseObject("MooseApp", TransientMultiApp)
void ErrorVector unsigned int
Grab all the (possibly semi)local dof indices for the variables passed in, in the system passed in.
const std::set< dof_id_type > & getDofIndices() const
A system that holds auxiliary variables.
virtual libMesh::System & system() override
Get the reference to the libMesh system.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
An output object for writing to the console (screen)
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()
virtual void advanceState()
Advance all of the state holding vectors / datastructures so that we can move to the next timestep.
void forceOutput()
Indicates that the next call to outputStep should be forced.
virtual MooseMesh & mesh() override
void finishMultiAppStep(ExecFlagType type, bool recurse_through_multiapp_levels=false)
Finish the MultiApp time step (endStep, postStep) associated with the ExecFlagType.
void allowOutput(bool state)
Ability to enable/disable all output calls.
virtual int & timeStep() const
virtual void meshChanged(bool intermediate_change, bool contract_mesh, bool clean_refinement_flags)
Update data after a mesh change.
virtual void outputStep(ExecFlagType type)
Output the current step.
bool isRestarting() const
Whether or not this is a "restart" calculation.
Real getGlobalTimeOffset() const
Each App has it's own local time.
bool isRecovering() const
Whether or not this is a "recover" calculation.
const std::map< std::string, unsigned int > & getOutputFileNumbers() const
Store a map of outputter names and file numbers The MultiApp system requires this to get the file num...
void paramInfo(const std::string ¶m, Args... args) const
Emits an informational message prefixed with the file and line number of the given param (from the in...
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...
bool prepare(const MeshBase *mesh_to_clone)
Calls prepare_for_use() if the underlying MeshBase object isn't prepared, then communicates various b...
const libMesh::ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems,...
MooseApp & _app
The MOOSE application this is associated with.
Utility class for catching solve failure errors so that MOOSE can recover state before continuing.
A MultiApp represents one or more MOOSE applications that are running simultaneously.
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.
virtual void initialSetup() override
Method to be called in main-app initial setup for create sub-apps if using positions is false.
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.
unsigned int _first_local_app
The number of the first app on this processor.
bool _has_an_app
Whether or not this processor as an App at all
const PerfID _solve_step_timer
Timers.
bool _keep_solution_during_restore
Flag indicates if or not restart from the latest solution.
static InputParameters validParams()
FEProblemBase & _fe_problem
The FEProblemBase this MultiApp is part of.
unsigned int globalAppToLocal(unsigned int global_app)
Map a global App number to the local number.
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.
unsigned int _my_num_apps
The number of apps this object is involved in simulating.
void mooseWarning(Args &&... args) const
NumericVector< Number > & solution()
void min(const T &r, T &o, Request &req) const
Base class for transient executioners that use a FixedPointSolve solve object for multiapp-main app i...
virtual void incrementStepOrReject()
This is where the solve step is actually incremented.
virtual void takeStep(Real input_dt=-1.0)
Do whatever is necessary to advance one step.
virtual Real getTime() const
Get the current time.
virtual bool lastSolveConverged() const override
Whether or not the last solve converged.
virtual void endStep(Real input_time=-1.0)
bool convergedToSteadyState() const
Determines whether the problem has converged to steady state.
virtual void preExecute() override
Override this for actions that should take place before execution.
Real & timestepTol()
Get the timestep tolerance.
Real & endTime()
Get a modifiable reference to the end time.
virtual void init() override
Initialize the executioner.
virtual void setTargetTime(Real target_time)
Can be used to set the next "target time" which is a time to nail perfectly.
static InputParameters validParams()
MultiApp Implementation for Transient Apps.
bool _detect_steady_state
virtual NumericVector< Number > & appTransferVector(unsigned int app, std::string var_name) override
Get the vector to transfer to for this MultiApp.
TransientMultiApp(const InputParameters ¶meters)
virtual void finishStep(bool recurse_through_multiapp_levels=false) override
Calls multi-apps executioners' endStep and postStep methods which creates output and advances time (n...
void setupApp(unsigned int i, Real time=0.0)
Setup the executioner for the local app.
virtual void initialSetup() override
Method to be called in main-app initial setup for create sub-apps if using positions is false.
bool _interpolate_transfers
virtual void incrementTStep(Real target_time) override
Advances the multi-apps time step which is important for dt selection.
bool _print_sub_cycles
Flag for toggling console output on sub cycles.
std::set< dof_id_type > _transferred_dofs
The DoFs associated with all of the currently transferred variables.
virtual void resetApp(unsigned int global_app, Real time) override
"Reset" the App corresponding to the global App number passed in.
Real computeDT()
Finds the smallest dt from among any of the apps.
virtual bool solveStep(Real dt, Real target_time, bool auto_advance=true) override
Re-solve all of the Apps.
unsigned int _max_failures
bool & _first
Is it our first time through the execution loop?
std::vector< std::string > _transferred_vars
The variables that have been transferred to. Used when doing transfer interpolation....
static InputParameters validParams()
std::vector< TransientBase * > _transient_executioners
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
const Parallel::Communicator & _communicator
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
std::unique_ptr< NumericVector< Number > > solution
const NumericVector< Number > & get_vector(std::string_view vec_name) const
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())