7878# If called with different functions (which are possible in the Hamiltonian case)
7979# an exception is thrown to avoid silently calculate wrong results.
8080function verify_f2 (f, p, q, pa, t, :: Any ,
81- :: C ) where {C <: Union{HamiltonConstantCache, VerletLeapfrogConstantCache} }
81+ :: C ) where {C <: Union {HamiltonConstantCache, VerletLeapfrogConstantCache,
82+ LeapfrogDriftKickDriftConstantCache}}
8283 f (p, q, pa, t)
8384end
8485function verify_f2 (f, res, p, q, pa, t, :: Any ,
85- :: C ) where {C <: Union{HamiltonMutableCache, VerletLeapfrogCache} }
86+ :: C ) where {C <: Union {HamiltonMutableCache, VerletLeapfrogCache,
87+ LeapfrogDriftKickDriftCache}}
8688 f (res, p, q, pa, t)
8789end
8890
@@ -128,8 +130,8 @@ function store_symp_state!(integrator, ::OrdinaryDiffEqMutableCache, kdu, ku)
128130end
129131
130132function initialize! (integrator,
131- cache:: C ) where {C <: Union {
132- HamiltonMutableCache, VelocityVerletCache, VerletLeapfrogCache }}
133+ cache:: C ) where {C <: Union {HamiltonMutableCache, VelocityVerletCache,
134+ VerletLeapfrogCache, LeapfrogDriftKickDriftCache }}
133135 integrator. kshortsize = 2
134136 resize! (integrator. k, integrator. kshortsize)
135137 integrator. k[1 ] = integrator. fsalfirst
@@ -144,8 +146,8 @@ function initialize!(integrator,
144146end
145147
146148function initialize! (integrator,
147- cache:: C ) where {C <: Union {
148- HamiltonConstantCache, VelocityVerletConstantCache, VerletLeapfrogConstantCache }}
149+ cache:: C ) where {C <: Union {HamiltonConstantCache, VelocityVerletConstantCache,
150+ VerletLeapfrogConstantCache, LeapfrogDriftKickDriftConstantCache }}
149151 integrator. kshortsize = 2
150152 integrator. k = typeof (integrator. k)(undef, integrator. kshortsize)
151153
@@ -207,13 +209,11 @@ end
207209 du = duprev + dt * half * kduprev
208210
209211 # update position
210- tnew = t + half * dt
211- ku = f. f2 (du, uprev, p, tnew)
212+ ku = f. f2 (du, uprev, p, t + half * dt)
212213 u = uprev + dt * ku
213214
214215 # update velocity
215- tnew = tnew + half * dt
216- kdu = f. f1 (du, u, p, tnew)
216+ kdu = f. f1 (du, u, p, t + dt)
217217 du = du + dt * half * kdu
218218
219219 OrdinaryDiffEqCore. increment_nf! (integrator. stats, 1 )
@@ -226,26 +226,83 @@ end
226226 duprev, uprev, kduprev, _ = load_symp_state (integrator)
227227 du, u, kdu, ku = alloc_symp_state (integrator)
228228
229- # Kick-Drift-Kick scheme of the Verlet Leapfrog method:
229+ # kick-drift-kick scheme of the Leapfrog method:
230230 # update velocity
231231 half = cache. half
232232 @. . broadcast= false du= duprev + dt * half * kduprev
233233
234234 # update position
235- tnew = t + half * dt
236- f. f2 (ku, du, uprev, p, tnew)
235+ f. f2 (ku, du, uprev, p, t + half * dt)
237236 @. . broadcast= false u= uprev + dt * ku
238237
239238 # update velocity
240- tnew = tnew + half * dt
241- f. f1 (kdu, du, u, p, tnew)
239+ f. f1 (kdu, du, u, p, t + dt)
242240 @. . broadcast= false du= du + dt * half * kdu
243241
244242 OrdinaryDiffEqCore. increment_nf! (integrator. stats, 1 )
245243 integrator. stats. nf2 += 1
246244 store_symp_state! (integrator, cache, kdu, ku)
247245end
248246
247+ @muladd function perform_step! (integrator, cache:: LeapfrogDriftKickDriftConstantCache ,
248+ repeat_step = false )
249+ @unpack t, dt, f, p = integrator
250+ duprev, uprev, _, _ = load_symp_state (integrator)
251+
252+ # drift-kick-drift scheme of the Leapfrog method, allowing for f1 to depend on v:
253+ # update position half step
254+ half = cache. half
255+ ku = f. f2 (duprev, uprev, p, t)
256+ u = uprev + dt * half * ku
257+
258+ # update velocity half step
259+ kdu = f. f1 (duprev, uprev, p, t)
260+ du = duprev + dt * half * kdu
261+
262+ # update velocity (add to previous full step velocity)
263+ # note that this extra step is only necessary if f1 depends on v/du (or t)
264+ kdu = f. f1 (du, u, p, t + half * dt)
265+ du = duprev + dt * kdu
266+
267+ # update position (add to half step position)
268+ ku = f. f2 (du, u, p, t + dt)
269+ u = u + dt * half * ku
270+
271+ OrdinaryDiffEqCore. increment_nf! (integrator. stats, 2 )
272+ integrator. stats. nf2 += 2
273+ store_symp_state! (integrator, cache, du, u, kdu, ku)
274+ end
275+
276+ @muladd function perform_step! (integrator, cache:: LeapfrogDriftKickDriftCache ,
277+ repeat_step = false )
278+ @unpack t, dt, f, p = integrator
279+ duprev, uprev, _, _ = load_symp_state (integrator)
280+ du, u, kdu, ku = alloc_symp_state (integrator)
281+
282+ # drift-kick-drift scheme of the Leapfrog method, allowing for f1 to depend on v:
283+ # update position half step
284+ half = cache. half
285+ f. f2 (ku, duprev, uprev, p, t)
286+ @. . broadcast= false u= uprev + dt * half * ku
287+
288+ # update velocity half step
289+ f. f1 (kdu, duprev, uprev, p, t)
290+ @. . broadcast= false du= duprev + dt * half * kdu
291+
292+ # update velocity (add to previous full step velocity)
293+ # note that this extra step is only necessary if f1 depends on v/du (or t)
294+ f. f1 (kdu, du, u, p, t + half * dt)
295+ @. . broadcast= false du= duprev + dt * kdu
296+
297+ # update position (add to half step position)
298+ f. f2 (ku, du, u, p, t + dt)
299+ @. . broadcast= false u= u + dt * half * ku
300+
301+ OrdinaryDiffEqCore. increment_nf! (integrator. stats, 2 )
302+ integrator. stats. nf2 += 2
303+ store_symp_state! (integrator, cache, kdu, ku)
304+ end
305+
249306@muladd function perform_step! (integrator, cache:: Symplectic2ConstantCache ,
250307 repeat_step = false )
251308 @unpack t, dt, f, p = integrator
0 commit comments