Hi All,
Working on a problem that has lead me to the Integrator Interface of DifferentialEquations.jl and have ran into something I can’t seem to work out.
My case requires my to solve my ODEProblem
on a timescale of days, but alter the larger system yearly.
In a normal run of my system I can use PeriodicCallback(action!, 365)
over my known timespan to invoke such changes. This works without issue.
Now, I need to solve my system continuously (by that I mean in a while loop essentially), therefore I’m not aware of tspan[end]
, and wish to use step!(integrator, 365.0, true)
to advance the ODE system. If I call this a couple of times however, I run into:
┌ Warning: dt <= dtmin. Aborting. There is either an error in your model specification or the true solution is unstable.
└ @ DiffEqBase ~/.julia/packages/DiffEqBase/TjqaN/src/integrator_interface.jl:343
Initially, I thought this may be because I wasn’t defining a jacobian for my ODEs, so I’ve used ModelingToolkit.jl to do that for me, but that wasn’t the problem it seems. My system is below for you to take a look at:
using OrdinaryDiffEq
using ModelingToolkit
@parameters t nutrients ib ip r H₁ H₂ H₃ H₄ cb cp prmax ce mp rv cv mv
@variables B(t) P(t) V(t)
@derivatives D' ~ t
FR = B^2 / (B^2 + H₄^2)
eqs = [
D(B) ~ ib + r * (nutrients / (nutrients + H₁)) * B - cb * B^2 - prmax * FR * P,
D(P) ~ ip + ce * prmax * FR * P * (V / (V + H₂)) - mp * P - cp * P^2,
D(V) ~ rv * V - cv * V^2 - mv * (V * B^2 / (H₃^2 + B^2)),
]
sys = ODESystem(eqs)
u0 = [
B => 20.0
P => 1.8
V => 50.0
]
p = [
nutrients => 0.7
ib => 2e-5
ip => 2e-5
r => 7.5e-3
H₁ => 0.5
H₂ => 20
H₃ => 20
H₄ => 15
cb => 7.5e-5
cp => 2.75e-4
prmax => 5e-2
ce => 0.14
mp => 2.25e-3
rv => 7e-3
cv => 6e-5
mv => 7e-3
]
tspan = (0.0, 365.0)
prob = ODEProblem(sys, u0, tspan, p; jac = true, sparse = true)
integrator = init(prob, Tsit5())
Tsit5()
handles this system without issue in my usual case with discrete, yearly callbacks.
So, this particular case will step to t=365.0
without issue, but the second step lands at t=796.9
, whereas I’d like it to land at t=730.0
.
I’ve tried to manually add_tstop!(integrator, 730.0)
, but I suspect this does the same thing that setting the third argument of step!
to true
.
The only workaround I can think of is let the solver step to where it needs, then use the interpolated results in my external functions after the step!
i.e. integrator.sol(730.0)
.
Are there any other options I could try?