# Time Integration

AMReX provides a basic explicit time integrator capable of Forward Euler or
both predefined and custom Runge-Kutta schemes designed to advance data on a
particular AMR level by a timestep. This integrator is designed to be flexible,
requiring the user to supply a right-hand side function taking a `MultiFab`

of state data and filling a `MultiFab`

of the corresponding right hand side
data. The user simply needs to supply a C++ lambda function to implement
whatever right hand side operations they need.

## A Simple Time Integrator Setup

This is best shown with some sample code that sets up a time integrator and
asks it to step forward by some interval `dt`

. The user needs to supply the
right-hand side function using the `TimeIntegrator::set_rhs()`

function.

```
#include <AMReX_TimeIntegrator.H>
MultiFab Sold; // MultiFab containing old-time state data
MultiFab Snew; // MultiFab where we want new-time state data
// [Fill Sold here]
// Create a time integrator that will work with
// MultiFabs with the same BoxArray, DistributionMapping,
// and number of components as the state_data MultiFab.
TimeIntegrator<MultiFab> integrator(Sold);
// Create a function that fills the state BCs and computes the RHS
auto rhs_fun = [&](MultiFab& rhs, MultiFab& state, const Real time){
// [Calculate the rhs MultiFab given the state MultiFab]
};
// Attach the right hand side function to the integrator
integrator.set_rhs(source_fun);
// integrate forward one step from `time` by `dt` to fill Snew
integrator.advance(Sold, Snew, time, dt);
```

## Picking A Time Integration Method

The user can customize which integration method they wish to use with a set of runtime parameters that allow choosing between a simple Forward Euler method or a generic explicit Runge-Kutta method. If Runge-Kutta is selected, then the user can choose which of a set of predefined Butcher Tables to use, or can choose to use a custom table and supply it manually.

The full set of integrator options are detailed as follows:

```
# INTEGRATION
## *** Selecting the integrator backend ***
## integration.type can take on the following string or int values:
## (without the quotation marks)
## "ForwardEuler" or "0" = Native Forward Euler Integrator
## "RungeKutta" or "1" = Native Explicit Runge Kutta
## "SUNDIALS" or "2" = SUNDIALS Integrator
## for example:
integration.type = RungeKutta
## *** Parameters Needed For Native Explicit Runge-Kutta ***
#
## integration.rk.type can take the following values:
### 0 = User-specified Butcher Tableau
### 1 = Forward Euler
### 2 = Trapezoid Method
### 3 = SSPRK3 Method
### 4 = RK4 Method
integration.rk.type = 3
## If using a user-specified Butcher Tableau, then
## set nodes, weights, and table entries here:
#
## The Butcher Tableau is read as a flattened,
## lower triangular matrix (but including the diagonal)
## in row major format.
integration.rk.weights = 1
integration.rk.nodes = 0
integration.rk.tableau = 0.0
```

## Using SUNDIALS

The AMReX Time Integration interface also supports a SUNDIALS backend that
provides explicit, implicit, and implicit-explicit (ImEx) Runge-Kutta methods
as well a multirate (MRI) methods from the ARKODE package in SUNDIALS.
To use SUNDIALS integrators, the user needs to compile AMReX with
`USE_SUNDIALS=TRUE`

and use SUNDIALS v6.0 or later.

The SUNDIALS interface supports `MultiFab`

or `Vector<MultiFab>`

data
types. Using a `Vector<MultiFab>`

permits integrating state data with
different spatial centering (e.g. cell centered, face centered, node centered)
concurrently.

The same code as above can be used with SUNDIALS explicit or implicit Runge-Kutta methods without any modification. To select a SUNDIALS explicit Runge-Kutta integrator, one needs only to add the following two input parameters at runtime:

```
integration.type = SUNDIALS
integration.sundials.type = ERK
```

One can select a different method type by changing the value of
`integration.sundials.type`

to one of the following values:

Input Option |
SUNDIALS Method Type |
---|---|

ERK |
Explicit Runge-Kutta method |

DIRK |
Diagonally Implicit Runge-Kutta method |

IMEX-RK |
Implicit-Explicit Additive Runge-Kutta method |

EX-MRI |
Explicit Multirate Infinitesimal method |

IM-MRI |
Implicit Multirate Infinitesimal method |

IMEX-MRI |
Implicit-Explicit Multirate Infinitesimal method |

For ImEx methods, the user needs to supply two right-hand side functions, an
implicit and an explicit function, using the function
`TimeIntegrator::set_imex_rhs()`

. Similarly for multirate methods, the user
needs to supply slow and fast right-hand side functions using
`TimeIntegrator::set_rhs()`

to set the slow function and
`TimeIntegrator::set_fast_rhs()`

to set the fast function. With multirate
methods, one also needs to select the fast time scale method type using the
input option `integration.sundials.fast_type`

which maybe set to `ERK`

or
`DIRK`

.

To select a specific SUNDIALS method use the input option
`integration.sundials.method`

for ERK and DIRK methods as well as the slow
time scale method with an MRI integrator, use `integration.sundials.method_i`

and `integration.sundials.method_e`

to set the implicit and explicit method in
an ImEx method, and `integration.sundials.fast_method`

to set the ERK or DIRK
method used at the fast time scale with an MRI integrator. These options may be
set to any valid SUNDIALS method name, see the following sections in the
SUNDIALS documentation for more details:

The full set of integrator options are detailed as follows:

```
# INTEGRATION WITH SUNDIALS
# *** Select the SUNDIALS integrator backend ***
integration.type = SUNDIALS
# *** Select the SUNDIALS method type ***
# ERK = Explicit Runge-Kutta method
# DIRK = Diagonally Implicit Runge-Kutta method
# IMEX-RK = Implicit-Explicit Additive Runge-Kutta method
# EX-MRI = Explicit Multirate Infatesimal method
# IM-MRI = Implicit Multirate Infatesimal method
# IMEX-MRI = Implicit-Explicit Multirate Infatesimal method
integration.sundials.type = ERK
# *** Select a specific SUNDIALS ERK method ***
integration.sundials.method = ARKODE_BOGACKI_SHAMPINE_4_2_3
# *** Select a specific SUNDIALS ImEx method ***
integration.sundials.method_i = ARKODE_ARK2_DIRK_3_1_2
integration.sundials.method_e = ARKODE_ARK2_ERK_3_1_2
# *** Select a specific SUNDIALS MRI method ***
integration.sundials.method = ARKODE_MIS_KW3
integration.sundials.fast_method = ARKODE_KNOTH_WOLKE_3_3
```

The features of this interface evolve with the needs of our codes, so they may not yet support all SUNDIALS configurations available. If you find you need SUNDIALS options we have not implemented, please let us know.