Shffl
Shffl

Reputation: 681

Simulating a reflecting boundary SDEProblem

I'm trying to simulate a reflecting boundary. Based on the suggestions found here: Stochastic differential equation with callback in Julia I tried

using DifferentialEquations
using Plots
using Random

m(x,p,t) -> 0
s(x,p,t) -> 1
x0 = 0.1
tspan = (0.0, 2.5)

prob = SDEProblem(m, s, x0, tspan)

condition(u,t,integrator) = true

function affect!(integrator)
    if integrator.u < 0    
        integrator.u = -integrator.u
    end
end
        
cb = DiscreteCallback(condition,affect!;save_positions=(false,false))

Random.seed!(2001)
sol1 = solve(prob, EM(), dt = 0.001, callback = cb)
plot(sol1)
Random.seed!(2021)
sol2 = solve(prob, EM(), dt = 0.01, callback = cb)
plot(sol2)

Which yield sol1 and sol2, respectively. One thing that I noticed is that the "quality" of the reflection is much better when dt is smaller. I suspect that this is because the solver only checks at knots in the interpolation, rather than at every point.

This has implications for adaptive solvers, which choose their own time steps. For example, if I now run the same problem using the SOSRI solver, which is the first recommendation on https://diffeq.sciml.ai/stable/solvers/sde_solve/, I get:

Random.seed!(2021)
sol3 = solve(prob, SOSRI(), callback = cb)
plot(sol3)

sol3 which features arguably poorer quality reflection.

Given that the problem seems to be that the condition is only evaluated at the knots, which is the idea of a DiscreteCallback, I tried one final approach of using ContinuousCallback:

condition(u,t,integrator) = u<0

function affect!(integrator)
    if integrator.u < 0    
        integrator.u = -integrator.u
    end
end
        
cb = ContinuousCallback(condition,affect!;save_positions=(false,false))

Random.seed!(2001)
sol4= solve(prob, EM(), dt = 0.001, callback = cb)
plot(sol4)
Random.seed!(2021)
sol5 = solve(prob, SOSRI(), callback = cb)
plot(sol5)

but this didn't work (I think I'm likely not using ContinuousCallback correctly. The results were sol4 and sol5, which feature arguably no reflection

What is the recommended way to simulate these processes, and are explicit timestepping solvers the only supported ones?

Upvotes: 1

Views: 318

Answers (1)

Chris Rackauckas
Chris Rackauckas

Reputation: 19132

It's really just saving. The way you had it would save every step, which means it would "save, reflect, save". What you really want are just the post-reflection saves:

using StochasticDiffEq
using Plots
using Random

m(x,p,t) = 0
s(x,p,t) = 1
x0 = 0.1
tspan = (0.0, 2.5)

prob = SDEProblem(m, s, x0, tspan)

condition(u,t,integrator) = true

function affect!(integrator)
    if integrator.u < 0
        integrator.u = -integrator.u
    end
end

cb = DiscreteCallback(condition,affect!;save_positions=(false,true))

Random.seed!(2001)
sol1 = solve(prob, EM(), dt = 0.001, callback = cb, save_everystep=false)
plot(sol1)
Random.seed!(2021)
sol2 = solve(prob, EM(), dt = 0.01, callback = cb, save_everystep=false)
plot(sol2)
Random.seed!(2021)
sol2 = solve(prob, SOSRI(), callback = cb, save_everystep=false)
plot(sol2)

enter image description here

Upvotes: 2

Related Questions