Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple callbacks result in apparent solver hang #600

Open
klaff opened this issue May 6, 2020 · 4 comments
Open

Multiple callbacks result in apparent solver hang #600

klaff opened this issue May 6, 2020 · 4 comments

Comments

@klaff
Copy link

klaff commented May 6, 2020

MWE:

using DifferentialEquations

function usode!(du,u,p,t)
    C1 = 1.63e-9
    RS = 790.0
    C2 = 3.3e-9
    C0 = 0.3e-9
    L1 = 1e-3
    L2 = 82e-3
    CM = 4e-12
    LM = 8.0
    RM = 7500.0
    VC1, VC2, VC0, VCM, IL1, IL2, ILM, Vp = u
    fv, VAmag = p
    VA = VAmag*sinpi(2*Vp)
    du[1] = 1/C1*IL1
    du[2] = -1/C2*IL1
    du[3] = 1/C0*(IL1-IL2-ILM)
    du[4] = 1/CM*ILM
    du[5] = 1/L1*(VA-VC1-VC0-VC2-IL1*RS)
    du[6] = 1/L2*VC0
    du[7] = 1/LM*(VC0-VCM-ILM*RM)
    du[8] = fv
end

mutable struct Controller
    f::Float64
end
function(c::Controller)(integrator)
    integrator.p[1] = c.f
    if c.f < 30000.0
        c.f += 15.0
    end
    println(join([integrator.t, c.f, integrator.p[3], integrator.p[4]], ", "))
end

condVzero(u,t,integrator) = integrator.p[2]*sinpi(2*u[8])-u[1] # Vmod
function affectVzero!(integrator)
    integrator.p[3]=integrator.t
end
cbVz = ContinuousCallback(condVzero, affectVzero!, nothing)
condIzero(u,t,integrator) = u[5]
function affectIzero!(integrator)
    integrator.p[4]=integrator.t
end
cbIz = ContinuousCallback(condIzero, affectIzero!, nothing)

function sim()
    p = [0.0, 100.0, 0.0, 0.0]
    cb1 = PeriodicCallback(Controller(27000.0),0.005)
    cbs = CallbackSet(cb1,cbVz,cbIz)
    #cbs = CallbackSet(cb1,cbVz)
    #cbs = CallbackSet(cb1,cbIz)
    u0 = [0.0,0.0,0.0,0.0, 0.0,0.0,0.0, 0.0]
    tspan = [0.0, 0.5]
    prob = ODEProblem(usode!,u0,tspan,p)
    @time sol = solve(prob,Tsit5(), callback=cbs, reltol=1e-8, abstol=1e-8, dense=false, maxiters=10_000_000)
    sol
end

sol = sim()

Looking at function sim, there are three lines that begin with cbs = CallbackSet. If I run as is, it stalls after 0.2 s (simulation time in print statements) and eventually dies wanting larger maxiters… If I instead use either of the commented cbs = lines, each only having one of the two ContinuousCallbacks, then it succeeds.

@klaff
Copy link
Author

klaff commented May 6, 2020

Substituting Trapezoid() for Tsit5() gives an interesting error message rather than failing silently:

0.20500000000000002, 27630.0, 0.20498183392116934, 0.20498234571777418
┌ Warning: dt <= dtmin. Aborting. There is either an error in your model specification or the true solution is unstable.
└ @ DiffEqBase C:\Users\klaff\.julia\packages\DiffEqBase\XoVg5\src\integrator_interface.jl:343

The println output indicates that there were several very closely spaced callbacks just prior to the failure. I suspect the closely spaced callbacks are significant because I see a similar pattern in a non-NWE version.

@klaff
Copy link
Author

klaff commented May 6, 2020

Using VectorContinuousCallback instead of two separate ContinuousCallbacks as follows appears to work:

using DifferentialEquations

function usode!(du,u,p,t)
    C1 = 1.63e-9
    RS = 790.0
    C2 = 3.3e-9
    C0 = 0.3e-9
    L1 = 1e-3
    L2 = 82e-3
    CM = 4e-12
    LM = 8.0
    RM = 7500.0
    VC1, VC2, VC0, VCM, IL1, IL2, ILM, Vp = u
    fv, VAmag = p
    VA = VAmag*sinpi(2*Vp)
    du[1] = 1/C1*IL1
    du[2] = -1/C2*IL1
    du[3] = 1/C0*(IL1-IL2-ILM)
    du[4] = 1/CM*ILM
    du[5] = 1/L1*(VA-VC1-VC0-VC2-IL1*RS)
    du[6] = 1/L2*VC0
    du[7] = 1/LM*(VC0-VCM-ILM*RM)
    du[8] = fv
end

mutable struct Controller
    f::Float64
end
function(c::Controller)(integrator)
    integrator.p[1] = c.f
    if c.f < 30000.0
        c.f += 15.0
    end
    println(join([integrator.t, c.f, integrator.p[3], integrator.p[4]], ", "))
end

condVzero(u,t,integrator) = integrator.p[2]*sinpi(2*u[8])-u[1] # Vmod
function affectVzero!(integrator)
    integrator.p[3]=integrator.t
end
cbVz = ContinuousCallback(condVzero, affectVzero!, nothing)
condIzero(u,t,integrator) = u[5]
function affectIzero!(integrator)
    integrator.p[4]=integrator.t
end
cbIz = ContinuousCallback(condIzero, affectIzero!, nothing)

function condition(out,u,t,integrator)
    out[1] =  integrator.p[2]*sinpi(2*u[8])-u[1]
    out[2] =  u[5]
end
function affect!(integrator, idx)
    if idx == 1
        integrator.p[3]=integrator.t
    elseif idx ==2
        integrator.p[4]=integrator.t
    end
end
vccb = VectorContinuousCallback(condition,affect!,2)

function sim()
    p = [0.0, 100.0, 0.0, 0.0]
    cb1 = PeriodicCallback(Controller(27000.0),0.005)
    #cbs = CallbackSet(cb1,cbVz,cbIz)
    cbs = CallbackSet(cb1,vccb)
    #cbs = CallbackSet(cb1,cbVz)
    #cbs = CallbackSet(cb1,cbIz)
    u0 = [0.0,0.0,0.0,0.0, 0.0,0.0,0.0, 0.0]
    tspan = [0.0, 0.5]
    prob = ODEProblem(usode!,u0,tspan,p)
    @time sol = solve(prob,Tsit5(), callback=cbs, reltol=1e-8, abstol=1e-8, dense=false, maxiters=10_000_000)
    sol
end

sol = sim()

@kanav99
Copy link

kanav99 commented May 7, 2020

Nice that it worked for you, but still we need to fix that, I am busy till Tuesday, I will get back to the issue once I am free.

@klaff
Copy link
Author

klaff commented May 7, 2020

Nice that it worked for you, but still we need to fix that, I am busy till Tuesday, I will get back to the issue once I am free.

I try to leave breadcrumbs in case someone else has the same issue and also let you know I'm not dead in the water so you can prioritize appropriately.

As a note of appreciation - this is an amazing library - I'm beating on it pretty hard and in the process showing coworkers what is possible. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants