Skip to content

Commit 7821590

Browse files
Harsh SinghHarsh Singh
authored andcommitted
Add Ralston4 explicit Runge–Kutta method to OrdinaryDiffEqLowOrderRK
1 parent ed254c3 commit 7821590

File tree

12 files changed

+177
-7
lines changed

12 files changed

+177
-7
lines changed

lib/OrdinaryDiffEqLowOrderRK/src/OrdinaryDiffEqLowOrderRK.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export Euler, SplitEuler, Heun, Ralston, Midpoint, RK4,
4545
BS3, OwrenZen3, OwrenZen4, OwrenZen5, BS5,
4646
DP5, Anas5, RKO65, FRK65, RKM, MSRK5, MSRK6,
4747
PSRK4p7q6, PSRK3p5q4, PSRK3p6q5, Stepanov5, SIR54,
48-
Alshina2, Alshina3, Alshina6, AutoDP5
48+
Alshina2, Alshina3, Alshina6, AutoDP5,
49+
Ralston4
4950

5051
end

lib/OrdinaryDiffEqLowOrderRK/src/alg_utils.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ alg_order(alg::RKO65) = 5
1414
alg_order(alg::FRK65) = 6
1515
alg_order(alg::RK4) = 4
1616
alg_order(alg::RKM) = 4
17+
alg_order(alg::Ralston4) = 4
1718
alg_order(alg::MSRK5) = 5
1819
alg_order(alg::MSRK6) = 6
1920
alg_order(alg::PSRK4p7q6) = 4

lib/OrdinaryDiffEqLowOrderRK/src/algorithms.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,28 @@ function RKM(stage_limiter!, step_limiter! = trivial_limiter!)
348348
return RKM(stage_limiter!, step_limiter!, False())
349349
end
350350

351+
@doc explicit_rk_docstring(
352+
"4th order Ralston method with minimum truncation error for 4-stage explicit Runge-Kutta.",
353+
"Ralston4",
354+
references = "@article{ralston1962runge,
355+
title={Runge-Kutta methods with minimum error bounds},
356+
author={Ralston, Anthony},
357+
journal={Mathematics of Computation},
358+
volume={16},
359+
number={80},
360+
pages={431--437},
361+
year={1962}
362+
}"
363+
)
364+
Base.@kwdef struct Ralston4{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm
365+
stage_limiter!::StageLimiter = trivial_limiter!
366+
step_limiter!::StepLimiter = trivial_limiter!
367+
thread::Thread = False()
368+
end
369+
function Ralston4(stage_limiter!, step_limiter! = trivial_limiter!)
370+
return Ralston4(stage_limiter!, step_limiter!, False())
371+
end
372+
351373
@doc explicit_rk_docstring(
352374
"5th order method.", "MSRK5",
353375
references = "Misha Stepanov - https://arxiv.org/pdf/2202.08443.pdf : Figure 3."

lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_caches.jl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,3 +1665,47 @@ function alg_cache(
16651665
alg.step_limiter!, alg.thread
16661666
)
16671667
end
1668+
1669+
@cache struct Ralston4Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <:
1670+
OrdinaryDiffEqMutableCache
1671+
u::uType
1672+
uprev::uType
1673+
fsalfirst::rateType
1674+
k2::rateType
1675+
k3::rateType
1676+
k4::rateType
1677+
k::rateType
1678+
tmp::uType
1679+
tab::TabType
1680+
stage_limiter!::StageLimiter
1681+
step_limiter!::StepLimiter
1682+
thread::Thread
1683+
end
1684+
1685+
function alg_cache(
1686+
alg::Ralston4, u, rate_prototype, ::Type{uEltypeNoUnits},
1687+
::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t,
1688+
dt, reltol, p, calck,
1689+
::Val{false}, verbose
1690+
) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
1691+
return Ralston4ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits))
1692+
end
1693+
1694+
function alg_cache(
1695+
alg::Ralston4, u, rate_prototype, ::Type{uEltypeNoUnits},
1696+
::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t,
1697+
dt, reltol, p, calck,
1698+
::Val{true}, verbose
1699+
) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
1700+
tab = Ralston4ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits))
1701+
fsalfirst = zero(rate_prototype)
1702+
k2 = zero(rate_prototype)
1703+
k3 = zero(rate_prototype)
1704+
k4 = zero(rate_prototype)
1705+
k = zero(rate_prototype)
1706+
tmp = zero(u)
1707+
return Ralston4Cache(
1708+
u, uprev, fsalfirst, k2, k3, k4, k, tmp, tab, alg.stage_limiter!,
1709+
alg.step_limiter!, alg.thread
1710+
)
1711+
end

lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_perform_step.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,3 +2209,65 @@ function perform_step!(integrator, cache::Alshina6Cache, repeat_step = false)
22092209
integrator.fsallast = k7
22102210
return nothing
22112211
end
2212+
2213+
function initialize!(integrator, cache::Ralston4ConstantCache)
2214+
integrator.kshortsize = 2
2215+
integrator.k = typeof(integrator.k)(undef, integrator.kshortsize)
2216+
integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t)
2217+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1)
2218+
integrator.fsallast = zero(integrator.fsalfirst)
2219+
integrator.k[1] = integrator.fsalfirst
2220+
return integrator.k[2] = integrator.fsallast
2221+
end
2222+
2223+
@muladd function perform_step!(
2224+
integrator, cache::Ralston4ConstantCache, repeat_step = false
2225+
)
2226+
(; t, dt, uprev, u, f, p) = integrator
2227+
(; a21, a31, a32, a41, a42, a43, c2, c3, b1, b2, b3, b4) = cache
2228+
k1 = integrator.fsalfirst
2229+
k2 = f(uprev + dt * a21 * k1, p, t + c2 * dt)
2230+
k3 = f(uprev + dt * (a31 * k1 + a32 * k2), p, t + c3 * dt)
2231+
k4 = f(uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3), p, t + dt)
2232+
u = uprev + dt * (b1 * k1 + b2 * k2 + b3 * k3 + b4 * k4)
2233+
integrator.fsallast = f(u, p, t + dt)
2234+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 4)
2235+
integrator.k[1] = integrator.fsalfirst
2236+
integrator.k[2] = integrator.fsallast
2237+
integrator.u = u
2238+
end
2239+
2240+
get_fsalfirstlast(cache::Ralston4Cache, u) = (cache.fsalfirst, cache.k)
2241+
function initialize!(integrator, cache::Ralston4Cache)
2242+
(; fsalfirst, k) = cache
2243+
integrator.fsalfirst = fsalfirst
2244+
integrator.fsallast = k
2245+
integrator.kshortsize = 2
2246+
resize!(integrator.k, integrator.kshortsize)
2247+
integrator.k[1] = integrator.fsalfirst
2248+
integrator.k[2] = integrator.fsallast
2249+
integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t)
2250+
return OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1)
2251+
end
2252+
2253+
@muladd function perform_step!(integrator, cache::Ralston4Cache, repeat_step = false)
2254+
(; t, dt, uprev, u, f, p) = integrator
2255+
(; fsalfirst, k2, k3, k4, k, tmp, tab, stage_limiter!, step_limiter!, thread) = cache
2256+
(; a21, a31, a32, a41, a42, a43, c2, c3, b1, b2, b3, b4) = tab
2257+
k1 = fsalfirst
2258+
@.. broadcast = false thread = thread tmp = uprev + dt * a21 * k1
2259+
stage_limiter!(tmp, integrator, p, t + c2 * dt)
2260+
f(k2, tmp, p, t + c2 * dt)
2261+
@.. broadcast = false thread = thread tmp = uprev + dt * (a31 * k1 + a32 * k2)
2262+
stage_limiter!(tmp, integrator, p, t + c3 * dt)
2263+
f(k3, tmp, p, t + c3 * dt)
2264+
@.. broadcast = false thread = thread tmp = uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3)
2265+
stage_limiter!(tmp, integrator, p, t + dt)
2266+
f(k4, tmp, p, t + dt)
2267+
@.. broadcast = false thread = thread u = uprev + dt * (b1 * k1 + b2 * k2 + b3 * k3 + b4 * k4)
2268+
stage_limiter!(u, integrator, p, t + dt)
2269+
step_limiter!(u, integrator, p, t + dt)
2270+
f(k, u, p, t + dt)
2271+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 4)
2272+
return nothing
2273+
end

lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_tableaus.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,3 +1964,37 @@ function Alshina6ConstantCache(T, T2)
19641964
b1, b5, b6, b7, c2, c3, c4, c5, c6, c7
19651965
)
19661966
end
1967+
1968+
struct Ralston4ConstantCache{T, T2} <: OrdinaryDiffEqConstantCache
1969+
a21::T
1970+
a31::T
1971+
a32::T
1972+
a41::T
1973+
a42::T
1974+
a43::T
1975+
c2::T2
1976+
c3::T2
1977+
b1::T
1978+
b2::T
1979+
b3::T
1980+
b4::T
1981+
end
1982+
1983+
function Ralston4ConstantCache(T, T2)
1984+
s5 = sqrt(convert(T, 5))
1985+
b1 = (263 + 24 * s5) / 1812
1986+
b4 = (30 - 4 * s5) / 123
1987+
b2 = (125 - 1000 * s5) / 3828
1988+
b3 = 1 - b1 - b2 - b4
1989+
c2 = convert(T2, 2 // 5)
1990+
c3 = convert(T2, (14 - 3 * s5) / 16)
1991+
a21 = convert(T, c2)
1992+
Ac3 = 2 / (3 * b3 * (2 + 3 * s5))
1993+
a32 = (5 // 2) * Ac3
1994+
a31 = c3 - a32
1995+
a43 = b3 * (2 + 3 * s5) / (16 * b4)
1996+
Ac4 = (1 // 6 - b3 * Ac3) / b4
1997+
a42 = (5 // 2) * (Ac4 - a43 * c3)
1998+
a41 = 1 - a42 - a43
1999+
return Ralston4ConstantCache(a21, a31, a32, a41, a42, a43, c2, c3, b1, b2, b3, b4)
2000+
end

src/OrdinaryDiffEq.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,14 @@ using OrdinaryDiffEqLowOrderRK: Euler, SplitEuler, Heun, Ralston, Midpoint, RK4,
204204
BS3, OwrenZen3, OwrenZen4, OwrenZen5, BS5,
205205
DP5, Anas5, RKO65, FRK65, RKM, MSRK5, MSRK6,
206206
PSRK4p7q6, PSRK3p5q4, PSRK3p6q5, Stepanov5, SIR54,
207-
Alshina2, Alshina3, Alshina6, AutoDP5
207+
Alshina2, Alshina3, Alshina6, AutoDP5,
208+
Ralston4
208209
export OrdinaryDiffEqLowOrderRK, Euler, SplitEuler, Heun, Ralston, Midpoint, RK4,
209210
BS3, OwrenZen3, OwrenZen4, OwrenZen5, BS5,
210211
DP5, Anas5, RKO65, FRK65, RKM, MSRK5, MSRK6,
211212
PSRK4p7q6, PSRK3p5q4, PSRK3p6q5, Stepanov5, SIR54,
212-
Alshina2, Alshina3, Alshina6, AutoDP5
213+
Alshina2, Alshina3, Alshina6, AutoDP5,
214+
Ralston4
213215

214216
import OrdinaryDiffEqFunctionMap: OrdinaryDiffEqFunctionMap
215217
using OrdinaryDiffEqFunctionMap: FunctionMap

test/integrators/step_limiter_test.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ end
2929
Rosenbrock23, Rosenbrock32, ROS3P, Rodas3, Rodas23W, Rodas3P, Rodas4, Rodas42,
3030
Rodas4P, Rodas4P2, Rodas5, Rodas5P, Rodas5Pe, Rodas5Pr,
3131
AdaptiveRadau, RadauIIA9, RadauIIA5, RadauIIA3, SIR54,
32-
Alshina2, Alshina3, Heun, Ralston, Midpoint, RK4,
32+
Alshina2, Alshina3, Heun, Ralston, Ralston4, Midpoint, RK4,
3333
OwrenZen3, OwrenZen4, OwrenZen5,
3434
BS3, DP5, Tsit5, DP8, TanYam7, TsitPap8, FRK65, PFRK87, BS5, Vern6, Vern7,
3535
Vern8, Vern9, QPRK98, SSPRKMSVS43, SSPRKMSVS32, SSPRK432, SSPRK43,

test/interface/float32.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tspan = (zero(NF), NF(1.0e3)) #integrate from t=0 to t = 1000
1111
ode_prob = ODEProblem(some_arbitrary_function!, u, tspan, params)
1212

1313
for alg in [
14-
Euler(), Midpoint(), Heun(), Ralston(), RK4(), SSPRK104(), SSPRK22(), SSPRK33(),
14+
Euler(), Midpoint(), Heun(), Ralston(), Ralston4(), RK4(), SSPRK104(), SSPRK22(), SSPRK33(),
1515
SSPRK43(), SSPRK432(), BS3(), BS5(), DP5(), DP8(), Feagin10(), Feagin12(),
1616
Feagin14(), TanYam7(), Tsit5(), TsitPap8(), Vern6(), Vern7(), Vern8(), Vern9(),
1717
]

test/interface/units_tests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using LinearAlgebra, Test, ADTypes
33

44
@testset "Algorithms" begin
55
algs = [
6-
Euler(), Midpoint(), Heun(), Ralston(), RK4(), SSPRK104(), SSPRK22(), SSPRK33(),
6+
Euler(), Midpoint(), Heun(), Ralston(), Ralston4(), RK4(), SSPRK104(), SSPRK22(), SSPRK33(),
77
SSPRK43(), SSPRK432(), BS3(), BS5(), DP5(), DP8(), Feagin10(), Feagin12(),
88
Feagin14(), TanYam7(), Tsit5(), TsitPap8(), Vern6(), Vern7(), Vern8(), Vern9(),
99
]

0 commit comments

Comments
 (0)