# ODESolvers

`ClimateMachine.ODESolvers`

— Module`ODESolvers`

Ordinary differential equation solvers

## Low Storage Runge Kutta methods

`ClimateMachine.ODESolvers.LowStorageRungeKutta2N`

— Type`LowStorageRungeKutta2N(f, RKA, RKB, RKC, Q; dt, t0 = 0)`

This is a time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

with the required time step size `dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

The constructor builds a low-storage Runge-Kutta scheme using 2N storage based on the provided `RKA`

, `RKB`

and `RKC`

coefficient arrays.

The available concrete implementations are:

`ClimateMachine.ODESolvers.LSRK54CarpenterKennedy`

— Function`LSRK54CarpenterKennedy(f, Q; dt, t0 = 0)`

This function returns a `LowStorageRungeKutta2N`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

with the required time step size `dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the fourth-order, low-storage, Runge–Kutta scheme of Carpenter and Kennedy (1994) (in their notation (5,4) 2N-Storage RK scheme).

**References**

```
@TECHREPORT{CarpenterKennedy1994,
author = {M.~H. Carpenter and C.~A. Kennedy},
title = {Fourth-order {2N-storage} {Runge-Kutta} schemes},
institution = {National Aeronautics and Space Administration},
year = {1994},
number = {NASA TM-109112},
address = {Langley Research Center, Hampton, VA},
}
```

`ClimateMachine.ODESolvers.LSRK144NiegemannDiehlBusch`

— Function`LSRK144NiegemannDiehlBusch((f, Q; dt, t0 = 0)`

This function returns a `LowStorageRungeKutta2N`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

with the required time step size `dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the fourth-order, 14-stage, low-storage, Runge–Kutta scheme of Niegemann, Diehl, and Busch (2012) with optimized stability region

**References**

## Low Storage (3N) Runge Kutta methods

`ClimateMachine.ODESolvers.LowStorageRungeKutta3N`

— Type`LowStorageRungeKutta3N(f, RKA, RKB, RKC, RKW, Q; dt, t0 = 0)`

This is a time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

The constructor builds a low-storage Runge–Kutta scheme using 3N storage based on the provided `RKA`

, `RKB`

and `RKC`

coefficient arrays. `RKC`

(vector of length the number of stages `ns`

) set nodal points position; `RKA`

and `RKB`

(size: ns x 2) set weight for tendency and stage-state; `RKW`

(unused) provides RK weight (last row in Butcher's tableau).

The 3-N storage formulation from Fyfe (1966) is applicable to any 4-stage, fourth-order RK scheme. It is implemented here as:

\[\hspace{-20mm} for ~~ j ~~ in ~ [1:ns]: \hspace{10mm} t_j = t^n + \Delta t ~ rkC_j\]

\[ dQ_j = dQ^*_j + f(Q_j,t_j)\]

\[ Q_{j+1} = Q_{j} + \Delta t \{ rkB_{j,1} ~ dQ_j + rkB_{j,2} ~ dR_j \}\]

\[ dR_{j+1} = dR_j + rkA_{j+1,2} ~ dQ_j\]

\[ dQ^*_{j+1} = rkA_{j+1,1} ~ dQ_j\]

The available concrete implementations are:

**References**

```
@article{Fyfe1966,
title = {Economical Evaluation of Runge-Kutta Formulae},
author = {Fyfe, David J.},
journal = {Mathematics of Computation},
volume = {20},
pages = {392--398},
year = {1966}
}
```

`ClimateMachine.ODESolvers.LS3NRK44Classic`

— Function`LS3NRK44Classic(f, Q; dt, t0 = 0)`

This function returns a `LowStorageRungeKutta3N`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the classic 4-stage, fourth-order Runge–Kutta scheme in the low-storage implementation of Blum (1962)

**References**

```
@article {Blum1962,
title = {A Modification of the Runge-Kutta Fourth-Order Method}
author = {Blum, E. K.},
journal = {Mathematics of Computation},
volume = {16},
pages = {176-187},
year = {1962}
}
```

`ClimateMachine.ODESolvers.LS3NRK33Heuns`

— Function`LS3NRK33Heuns(f, Q; dt, t0 = 0)`

This function returns a `LowStorageRungeKutta3N`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This method uses the 3-stage, third-order Heun's Runge–Kutta scheme.

**References**

```
@article {Heun1900,
title = {Neue Methoden zur approximativen Integration der
Differentialgleichungen einer unabh"{a}ngigen Ver"{a}nderlichen}
author = {Heun, Karl},
journal = {Z. Math. Phys},
volume = {45},
pages = {23--38},
year = {1900}
}
```

## Strong Stability Preserving RungeKutta methods

`ClimateMachine.ODESolvers.StrongStabilityPreservingRungeKutta`

— Type`StrongStabilityPreservingRungeKutta(f, RKA, RKB, RKC, Q; dt, t0 = 0)`

This is a time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

The constructor builds a strong-stability-preserving Runge–Kutta scheme based on the provided `RKA`

, `RKB`

and `RKC`

coefficient arrays.

The available concrete implementations are:

`ClimateMachine.ODESolvers.SSPRK33ShuOsher`

— Function`SSPRK33ShuOsher(f, Q; dt, t0 = 0)`

This function returns a `StrongStabilityPreservingRungeKutta`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the third-order, 3-stage, strong-stability-preserving, Runge–Kutta scheme of Shu and Osher (1988)

**References**

`ClimateMachine.ODESolvers.SSPRK34SpiteriRuuth`

— Function`SSPRK34SpiteriRuuth(f, Q; dt, t0 = 0)`

This function returns a `StrongStabilityPreservingRungeKutta`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the third-order, 4-stage, strong-stability-preserving, Runge–Kutta scheme of Spiteri and Ruuth (1988)

**References**

## Additive Runge Kutta methods

`ClimateMachine.ODESolvers.AdditiveRungeKutta`

— Type```
AdditiveRungeKutta(f, l, backward_euler_solver, RKAe, RKAi, RKB, RKC, Q;
split_explicit_implicit, variant, dt, t0 = 0)
```

This is a time stepping object for implicit-explicit time stepping of a decomposed differential equation. When `split_explicit_implicit == false`

the equation is assumed to be decomposed as

\[ \dot{Q} = [l(Q, t)] + [f(Q, t) - l(Q, t)]\]

where `Q`

is the state, `f`

is the full tendency and `l`

is the chosen implicit operator. When `split_explicit_implicit == true`

the assumed decomposition is

\[ \dot{Q} = [l(Q, t)] + [f(Q, t)]\]

where `f`

is now only the nonlinear tendency. For both decompositions the implicit operator `l`

is integrated implicitly whereas the remaining part is integrated explicitly. Other arguments are the required time step size `dt`

and the optional initial time `t0`

. The resulting backward Euler type systems are solved using the provided `backward_euler_solver`

. This time stepping object is intended to be passed to the `solve!`

command.

The constructor builds an additive Runge–Kutta scheme based on the provided `RKAe`

, `RKAi`

, `RKB`

and `RKC`

coefficient arrays. Additionally `variant`

specifies which of the analytically equivalent but numerically different formulations of the scheme is used.

The available concrete implementations are:

`ClimateMachine.ODESolvers.ARK1ForwardBackwardEuler`

— Function```
ARK1ForwardBackwardEuler(f, l, backward_euler_solver, Q; dt, t0,
split_explicit_implicit, variant)
```

This function returns an `AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

This uses a first-order-accurate two-stage additive Runge–Kutta scheme by combining a forward Euler explicit step with a backward Euler implicit correction.

**References**

```
@article{Ascher1997,
title = {Implicit-explicit Runge-Kutta methods for time-dependent
partial differential equations},
author = {Uri M. Ascher and Steven J. Ruuth and Raymond J. Spiteri},
volume = {25},
number = {2-3},
pages = {151--167},
year = {1997},
journal = {Applied Numerical Mathematics},
publisher = {Elsevier {BV}}
}
```

`ClimateMachine.ODESolvers.ARK2ImplicitExplicitMidpoint`

— Function```
ARK2ImplicitExplicitMidpoint(f, l, backward_euler_solver, Q; dt, t0,
split_explicit_implicit, variant)
```

This function returns an `AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

This uses a second-order-accurate two-stage additive Runge–Kutta scheme by combining the implicit and explicit midpoint methods.

**References**

```
@article{Ascher1997,
title = {Implicit-explicit Runge-Kutta methods for time-dependent
partial differential equations},
author = {Uri M. Ascher and Steven J. Ruuth and Raymond J. Spiteri},
volume = {25},
number = {2-3},
pages = {151--167},
year = {1997},
journal = {Applied Numerical Mathematics},
publisher = {Elsevier {BV}}
}
```

`ClimateMachine.ODESolvers.ARK2GiraldoKellyConstantinescu`

— Function```
ARK2GiraldoKellyConstantinescu(f, l, backward_euler_solver, Q; dt, t0,
split_explicit_implicit, variant, paperversion)
```

This function returns an `AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

`paperversion=true`

uses the coefficients from the paper, `paperversion=false`

uses coefficients that make the scheme (much) more stable but less accurate

This uses the second-order-accurate 3-stage additive Runge–Kutta scheme of Giraldo, Kelly and Constantinescu (2013).

**References**

`ClimateMachine.ODESolvers.ARK548L2SA2KennedyCarpenter`

— Function```
ARK548L2SA2KennedyCarpenter(f, l, backward_euler_solver, Q; dt, t0,
split_explicit_implicit, variant)
```

`AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

This uses the fifth-order-accurate 8-stage additive Runge–Kutta scheme of Kennedy and Carpenter (2013).

**References**

`ClimateMachine.ODESolvers.ARK437L2SA1KennedyCarpenter`

— Function```
ARK437L2SA1KennedyCarpenter(f, l, backward_euler_solver, Q; dt, t0,
split_explicit_implicit, variant)
```

`AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

This uses the fourth-order-accurate 7-stage additive Runge–Kutta scheme of Kennedy and Carpenter (2013).

**References**

`ClimateMachine.ODESolvers.Trap2LockWoodWeller`

— Function```
Trap2LockWoodWeller(F, L, backward_euler_solver, Q; dt, t0, nsubsteps,
split_explicit_implicit, variant)
```

`AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

The time integrator scheme used is Trap2(2,3,2) with δ*s = 1, δ*f = 0, from the following reference

**References**

```
@article{Ascher1997,
title = {Numerical analyses of Runge–Kutta implicit–explicit schemes
for horizontally explicit, vertically implicit solutions of
atmospheric models},
author = {S.-J. Lock and N. Wood and H. Weller},
volume = {140},
number = {682},
pages = {1654-1669},
year = {2014},
journal = {Quarterly Journal of the Royal Meteorological Society},
publisher = {{RMetS}}
}
```

`ClimateMachine.ODESolvers.DBM453VoglEtAl`

— Function```
DBM453VoglEtAl(f, l, backward_euler_solver, Q; dt, t0,
split_explicit_implicit, variant)
```

`AdditiveRungeKutta`

time stepping object, see the documentation of `AdditiveRungeKutta`

for arguments definitions. This time stepping object is intended to be passed to the `solve!`

command.

This uses the third-order-accurate 5-stage additive Runge–Kutta scheme of Vogl et al. (2019).

**References**

`ClimateMachine.ODESolvers.SSPRK22Ralstons`

— Function`SSPRK22Ralstons(f, Q; dt, t0 = 0)`

This function returns a `StrongStabilityPreservingRungeKutta`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the second-order, 2-stage, strong-stability-preserving, Runge–Kutta scheme of Shu and Osher (1988) (also known as Ralstons's method.) Exact choice of coefficients from wikipedia page for Heun's method :)

**References**

`ClimateMachine.ODESolvers.SSPRK22Heuns`

— Function`SSPRK22Heuns(f, Q; dt, t0 = 0)`

`StrongStabilityPreservingRungeKutta`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This uses the second-order, 2-stage, strong-stability-preserving, Runge–Kutta scheme of Shu and Osher (1988) (also known as Heun's method.) Exact choice of coefficients from wikipedia page for Heun's method :)

**References**

`ClimateMachine.ODESolvers.LSRKEulerMethod`

— Function`LSRKEulerMethod(f, Q; dt, t0 = 0)`

This function returns a `LowStorageRungeKutta2N`

time stepping object for explicitly time stepping the differential equation given by the right-hand-side function `f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This method uses the LSRK2N framework to implement a simple Eulerian forward time stepping scheme for the use of debugging.

**References**

## Multi-rate Runge Kutta Methods

`ClimateMachine.ODESolvers.MultirateRungeKutta`

— Type`MultirateRungeKutta(slow_solver, fast_solver; dt, t0 = 0)`

`f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f_fast(Q, t) + f_slow(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

The constructor builds a multirate Runge-Kutta scheme using two different RK solvers. This is based on

Currently only the low storage RK methods can be used as slow solvers

**References**

## Multi-rate Infinitesimal Step Methods

`ClimateMachine.ODESolvers.TimeScaledRHS`

— Type`TimeScaledRHS(a, b, rhs!)`

When evaluate at time `t`

, evaluates `rhs!`

at time `a + bt`

.

`ClimateMachine.ODESolvers.MultirateInfinitesimalStep`

— Type```
MultirateInfinitesimalStep(slowrhs!, fastrhs!, fastmethod,
α, β, γ,
Q::AT; dt=0, t0=0) where {AT<:AbstractArray}
```

This is a time stepping object for explicitly time stepping the partitioned differential equation given by right-hand-side functions `f_fast`

and `f_slow`

with the state `Q`

, i.e.,

\[ \dot{Q} = f_{fast}(Q, t) + f_{slow}(Q, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

The constructor builds a multirate infinitesimal step Runge-Kutta scheme based on the provided `α`

, `β`

and `γ`

tableaux and `fastmethod`

for solving the fast modes.

The available concrete implementations are:

**References**

`ClimateMachine.ODESolvers.MISRK1`

— Function`MISRK1(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MISRK1`

method is a 1st-order accurate MIS method based on the RK1 (explicit Euler) method.

**References**

`ClimateMachine.ODESolvers.MIS2`

— Function`MIS2(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MIS2`

method is a 2nd-order accurate, 3-stage MIS method whose construction is summarized in Table 1 of Oswald Knoth , Joerg Wensch (2014).

**References**

`ClimateMachine.ODESolvers.MISRK2a`

— Function`MISRK2a(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MISRK2a`

method is a 2nd-order accurate, 2-stage MIS method based on the approach detailed by Wicker and Skamarock in Louis J. Wicker , William C. Skamarock (2002).

**References**

`ClimateMachine.ODESolvers.MISRK2b`

— Function`MISRK2b(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MISRK2b`

method is a 2nd-order accurate, 2-stage MIS method and a variant of the `MISRK2a`

method based on the approach detailed by Wicker and Skamarock in Louis J. Wicker , William C. Skamarock (2002).

**References**

`ClimateMachine.ODESolvers.MIS3C`

— Function`MIS3C(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MIS3C`

method is a 3rd-order accurate, 3-stage MIS method whose construction is summarized in Table 2 of Oswald Knoth , Joerg Wensch (2014).

**References**

`ClimateMachine.ODESolvers.MISRK3`

— Function`MISRK3(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MISRK3`

method is a 3rd-order accurate, 3-stage MIS method based on the approach detailed by Wicker and Skamarock in Louis J. Wicker , William C. Skamarock (2002).

**References**

`ClimateMachine.ODESolvers.MIS4`

— Function`MIS4(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MIS4`

method is a 3rd-order accurate, 4-stage MIS method whose construction is summarized in Table 3 of Oswald Knoth , Joerg Wensch (2014).

**References**

`ClimateMachine.ODESolvers.MIS4a`

— Function`MIS4a(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MIS4a`

method is a 3rd-order accurate, 4-stage MIS method whose construction is summarized in Table 4 of Oswald Knoth , Joerg Wensch (2014).

**References**

`ClimateMachine.ODESolvers.MISKWRK43`

— Function`MISKWRK43(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `MISKWRK43`

method is a 3rd-order accurate, 4-stage MIS method. It is the MIS analog of an RK43 method, based on the approach detailed in Oswald Knoth , Ralf Wolke (1998).

**References**

`ClimateMachine.ODESolvers.TVDMISA`

— Function`TVDMISA(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `TVDMISA`

method is a 3rd-order accurate, 3-stage MIS method whose construction is summarized in Table 6 of Oswald Knoth , Joerg Wensch (2014).

**References**

`ClimateMachine.ODESolvers.TVDMISB`

— Function`TVDMISB(slowrhs!, fastrhs!, fastmethod, nsubsteps, Q; dt = 0, t0 = 0)`

The `TVDMISB`

method is a 3rd-order accurate, 3-stage MIS method whose construction is summarized in Table 7 of Oswald Knoth , Joerg Wensch (2014).

**References**

## Split-explicit methods

`ClimateMachine.ODESolvers.SplitExplicitSolver`

— Type`SplitExplicitSolver(slow_solver, fast_solver; dt, t0 = 0, coupled = true)`

`f`

with the state `Q`

, i.e.,

\[ \dot{Q_{fast}} = f_{fast}(Q_{fast}, Q_{slow}, t) \dot{Q_{slow}} = f_{slow}(Q_{slow}, Q_{fast}, t)\]

`dt`

and optional initial time `t0`

. This time stepping object is intended to be passed to the `solve!`

command.

This method performs an operator splitting to timestep the vertical average of the model at a faster rate than the full model. This results in a first- order time stepper.

## GARK methods

`ClimateMachine.ODESolvers.MRIGARKESDIRK46aSandu`

— Function`MRIGARKESDIRK46aSandu(f!, fastsolver, Q; dt, t0=0)`

The 4th order, 6 stage decoupled implicit scheme from Sandu (2019).

`ClimateMachine.ODESolvers.MRIGARKIRK21aSandu`

— Function`MRIGARKIRK21aSandu(f!, fastsolver, Q; dt, t0 = 0)`

The 2rd order, 2 stage implicit scheme from Sandu (2019).

`ClimateMachine.ODESolvers.MRIGARKESDIRK24LSA`

— Function```
MRIGARKESDIRK24LSA(f!,
fastsolver,
Q;
dt,
t0 = 0,
γ = 0.2,
c3 = (2γ + 1) / 2,
a32 = 0.2,
α = -0.1,
β1 = c3 / 10,
β2 = c3 / 10,
)
```

A 2nd order, 4 stage decoupled implicit scheme. It is based on an L-Stable, stiffly-accurate ESDIRK.

`ClimateMachine.ODESolvers.MRIGARKESDIRK34aSandu`

— Function`MRIGARKESDIRK34aSandu(f!, fastsolver, Q; dt, t0=0)`

The 3rd order, 4 stage decoupled implicit scheme from Sandu (2019).

`ClimateMachine.ODESolvers.MRIGARKERK45aSandu`

— Function`MRIGARKERK45aSandu(f!, fastsolver, Q; dt, t0 = 0)`

The 4th order, 5 stage scheme from Sandu (2019).

`ClimateMachine.ODESolvers.MRIGARKExplicit`

— Type`MRIGARKExplicit(f!, fastsolver, Γs, γ̂s, Q, Δt, t0)`

Construct an explicit MultiRate Infinitesimal General-structure Additive Runge–Kutta (MRI-GARK) scheme to solve

\[ \dot{y} = f_{slow}(y, t) + f_{fast}(y, t)\]

where `f_{slow}`

is the slow tendency function and `f_{fast}`

is the fast tendency function; see Sandu (2019).

The fast tendency is integrated using the `fastsolver`

and the slow tendency using the MRI-GARK scheme. Namely, at each stage the scheme solves

\[\begin{aligned} v(T_i) &= Y_i \\ \dot{v} &= f(v, t) + \sum_{j=1}^{i} \bar{γ}_{ij}(t) R_j \\ \bar{γ}_{ijk}(t) &= \sum_{k=0}^{NΓ-1} γ_{ijk} τ(t)^k / Δc_s \\ τ(t) &= (t - t_s) / Δt \\ Y_{i+1} &= v(T_i + c_s * Δt) \end{aligned}\]

where $Y_1 = y_n$ and $y_{n+1} = Y_{Nstages+1}$.

Here $R_j = g(Y_j, t_0 + c_j * Δt)$ is the tendency for stage $j$, $γ_{ijk}$ are the GARK coupling coefficients, $NΓ$ is the number of sets of GARK coupling coefficients there are $Δc_s = \sum_{j=1}^{Nstages} γ_{sj1} = c_{s+1} - c_s$ is the scaling increment between stage times. The ODE for $v(t)$ is solved using the `fastsolver`

. Note that this form of the scheme is based on Definition 2.2 of Sandu (2019), but ODE for $v(t)$ is written to go from $t_s$ to $T_i + c_s * Δt$ as opposed to $0$ to $1$.

Currently only `LowStorageRungeKutta2N`

schemes are supported for `fastsolver`

The coefficients defined by `γ̂s`

can be used for an embedded scheme (only the last stage is different).

The available concrete implementations are:

**References**

`ClimateMachine.ODESolvers.MRIGARKESDIRK23LSA`

— Function`MRIGARKESDIRK23LSA(f!, fastsolver, Q; dt, t0 = 0, δ = 0`

A 2nd order, 3 stage decoupled implicit scheme. It is based on L-Stable, stiffly-accurate ESDIRK scheme of Bank et al (1985); see also Kennedy and Carpenter (2016).

The free parameter `δ`

can take any values for accuracy.

**References**

`ClimateMachine.ODESolvers.MRIGARKERK33aSandu`

— Function`MRIGARKERK33aSandu(f!, fastsolver, Q; dt, t0 = 0, δ = -1 // 2)`

The 3rd order, 3 stage scheme from Sandu (2019). The parameter `δ`

defaults to the value suggested by Sandu, but can be varied.

`ClimateMachine.ODESolvers.MRIGARKDecoupledImplicit`

— Type```
MRIGARKDecoupledImplicit(f!, backward_euler_solver, fastsolver, Γs, γ̂s, Q,
Δt, t0)
```

Construct a decoupled implicit MultiRate Infinitesimal General-structure Additive Runge–Kutta (MRI-GARK) scheme to solve

\[ \dot{y} = f(y, t) + g(y, t)\]

where `f`

is the slow tendency function and `g`

is the fast tendency function; see Sandu (2019).

The fast tendency is integrated using the `fastsolver`

and the slow tendency using the MRI-GARK scheme. Since this is a decoupled, implicit MRI-GARK there is no implicit coupling between the fast and slow tendencies.

The `backward_euler_solver`

should be of type `AbstractBackwardEulerSolver`

or `LinearBackwardEulerSolver`

, and is used to perform the backward Euler solves for `y`

given the slow tendency function, namely

\[ y = z + α f(y, t; p)\]

Currently only `LowStorageRungeKutta2N`

schemes are supported for `fastsolver`

The coefficients defined by `γ̂s`

can be used for an embedded scheme (only the last stage is different).

The available concrete implementations are:

**References**

## Euler methods

`ClimateMachine.ODESolvers.LinearBackwardEulerSolver`

— Type`LinearBackwardEulerSolver(::AbstractSystemSolver; isadjustable = false)`

Helper type for specifying building a backward Euler solver with a linear solver. If `isadjustable == true`

then the solver can be updated with a new time step size.

`ClimateMachine.ODESolvers.AbstractBackwardEulerSolver`

— Type`AbstractBackwardEulerSolver`

An abstract backward Euler method

`ClimateMachine.ODESolvers.NonLinearBackwardEulerSolver`

— Type```
struct NonLinearBackwardEulerSolver{NLS}
nlsolver::NLS
isadjustable::Bool
preconditioner_update_freq::Int64
end
```

Helper type for specifying building a nonlinear backward Euler solver with a nonlinear solver.

**Arguments**

`nlsolver`

: iterative nonlinear solver, i.e., JacobianFreeNewtonKrylovSolver`isadjustable`

: TODO not used, might use for updating preconditioner`preconditioner_update_freq`

: relavent to Jacobian free -1: no preconditioner; positive number, update every freq times

## Differential Equations

`ClimateMachine.ODESolvers.DiffEqJLIMEXSolver`

— Type`DiffEqJLSolver(f, RKA, RKB, RKC, Q; dt, t0 = 0)`

`f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f_I(Q, t) + f_E(Q, t)\]

via a DifferentialEquations.jl DEAlgorithm, which includes support for OrdinaryDiffEq.jl, Sundials.jl, and more.

`ClimateMachine.ODESolvers.DiffEqJLSolver`

— Type`DiffEqJLSolver(f, RKA, RKB, RKC, Q; dt, t0 = 0)`

`f`

with the state `Q`

, i.e.,

\[ \dot{Q} = f(Q, t)\]

via a DifferentialEquations.jl DEAlgorithm, which includes support for OrdinaryDiffEq.jl, Sundials.jl, and more.

## ODE Solvers

`ClimateMachine.ODESolvers.solve!`

— Function```
solve!(Q, solver::AbstractODESolver; timeend,
stopaftertimeend=true, numberofsteps, callbacks)
```

Solves an ODE using the `solver`

starting from a state `Q`

. The state `Q`

is updated inplace. The final time `timeend`

or `numberofsteps`

must be specified.

A series of optional callback functions can be specified using the tuple `callbacks`

; see the `GenericCallbacks`

module.

`ClimateMachine.ODESolvers.updatedt!`

— Function`updatedt!(solver::AbstractODESolver, dt)`

Change the time step size to `dt`

for the ODE solver `solver`

.

`ClimateMachine.ODESolvers.gettime`

— Function`gettime(solver::AbstractODESolver)`

Returns the current simulation time of the ODE solver `solver`

`ClimateMachine.ODESolvers.getsteps`

— Function`getsteps(solver::AbstractODESolver)`

Returns the number of completed time steps of the ODE solver `solver`

## Generic Callbacks

`ClimateMachine.GenericCallbacks`

— Module`GenericCallbacks`

This module defines interfaces and wrappers for callbacks to be used with an `AbstractODESolver`

.

A callback `cb`

defines three methods:

`GenericCallbacks.init!(cb, solver, Q, param, t)`

, to be called at solver initialization.`GenericCallbacks.call!(cb, solver, Q, param, t)`

, to be called after each time step: the return value dictates what action should be taken:`0`

or`nothing`

: continue time stepping as usual`1`

: stop time stepping after all callbacks have been executed`2`

: stop time stepping immediately

`GenericCallbacks.fini!(cb, solver, Q, param, t)`

, to be called at solver finish.

Additionally, *wrapper* callbacks can be used to execute the callbacks under certain conditions:

For convenience, the following objects can also be used as callbacks:

- A
`Function`

object`f`

,`init!`

and`fini!`

are no-ops, and`call!`

will call`f()`

, and ignore the return value. - A
`Tuple`

object will call`init!`

,`call!`

and`fini!`

on each element of the tuple.

`ClimateMachine.GenericCallbacks.AtInit`

— Type`AtInit(callback) <: AbstractCallback`

A wrapper callback to execute `callback`

at initialization as well as after each interval.

`ClimateMachine.GenericCallbacks.AtInitAndFini`

— Type`AtInitAndFini(callback) <: AbstractCallback`

A wrapper callback to execute `callback`

at initialization and at finish as well as after each interval.

`ClimateMachine.GenericCallbacks.EveryXWallTimeSeconds`

— Type`EveryXWallTimeSeconds(callback, Δtime, mpicomm)`

A wrapper callback to execute `callback`

every `Δtime`

wallclock time seconds. `mpicomm`

is used to syncronize runtime across MPI ranks.

`ClimateMachine.GenericCallbacks.EveryXSimulationTime`

— Type`EveryXSimulationTime(f, Δtime)`

A wrapper callback to execute `callback`

every `time`

simulation time seconds.

`ClimateMachine.GenericCallbacks.EveryXSimulationSteps`

— Type`EveryXSimulationSteps(callback, Δsteps)`

A wrapper callback to execute `callback`

every `nsteps`

of the time stepper.