Skip to content

Commit

Permalink
EPIRK4s3B (in-place)
Browse files Browse the repository at this point in the history
  • Loading branch information
MSeeker1340 committed Jul 4, 2018
1 parent 8486f91 commit 461da92
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
26 changes: 26 additions & 0 deletions src/caches/linear_nonlinear_caches.jl
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,32 @@ struct EPIRK4s3BConstantCache <: ExpRKConstantCache end
alg_cache(alg::EPIRK4s3B,u,rate_prototype,uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits,
uprev,uprev2,f,t,dt,reltol,p,calck,::Type{Val{false}}) = EPIRK4s3BConstantCache()

struct EPIRK4s3BCache{uType,rateType,matType,KsType} <: ExpRKCache
u::uType
uprev::uType
tmp::uType
rtmp::rateType
rtmp2::rateType
K::matType
A::matType
B::matType
KsCache::KsType
end
function alg_cache(alg::EPIRK4s3B,u,rate_prototype,uEltypeNoUnits,uBottomEltypeNoUnits,
tTypeNoUnits,uprev,uprev2,f,t,dt,reltol,p,calck,::Type{Val{true}})
tmp = similar(u) # uType caches
rtmp, rtmp2 = (zeros(rate_prototype) for i = 1:2) # rateType caches
# Allocate matrices
n = length(u); T = eltype(u)
K = Matrix{T}(n, 2)
A = Matrix{T}(n, n) # TODO: sparse Jacobian support
B = zeros(T, n, 5)
# Allocate caches for phiv_timestep
maxiter = min(alg.m, n)
KsCache = _phiv_timestep_caches(u, maxiter, 4)
EPIRK4s3BCache(u,uprev,tmp,rtmp,rtmp2,K,A,B,KsCache)
end

####################################
# Multistep exponential method caches

Expand Down
40 changes: 40 additions & 0 deletions src/perform_step/exponential_rk_perform_step.jl
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,46 @@ function perform_step!(integrator, cache::EPIRK4s3BConstantCache, repeat_step=fa
integrator.u = u
end

function perform_step!(integrator, cache::EPIRK4s3BCache, repeat_step=false)
@unpack t,dt,uprev,u,f,p = integrator
@unpack tmp,rtmp,rtmp2,K,A,B,KsCache = cache
f.jac(A, uprev, p, t)
alg = typeof(integrator.alg) <: CompositeAlgorithm ? integrator.alg.algs[integrator.cache.current] : integrator.alg
f0 = integrator.fsalfirst # f(u0) is fsaled
kwargs = [(:tol, integrator.opts.reltol), (:iop, alg.iop), (:norm, integrator.opts.internalnorm),
(:adaptive, true), (:caches, KsCache)]

# Compute U2 and U3 vertically
fill!(@view(B[:, 2]), zero(eltype(B)))
B[:, 3] .= f0
phiv_timestep!(K, [dt/2, 3dt/4], A, @view(B[:, 1:3]); kwargs...)
K[:, 1] .*= 8 / (3*dt)
K[:, 2] .*= 16 / (9*dt)
## U2 and R2
@. tmp = uprev + @view(K[:, 1]) # tmp is now U2
f(rtmp, tmp, p, t + dt/2); A_mul_B!(rtmp2, A, @view(K[:, 1]))
@. rtmp = rtmp - f0 - rtmp2 # rtmp is now R2
B[:, 4] .= (54/dt^2) * rtmp
B[:, 5] .= (-324/dt^3) * rtmp
## U3 and R3
@. tmp = uprev + @view(K[:, 2]) # tmp is now U3
f(rtmp, tmp, p, t + 3dt/4); A_mul_B!(rtmp2, A, @view(K[:, 2]))
@. rtmp = rtmp - f0 - rtmp2 # rtmp is now R3
B[:, 4] .-= (16/dt^2) * rtmp
B[:, 5] .+= (144/dt^3) * rtmp

# Update u
fill!(@view(B[:, 3]), zero(eltype(B)))
B[:, 2] .= f0
du = @view(K[:, 1])
phiv_timestep!(du, dt, A, B; kwargs...)
@. u = uprev + du

# Update integrator state
f(integrator.fsallast, u, p, t + dt)
# integrator.k is automatically set due to aliasing
end

######################################################
# Multistep exponential integrators
function initialize!(integrator,cache::ETD2ConstantCache)
Expand Down
2 changes: 1 addition & 1 deletion test/linear_nonlinear_krylov_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ end
prob_ip = ODEProblem{true}(f_ip, u0, (0.0, 1.0))

dt = 0.05; tol=1e-5
Algs = [Exp4, EPIRK4s3A]
Algs = [Exp4, EPIRK4s3A, EPIRK4s3B]
for Alg in Algs
gc()
sol = solve(prob, Alg(); dt=dt, internalnorm=Base.norm, reltol=tol)
Expand Down

0 comments on commit 461da92

Please sign in to comment.