Skip to content

Commit e4abed8

Browse files
committed
W2Ito1 scheme
1 parent 5a7ca13 commit e4abed8

File tree

9 files changed

+693
-2
lines changed

9 files changed

+693
-2
lines changed

src/StochasticDiffEq.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ end
151151
SROCK1, SROCK2, SROCKEM, SKSROCK, TangXiaoSROCK2, KomBurSROCK2, SROCKC2,
152152
WangLi3SMil_A, WangLi3SMil_B, WangLi3SMil_C, WangLi3SMil_D, WangLi3SMil_E, WangLi3SMil_F,
153153
AutoSOSRI2, AutoSOSRA2,
154-
DRI1, DRI1NM, RI1, RI3, RI5, RI6, RDI1WM, RDI2WM, RDI3WM, RDI4WM,
154+
DRI1, DRI1NM, RI1, RI3, RI5, RI6, RDI1WM, RDI2WM, RDI3WM, RDI4WM, W2Ito1,
155155
RS1, RS2,
156156
PL1WM, PL1WMA,
157157
NON, COM, NON2

src/alg_utils.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ alg_order(alg::RDI1WM) = 1 // 1
101101
alg_order(alg::RDI2WM) = 1 // 1
102102
alg_order(alg::RDI3WM) = 1 // 1
103103
alg_order(alg::RDI4WM) = 1 // 1
104+
alg_order(alg::W2Ito1) = 1 // 1
104105

105106
alg_order(alg::RS1) = 1 // 1
106107
alg_order(alg::RS2) = 1 // 1
@@ -181,6 +182,7 @@ alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::RDI1WM) = true
181182
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::RDI2WM) = true
182183
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::RDI3WM) = true
183184
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::RDI4WM) = true
185+
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::W2Ito1) = true
184186
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::RS1) = true
185187
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::RS2) = true
186188
alg_compatible(prob::DiffEqBase.AbstractSDEProblem, alg::PL1WM) = true
@@ -254,6 +256,7 @@ alg_needs_extra_process(alg::RDI1WM) = true
254256
alg_needs_extra_process(alg::RDI2WM) = true
255257
alg_needs_extra_process(alg::RDI3WM) = true
256258
alg_needs_extra_process(alg::RDI4WM) = true
259+
alg_needs_extra_process(alg::W2Ito1) = true
257260
alg_needs_extra_process(alg::RS1) = true
258261
alg_needs_extra_process(alg::RS2) = true
259262
alg_needs_extra_process(alg::PL1WM) = true

src/algorithms.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Defaults to solving the Ito problem, but RKMilCommute(interpretation=:Stratonovi
9393
Uses a 1.5/2.0 error estimate for adaptive time stepping.
9494
Default: ii_approx=IICommutative() does not approximate the Levy area.
9595
"""
96-
struct RKMilCommute{T} <: StochasticDiffEqAdaptiveAlgorithm
96+
struct RKMilCommute{T} <: StochasticDiffEqAdaptiveAlgorithm
9797
interpretation::Symbol
9898
ii_approx::T
9999
end
@@ -483,6 +483,19 @@ Can handle diagonal, non-diagonal, non-commuting, and scalar additive noise.
483483
"""
484484
struct RDI4WM <: StochasticDiffEqAdaptiveAlgorithm end
485485

486+
487+
"""
488+
Tang, X., & Xiao, A., Efficient weak second-order stochastic Runge–Kutta methods
489+
for Itô stochastic differential equations,
490+
BIT Numerical Mathematics, 57, 241-260 (2017)
491+
DOI: 10.1007/s10543-016-0618-9
492+
493+
W2Ito1: High Weak Order Method
494+
Adaptive step weak order 2.0 for Ito SDEs (deterministic order 3).
495+
Can handle diagonal, non-diagonal, non-commuting, and scalar additive noise.
496+
"""
497+
struct W2Ito1 <: StochasticDiffEqAdaptiveAlgorithm end
498+
486499
# Stratonovich sense
487500

488501
"""

src/caches/srk_weak_caches.jl

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,3 +2318,167 @@ function alg_cache(alg::SMEB,prob,u,ΔW,ΔZ,p,rate_prototype,
23182318

23192319
SIESMECache(u,uprev,W2,W3,tab,k0,k1,g0,g1,g2,tmpu)
23202320
end
2321+
2322+
2323+
2324+
2325+
2326+
# Tang & Xiao: DOI 10.1007/s10543-016-0618-9 W2Ito1 and W2Ito2 methods
2327+
2328+
struct W2Ito1ConstantCache{T} <: StochasticDiffEqConstantCache
2329+
# hard-coded version
2330+
a021::T
2331+
a031::T
2332+
a032::T
2333+
2334+
a121::T
2335+
a131::T
2336+
#a132::T
2337+
2338+
#a221::T
2339+
#a231::T
2340+
#a232::T
2341+
2342+
b021::T
2343+
b031::T
2344+
#b032::T
2345+
2346+
b121::T
2347+
b131::T
2348+
#b132::T
2349+
2350+
b221::T
2351+
#b222::T
2352+
#b223::T
2353+
#b231::T
2354+
#b232::T
2355+
#b233::T
2356+
2357+
α1::T
2358+
α2::T
2359+
α3::T
2360+
2361+
beta01::T
2362+
beta02::T
2363+
beta03::T
2364+
2365+
beta11::T
2366+
#beta12::T
2367+
beta13::T
2368+
2369+
#quantile(Normal(),1/6)
2370+
NORMAL_ONESIX_QUANTILE::T
2371+
end
2372+
2373+
2374+
2375+
function W2Ito1ConstantCache(::Type{T}, ::Type{T2}) where {T,T2}
2376+
2377+
a021 = convert(T, 1 // 2)
2378+
a031 = convert(T, -1)
2379+
a032 = convert(T, 2)
2380+
2381+
a121 = convert(T, 1 // 4)
2382+
a131 = convert(T, 1 // 4)
2383+
2384+
b021 = convert(T, (6 - sqrt(6)) / 10)
2385+
b031 = convert(T, (3 + 2 * sqrt(6)) / 5)
2386+
2387+
b121 = convert(T, 1 // 2)
2388+
b131 = convert(T, -1 // 2)
2389+
2390+
b221 = convert(T, 1)
2391+
2392+
α1 = convert(T, 1 // 6)
2393+
α2 = convert(T, 2 // 3)
2394+
α3 = convert(T, 1 // 6)
2395+
2396+
beta01 = convert(T, -1)
2397+
beta02 = convert(T, 1)
2398+
beta03 = convert(T, 1)
2399+
2400+
beta11 = convert(T, 2)
2401+
beta13 = convert(T, -2)
2402+
2403+
NORMAL_ONESIX_QUANTILE = convert(T, -0.9674215661017014)
2404+
2405+
W2Ito1ConstantCache(a021, a031, a032, a121, a131, b021, b031, b121, b131, b221, α1, α2, α3, beta01, beta02, beta03, beta11, beta13, NORMAL_ONESIX_QUANTILE)
2406+
end
2407+
2408+
2409+
function alg_cache(alg::W2Ito1, prob, u, ΔW, ΔZ, p, rate_prototype, noise_rate_prototype, jump_rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, f, t, dt, ::Type{Val{false}}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
2410+
W2Ito1ConstantCache(real(uBottomEltypeNoUnits), real(tTypeNoUnits))
2411+
end
2412+
2413+
@cache struct W2Ito1Cache{uType,randType,tabType,rateNoiseType,rateType,possibleRateType} <: StochasticDiffEqMutableCache
2414+
u::uType
2415+
uprev::uType
2416+
uhat::uType
2417+
2418+
_dW::randType
2419+
_dZ::randType
2420+
chi1::randType
2421+
2422+
tab::tabType
2423+
2424+
g1::rateNoiseType
2425+
g2::rateNoiseType
2426+
g3::rateNoiseType
2427+
2428+
k1::rateType
2429+
k2::rateType
2430+
k3::rateType
2431+
2432+
H02::uType
2433+
H03::uType
2434+
H12::Vector{uType}
2435+
H13::Vector{uType}
2436+
2437+
tmp1::possibleRateType
2438+
tmpg::rateNoiseType
2439+
2440+
tmp::uType
2441+
resids::uType
2442+
2443+
end
2444+
2445+
function alg_cache(alg::W2Ito1, prob, u, ΔW, ΔZ, p, rate_prototype,
2446+
noise_rate_prototype, jump_rate_prototype, ::Type{uEltypeNoUnits},
2447+
::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, f, t, dt, ::Type{Val{true}}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
2448+
if ΔW isa Union{SArray,Number}
2449+
_dW = copy(ΔW)
2450+
_dZ = zeros(eltype(ΔW), 2)
2451+
chi1 = copy(ΔW)
2452+
else
2453+
_dW = zero(ΔW)
2454+
_dZ = zeros(eltype(ΔW), 2)
2455+
chi1 = zero(ΔW)
2456+
end
2457+
m = length(ΔW)
2458+
tab = W2Ito1ConstantCache(real(uBottomEltypeNoUnits), real(tTypeNoUnits))
2459+
g1 = zero(noise_rate_prototype)
2460+
g2 = zero(noise_rate_prototype)
2461+
g3 = zero(noise_rate_prototype)
2462+
k1 = zero(rate_prototype)
2463+
k2 = zero(rate_prototype)
2464+
k3 = zero(rate_prototype)
2465+
2466+
H02 = zero(u)
2467+
H03 = zero(u)
2468+
H12 = Vector{typeof(u)}()
2469+
H13 = Vector{typeof(u)}()
2470+
2471+
for k = 1:m
2472+
push!(H12, zero(u))
2473+
push!(H13, zero(u))
2474+
end
2475+
2476+
tmp1 = zero(rate_prototype)
2477+
tmpg = zero(noise_rate_prototype)
2478+
2479+
uhat = copy(uprev)
2480+
tmp = zero(u)
2481+
resids = zero(u)
2482+
2483+
W2Ito1Cache(u, uprev, uhat, _dW, _dZ, chi1, tab, g1, g2, g3, k1, k2, k3, H02, H03, H12, H13, tmp1, tmpg, tmp, resids)
2484+
end

0 commit comments

Comments
 (0)