Skip to content

Commit 318ea29

Browse files
Add the Makazaga-Murua MM5GEE global-error-estimating solver
Adds the DOPRI5-based order-5 scheme with cheap global error estimation of Makazaga and Murua (BIT 43, 2003) as another tableau in the GLEE general linear framework (SciML/GlobalDiffEq.jl#6, the coefficient- complete published representative of the Dormand-Duckers-Prince RK triple family). Stages 1-7 are the standard DOPRI5 stages, three extra stages propagate an order-6 companion solution, and a generic solution-stage FSAL detection reuses stage 7's evaluation for fsallast, giving exactly 9 function evaluations per step (verified by an nf accounting test). The tableau was verified with exact rational arithmetic against the order and independency conditions. Verified locally on the unstable Prince42 problem: solution order 5, estimate accuracy order 6, est/true-error ratio 1.04, 9.01 f-evals/step. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
1 parent 97c4bb2 commit 318ea29

7 files changed

Lines changed: 88 additions & 7 deletions

File tree

docs/src/globalerrorcontrol/GlobalDiffEq.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ using GlobalDiffEq
1818

1919
- For a solution accompanied by a running, asymptotically correct estimate of
2020
its global error at every time point, use the global-error-estimating
21-
solvers [`GLEE24`](@ref) or [`GLEE35`](@ref) (Constantinescu 2016). These
22-
cost only a few extra stages per step over a plain method of the same order
23-
and require nothing beyond the right-hand side `f`.
21+
solvers [`GLEE24`](@ref), [`GLEE35`](@ref) (Constantinescu 2016), or the
22+
Dormand-Prince-based [`MM5GEE`](@ref) (Makazaga and Murua 2003). These cost
23+
only a few extra stages per step over a plain method of the same order and
24+
require nothing beyond the right-hand side `f`.
2425
- To *control* the endpoint global error to a tolerance `gtol`, wrap any
2526
adaptive solver in [`GlobalAdjoint`](@ref) (adjoint-based, for endpoint
2627
functionals; requires SciMLSensitivity and QuadGK to be loaded). It solves
@@ -51,6 +52,7 @@ errs = global_error_estimate(sol) # global error estimate at every sol.t
5152
GLEE23
5253
GLEE24
5354
GLEE35
55+
MM5GEE
5456
global_error_estimate
5557
```
5658

lib/GlobalDiffEq/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "GlobalDiffEq"
22
uuid = "1d72d19b-84cc-4cb7-a099-7cbdb9ccc67c"
33
authors = ["Chris Rackauckas <accounts@chrisrackauckas.com> and contributors"]
4-
version = "1.4.0"
4+
version = "1.5.0"
55

66
[deps]
77
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"

lib/GlobalDiffEq/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ provides:
1515
- `GLEE23`, `GLEE24`, `GLEE35`: explicit general linear methods with built-in
1616
global error estimation (Constantinescu 2016), which propagate the solution
1717
together with an asymptotically correct estimate of its global error.
18+
- `MM5GEE`: the Makazaga-Murua (2003) Dormand-Prince-based order-5 scheme
19+
with a cheap built-in global error estimate.
1820
- `GlobalAdjoint`: adjoint-based a posteriori endpoint error estimation and
1921
control (Cao and Petzold 2004), available as a package extension when
2022
SciMLSensitivity and QuadGK are loaded.

lib/GlobalDiffEq/src/GlobalDiffEq.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ include("glee/caches.jl")
2222
include("glee/perform_step.jl")
2323

2424
export GlobalAdjoint, GlobalRichardson, adjoint_error_estimate
25-
export GLEE23, GLEE24, GLEE35, global_error_estimate
25+
export GLEE23, GLEE24, GLEE35, MM5GEE, global_error_estimate
2626

2727
@setup_workload begin
2828
# Simple test ODE: exponential decay du/dt = -u

lib/GlobalDiffEq/src/glee/algorithms.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,33 @@ $(_GLEE_DOCS_SHARED)
5858
"""
5959
struct GLEE35 <: AbstractGLEEAlgorithm end
6060

61+
"""
62+
MM5GEE()
63+
64+
Fifth-order Dormand-Prince-based scheme with cheap global error estimation
65+
(Makazaga and Murua, BIT Numerical Mathematics 43, 2003). Propagates the
66+
standard DOPRI5 solution together with an order-6 companion solution through
67+
three extra stages (9 function evaluations per step in total), whose
68+
difference is an asymptotically correct global error estimate. This is the
69+
recommended method of the Runge-Kutta triple family of Dormand, Duckers and
70+
Prince, as it is the coefficient-complete published scheme of that type.
71+
72+
$(_GLEE_DOCS_SHARED)
73+
74+
- J. Makazaga and A. Murua, New Runge-Kutta based schemes for ODEs with
75+
cheap global error estimation, BIT Numerical Mathematics 43 (2003).
76+
"""
77+
struct MM5GEE <: AbstractGLEEAlgorithm end
78+
6179
SciMLBase.alg_order(::GLEE23) = 2
6280
SciMLBase.alg_order(::GLEE24) = 2
6381
SciMLBase.alg_order(::GLEE35) = 3
82+
SciMLBase.alg_order(::MM5GEE) = 5
6483

6584
OrdinaryDiffEqCore.alg_adaptive_order(alg::AbstractGLEEAlgorithm) =
6685
SciMLBase.alg_order(alg)
6786

6887
_glee_tableau_for(::GLEE23, ::Type{T}, ::Type{T2}) where {T, T2} = GLEE23Tableau(T, T2)
6988
_glee_tableau_for(::GLEE24, ::Type{T}, ::Type{T2}) where {T, T2} = GLEE24Tableau(T, T2)
7089
_glee_tableau_for(::GLEE35, ::Type{T}, ::Type{T2}) where {T, T2} = GLEE35Tableau(T, T2)
90+
_glee_tableau_for(::MM5GEE, ::Type{T}, ::Type{T2}) where {T, T2} = MM5GEETableau(T, T2)

lib/GlobalDiffEq/src/glee/tableaus.jl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,48 @@ function GLEE35Tableau(::Type{T}, ::Type{T2}) where {T, T2}
142142
Uyε, Byε = _yytilde_to_yeps(U, B, Z)
143143
return _glee_tableau(T, T2, A, Uyε, Byε, 0, 3)
144144
end
145+
146+
"""
147+
MM5GEETableau(T, T2)
148+
149+
Tableau of the Makazaga-Murua global-error-estimating scheme built on the
150+
Dormand-Prince 5(4) method (Makazaga and Murua, BIT Numerical Mathematics 43,
151+
2003, Table 4.1), rewritten in the y-ε general linear form: stages 1-7 are the
152+
standard DOPRI5 stages (stage 7 the FSAL stage), stages 8-10 propagate the
153+
order-6 companion solution `ȳ = y + ε` through the mixing coefficients
154+
`U[i,2] = 1 - μ_i`, and the second output row is `b̄ - b`.
155+
"""
156+
function MM5GEETableau(::Type{T}, ::Type{T2}) where {T, T2}
157+
R(num, den) = big(num) // big(den)
158+
Z = R(0, 1)
159+
b = [
160+
R(35, 384), Z, R(500, 1113), R(125, 192), R(-2187, 6784), R(11, 84), Z,
161+
Z, Z, Z,
162+
]
163+
A = [
164+
Z Z Z Z Z Z Z Z Z Z;
165+
R(1, 5) Z Z Z Z Z Z Z Z Z;
166+
R(3, 40) R(9, 40) Z Z Z Z Z Z Z Z;
167+
R(44, 45) R(-56, 15) R(32, 9) Z Z Z Z Z Z Z;
168+
R(19372, 6561) R(-25360, 2187) R(64448, 6561) R(-212, 729) Z Z Z Z Z Z;
169+
R(9017, 3168) R(-355, 33) R(46732, 5247) R(49, 176) R(-5103, 18656) Z Z Z Z Z;
170+
R(35, 384) Z R(500, 1113) R(125, 192) R(-2187, 6784) R(11, 84) Z Z Z Z;
171+
R(26251126, 75292183) R(-30511879, 68834945) R(11490887, 155205387) R(700737845, 174891007) R(-5336, 941) R(5735, 1214) R(-2507, 898) Z Z Z;
172+
R(-126276029, 115017392) R(153409379, 49308629) R(-107711621, 48274693) R(-675136779, 64711289) R(559269939, 36928210) R(-669687859, 52442748) R(193952703, 25738526) R(169021117, 130072535) Z Z;
173+
R(89178409, 82486612) R(-275044175, 99029299) R(115406143, 68971088) R(140298385, 24130572) R(-344040692, 42025591) R(121333564, 17575013) R(-190380249, 47005513) R(-12078143, 165601005) R(56747365, 92317949) Z
174+
]
175+
# U[:, 2] = 1 - μ_i: the weight of the companion register ȳ = y + ε in each
176+
# stage; μ_i = 1 for the DOPRI5 stages 1-7.
177+
one_minus_μ = [
178+
Z, Z, Z, Z, Z, Z, Z,
179+
R(140719960, 143529893), R(941, 896), R(92493035, 95359057),
180+
]
181+
U = hcat(fill(R(1, 1), 10), one_minus_μ)
182+
= [
183+
R(56696811, 789712427), Z, R(-47431484, 279691831), R(72791025, 357831874),
184+
R(17490085, 349505178), R(-66245097, 563676842), R(-24, 611),
185+
R(40757463, 82884629), R(33159666, 111811519), R(42422453, 199331202),
186+
]
187+
B = permutedims(hcat(b, b̄ .- b))
188+
return _glee_tableau(T, T2, A, U, B, 0, 5)
189+
end

lib/GlobalDiffEq/test/glee_tests.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,15 @@ end
4242
# to the true error one order faster than the solution converges
4343
@test est_order p + 1 atol = 0.2
4444
end
45+
sol_order, est_order = glee_convergence(prob, MM5GEE(), 2.0 .^ -(2:5))
46+
@test sol_order 5 atol = 0.35
47+
@test est_order > 5.5
4548
end
4649
end
4750

4851
@testset "GLEE estimate tracks the true error" begin
4952
prob = ODEProblem(f_prince!, [0.0], prince_tspan)
50-
for alg in (GLEE23(), GLEE24(), GLEE35())
53+
for alg in (GLEE23(), GLEE24(), GLEE35(), MM5GEE())
5154
sol = solve(prob, alg; dt = 1 / 128, adaptive = false)
5255
err = prince_exact(prince_tspan[2]) - sol.u[end].x[1][1]
5356
est = global_error_estimate(sol)[end][1]
@@ -57,7 +60,7 @@ end
5760

5861
@testset "GLEE adaptive stepping" begin
5962
prob = ODEProblem(f_prince!, [0.0], prince_tspan)
60-
for alg in (GLEE24(), GLEE35())
63+
for alg in (GLEE24(), MM5GEE())
6164
sol = solve(prob, alg; abstol = 1.0e-8, reltol = 1.0e-8)
6265
@test SciMLBase.successful_retcode(sol)
6366
err = prince_exact(prince_tspan[2]) - sol.u[end].x[1][1]
@@ -78,6 +81,14 @@ end
7881
@test global_error_estimate(sol)[end][1] / err 1 rtol = 0.1
7982
end
8083

84+
@testset "MM5GEE function evaluation count" begin
85+
prob = ODEProblem(f_prince!, [0.0], prince_tspan)
86+
sol = solve(prob, MM5GEE(); dt = 1 / 32, adaptive = false)
87+
# 9 f-evals per step (FSAL first stage + solution stage reuse) plus the
88+
# initialization evaluation
89+
@test sol.stats.nf == 9 * (length(sol.t) - 1) + 1
90+
end
91+
8192
@testset "GLEE argument validation" begin
8293
prob = ODEProblem(f_prince!, [0.0], prince_tspan)
8394
partitioned_prob = ODEProblem(
@@ -96,4 +107,5 @@ end
96107
@test SciMLBase.alg_order(GLEE23()) == 2
97108
@test SciMLBase.alg_order(GLEE24()) == 2
98109
@test SciMLBase.alg_order(GLEE35()) == 3
110+
@test SciMLBase.alg_order(MM5GEE()) == 5
99111
end

0 commit comments

Comments
 (0)