Rosenbrock methods
Consider an ordinary differential equation (ODE) of the form
\[u'(t) = f(t, u(t)).\]
A Rosenbrock (or Rosenbrock-Wanner, ROW) method with $s$ stages is given by its coefficients
\[\gamma = (\gamma_{i,j})_{i,j} \in \mathbb{R}^{s \times s}, \quad A = (a_{i,j})_{i,j} \in \mathbb{R}^{s \times s}, \quad b = (b_i)_i \in \mathbb{R}^{s}, \quad c = (c_i)_i \in \mathbb{R}^{s}.\]
Usually, the consistency condition
\[\forall i\colon \quad c_i = \sum_j a_{i,j}\]
is assumed, which reduces all analysis to autonomous problems.
The step from $u^{n}$ to $u^{n+1}$ is given by
\[\begin{aligned} k^i &= \Delta t f\bigl(u^n + \sum_j a_{i,j} k^j \bigr) + \Delta t J \sum_j \gamma_{ij} k_j, \\ u^{n+1} &= u^n + \sum_i b_{i} k^i. \end{aligned}\]
In RootedTrees.jl, ROW methods are represented as RosenbrockMethod
s.
Order conditions
The order conditions of ROW methods can be derived using rooted trees. In RootedTrees.jl, this functionality is again implemented in residual_order_condition
. Thus, a RosenbrockMethod
is of order $p$ if the residual_order_condition
vanishes for all rooted trees with order
up to $p$.
For example, the method GRK4A of Kaps and Rentrop (1979) can be written as follows.
using RootedTrees
γ = [0.395 0 0 0;
-0.767672395484 0.395 0 0;
-0.851675323742 0.522967289188 0.395 0;
0.288463109545 0.880214273381e-1 -.337389840627 0.395]
A = [0 0 0 0;
0.438 0 0 0;
0.796920457938 0.730795420615e-1 0 0;
0.796920457938 0.730795420615e-1 0 0]
b = [0.199293275701, 0.482645235674, 0.680614886256e-1, 0.25]
ros = RosenbrockMethod(γ, A, b)
RosenbrockMethod{Float64} with
γ: 4×4 Matrix{Float64}:
0.395 0.0 0.0 0.0
-0.767672 0.395 0.0 0.0
-0.851675 0.522967 0.395 0.0
0.288463 0.0880214 -0.33739 0.395
A: 4×4 Matrix{Float64}:
0.0 0.0 0.0 0.0
0.438 0.0 0.0 0.0
0.79692 0.0730795 0.0 0.0
0.79692 0.0730795 0.0 0.0
b: 4-element Vector{Float64}:
0.199293275701
0.482645235674
0.0680614886256
0.25
c: 4-element Vector{Float64}:
0.0
0.438
0.8699999999995001
0.8699999999995001
To verify that this method is at least fourth-order accurate, we can check the residual_order_condition
s up to this order.
using Test
@testset "GRK4A, order 4" begin
for o in 0:4
for t in RootedTreeIterator(o)
val = residual_order_condition(t, ros)
@test abs(val) < 3000 * eps()
end
end
end
Test Summary: | Pass Total Time
GRK4A, order 4 | 9 9 0.1s
To verify that this method does not satisfy the order conditions for an order of accuracy of five, we can use the following code.
@testset "GRK4A, not order 5" begin
s = 0.0
for t in RootedTreeIterator(5)
s += abs(residual_order_condition(t, ros))
end
@test s > 0.06
end
Test Summary: | Pass Total Time
GRK4A, not order 5 | 1 1 0.0s