I am solving a simple periodic vector parabolic equation using DifferentialEquations’ RK4() ODE solver. The code below is self contained.
For the parameters specified, the ODE solver on my computer takes 0.23s (average time after compilation) during which it calls the function dydx a total of 24261 times.
Separate benchmarking of the function dydx indicates it takes 1.4 microseconds to execute. The function dydx seems pretty optimized (0 allocations…).
The overhead of the RK4() solver appears large. Specifically, the ratio 0.23s/24261 (the effective time per call in RK4) is roughly 7 times 1.4 microseconds (the time fore one call). Given the simplicity of the RK4 scheme (just a few additions of the results from dydx), this ratio seems large.
Are there ODE parameters that can reduce this overhead? Thanks!
using DifferentialEquations
ny = 1000 # # of points along y
dy = 0.05 # discretization step along y
xspan = 90.0 # size of domain along x
nhar = 10; # number of periods along y
k = 2pi # wavenumber
ky = nhar*k/(ny*dy) # wavenumber along x
kx = sqrt(k^2-ky^2) # wavenumber along y
phi = atan(ky/kx)
phi*180/pi # angle of propagation
yin = [exp(-im*k*j*dy*sin(phi)) for j in 1:ny] # periodic excitation
abstol = 1e-6
reltol = 1e-6
@fastmath @views @inbounds function dydx!(dydxa,y,p,x)
ny,dy,k,neval = p
neval[1] += 1 #counter to keep track of function calls
ym1 = y[1]
y0 = y[2]
c2 = -im/(2.0*k*dy^2)
for i in 2:ny-1
yp1 = y[i+1]
dydxa[i] = c2*(ym1-2y0+yp1)
ym1 = y0
y0 = yp1
end
dydxa[1] = c2*(y[ny] -2y[1] + y[2])
dydxa[ny] = c2*(y[ny-1] - 2y[end] + y[1])
end
#time dydx routine
neval = [0]
p = ny,dy,k,neval
dydxa = similar(yin)
x = 0.1
@btime dydx!($dydxa,$yin,$p,$x)
# reveals time of 1.4 microsecond per call
tsingle = 1.4e-6
#time ODE solver
abstol = 1e-6
reltol = 1e-6
neval = [0]
p = ny,dy,k,neval
prob1 = ODEProblem(dydx!,yin,xspan,p)
@time sol1 = solve(prob1,RK4(),abstol=abstol,reltol=reltol,save_everystep=false)
neval[1]
#reveals time of 0.234 sec and 24261 calls to dydx
#timing was obtained after compilation
tpercallinODE = 0.234/24261
#Ratio approaches 7
tpercallinODE/tsingle