Skip to content

Commit a265106

Browse files
Merge pull request #2559 from efaulhaber/verlet-leapfrog
Optimize `VerletLeapfrog` method
2 parents 607c124 + 87ff9ea commit a265106

File tree

4 files changed

+85
-24
lines changed

4 files changed

+85
-24
lines changed

lib/OrdinaryDiffEqSymplecticRK/src/algorithms.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ struct VelocityVerlet <: OrdinaryDiffEqPartitionedAlgorithm end
3030
verlet1967, "", "")
3131
struct VerletLeapfrog <: OrdinaryDiffEqPartitionedAlgorithm end
3232

33+
OrdinaryDiffEqCore.default_linear_interpolation(alg::VerletLeapfrog, prob) = true
34+
3335
@doc generic_solver_docstring("2nd order explicit symplectic integrator.",
3436
"PseudoVerletLeapfrog",
3537
"Symplectic Runge-Kutta Methods",

lib/OrdinaryDiffEqSymplecticRK/src/symplectic_caches.jl

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,18 @@ function alg_cache(alg::VelocityVerlet, u, rate_prototype, ::Type{uEltypeNoUnits
5757
VelocityVerletConstantCache(uEltypeNoUnits(1 // 2))
5858
end
5959

60-
@cache struct Symplectic2Cache{uType, rateType, tableauType} <: HamiltonMutableCache
60+
@cache struct VerletLeapfrogCache{uType, rateType, uEltypeNoUnits} <:
61+
OrdinaryDiffEqMutableCache
6162
u::uType
6263
uprev::uType
6364
tmp::uType
6465
k::rateType
6566
fsalfirst::rateType
66-
tab::tableauType
67+
half::uEltypeNoUnits
68+
end
69+
70+
struct VerletLeapfrogConstantCache{uEltypeNoUnits} <: HamiltonConstantCache
71+
half::uEltypeNoUnits
6772
end
6873

6974
function alg_cache(alg::VerletLeapfrog, u, rate_prototype, ::Type{uEltypeNoUnits},
@@ -73,16 +78,24 @@ function alg_cache(alg::VerletLeapfrog, u, rate_prototype, ::Type{uEltypeNoUnits
7378
tmp = zero(u)
7479
k = zero(rate_prototype)
7580
fsalfirst = zero(rate_prototype)
76-
tab = VerletLeapfrogConstantCache(constvalue(uBottomEltypeNoUnits),
77-
constvalue(tTypeNoUnits))
78-
Symplectic2Cache(u, uprev, k, tmp, fsalfirst, tab)
81+
half = uEltypeNoUnits(1 // 2)
82+
VerletLeapfrogCache(u, uprev, k, tmp, fsalfirst, half)
7983
end
8084

8185
function alg_cache(alg::VerletLeapfrog, u, rate_prototype, ::Type{uEltypeNoUnits},
8286
::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t,
8387
dt, reltol, p, calck,
8488
::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
85-
VerletLeapfrogConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits))
89+
VerletLeapfrogConstantCache(uEltypeNoUnits(1 // 2))
90+
end
91+
92+
@cache struct Symplectic2Cache{uType, rateType, tableauType} <: HamiltonMutableCache
93+
u::uType
94+
uprev::uType
95+
tmp::uType
96+
k::rateType
97+
fsalfirst::rateType
98+
tab::tableauType
8699
end
87100

88101
function alg_cache(alg::PseudoVerletLeapfrog, u, rate_prototype, ::Type{uEltypeNoUnits},
@@ -422,6 +435,7 @@ function alg_cache(alg::SofSpa10, u, rate_prototype, ::Type{uEltypeNoUnits},
422435
end
423436

424437
function get_fsalfirstlast(
425-
cache::Union{HamiltonMutableCache, VelocityVerletCache, SymplecticEulerCache}, u)
438+
cache::Union{HamiltonMutableCache, VelocityVerletCache, VerletLeapfrogCache,
439+
SymplecticEulerCache}, u)
426440
(cache.fsalfirst, cache.k)
427441
end

lib/OrdinaryDiffEqSymplecticRK/src/symplectic_perform_step.jl

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,12 @@ end
7777
# f.f2(p, q, pa, t) = p which is the Newton/Lagrange equations
7878
# If called with different functions (which are possible in the Hamiltonian case)
7979
# an exception is thrown to avoid silently calculate wrong results.
80-
verify_f2(f, p, q, pa, t, ::Any, ::C) where {C <: HamiltonConstantCache} = f(p, q, pa, t)
81-
function verify_f2(f, res, p, q, pa, t, ::Any, ::C) where {C <: HamiltonMutableCache}
80+
function verify_f2(f, p, q, pa, t, ::Any,
81+
::C) where {C <: Union{HamiltonConstantCache, VerletLeapfrogConstantCache}}
82+
f(p, q, pa, t)
83+
end
84+
function verify_f2(f, res, p, q, pa, t, ::Any,
85+
::C) where {C <: Union{HamiltonMutableCache, VerletLeapfrogCache}}
8286
f(res, p, q, pa, t)
8387
end
8488

@@ -124,8 +128,8 @@ function store_symp_state!(integrator, ::OrdinaryDiffEqMutableCache, kdu, ku)
124128
end
125129

126130
function initialize!(integrator,
127-
cache::C) where {C <:
128-
Union{HamiltonMutableCache, VelocityVerletCache}}
131+
cache::C) where {C <: Union{
132+
HamiltonMutableCache, VelocityVerletCache, VerletLeapfrogCache}}
129133
integrator.kshortsize = 2
130134
resize!(integrator.k, integrator.kshortsize)
131135
integrator.k[1] = integrator.fsalfirst
@@ -140,9 +144,8 @@ function initialize!(integrator,
140144
end
141145

142146
function initialize!(integrator,
143-
cache::C) where {
144-
C <:
145-
Union{HamiltonConstantCache, VelocityVerletConstantCache}}
147+
cache::C) where {C <: Union{
148+
HamiltonConstantCache, VelocityVerletConstantCache, VerletLeapfrogConstantCache}}
146149
integrator.kshortsize = 2
147150
integrator.k = typeof(integrator.k)(undef, integrator.kshortsize)
148151

@@ -171,7 +174,7 @@ end
171174
# v(t+Δt) = v(t) + 1/2*(a(t)+a(t+Δt))*Δt
172175
du = duprev + dt * (half * ku + half * kdu)
173176

174-
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 2)
177+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1)
175178
store_symp_state!(integrator, cache, du, u, kdu, du)
176179
end
177180

@@ -186,13 +189,63 @@ end
186189
half = cache.half
187190
@.. broadcast=false u=uprev + dt * duprev + dtsq * (half * ku)
188191
f.f1(kdu, duprev, u, p, t + dt)
189-
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 2)
192+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1)
190193
# v(t+Δt) = v(t) + 1/2*(a(t)+a(t+Δt))*Δt
191194
@.. broadcast=false du=duprev + dt * (half * ku + half * kdu)
192195

193196
store_symp_state!(integrator, cache, kdu, du)
194197
end
195198

199+
@muladd function perform_step!(integrator, cache::VerletLeapfrogConstantCache,
200+
repeat_step = false)
201+
@unpack t, dt, f, p = integrator
202+
duprev, uprev, kduprev, _ = load_symp_state(integrator)
203+
204+
# kick-drift-kick scheme of the Leapfrog method:
205+
# update velocity
206+
half = cache.half
207+
du = duprev + dt * half * kduprev
208+
209+
# update position
210+
tnew = t + half * dt
211+
ku = f.f2(du, uprev, p, tnew)
212+
u = uprev + dt * ku
213+
214+
# update velocity
215+
tnew = tnew + half * dt
216+
kdu = f.f1(du, u, p, tnew)
217+
du = du + dt * half * kdu
218+
219+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1)
220+
integrator.stats.nf2 += 1
221+
store_symp_state!(integrator, cache, du, u, kdu, ku)
222+
end
223+
224+
@muladd function perform_step!(integrator, cache::VerletLeapfrogCache, repeat_step = false)
225+
@unpack t, dt, f, p = integrator
226+
duprev, uprev, kduprev, _ = load_symp_state(integrator)
227+
du, u, kdu, ku = alloc_symp_state(integrator)
228+
229+
# Kick-Drift-Kick scheme of the Verlet Leapfrog method:
230+
# update velocity
231+
half = cache.half
232+
@.. broadcast=false du=duprev + dt * half * kduprev
233+
234+
# update position
235+
tnew = t + half * dt
236+
f.f2(ku, du, uprev, p, tnew)
237+
@.. broadcast=false u=uprev + dt * ku
238+
239+
# update velocity
240+
tnew = tnew + half * dt
241+
f.f1(kdu, du, u, p, tnew)
242+
@.. broadcast=false du=du + dt * half * kdu
243+
244+
OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1)
245+
integrator.stats.nf2 += 1
246+
store_symp_state!(integrator, cache, kdu, ku)
247+
end
248+
196249
@muladd function perform_step!(integrator, cache::Symplectic2ConstantCache,
197250
repeat_step = false)
198251
@unpack t, dt, f, p = integrator

lib/OrdinaryDiffEqSymplecticRK/src/symplectic_tableaus.jl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@ function McAte2ConstantCache(T, T2)
2121
Symplectic2ConstantCache{T, T2}(a1, a2, b1, b2)
2222
end
2323

24-
function VerletLeapfrogConstantCache(T, T2)
25-
a1 = convert(T, 1 // 2)
26-
a2 = convert(T, 1 // 2)
27-
b1 = convert(T, 0)
28-
b2 = convert(T, 1)
29-
Symplectic2ConstantCache{T, T2}(a1, a2, b1, b2)
30-
end
31-
3224
struct Symplectic3ConstantCache{T, T2} <: HamiltonConstantCache
3325
a1::T
3426
a2::T

0 commit comments

Comments
 (0)