I have two coupled nonlinear ODEs where I’m aiming to find x(t) and y(t), defined generally as:
f(x,y,x',y') = 0,
\min(g(x,y,x',y'),h(x,y,x',y')) = 0,
where I expect that I will switch between g<h and g>h at least once at some unknown location in the domain.
Naïvely, I first tried the following (forgive the clunky variable names)
using DifferentialEquations, Plots, Sundials
function test_implicit(res,du,u,p,z)
# unpack for visual clarity
κ, Ḣ = p
θ̃,τ̃ = u
θ̃_z,τ̃_z = du
func_g = Ḣ*θ̃ + κ*θ̃_z ### g(...)
func_h = Ḣ^2*θ̃^2 - τ̃*θ̃_z### h(...)
res[1] = τ̃*θ̃_z - τ̃_z*θ̃ - θ̃^2 ### f(...) = 0
res[2] = min(condA,condB)
end
κh = 2.5#1.8
Ḣ0 = 5.0
p = κ, Ḣ
zmin = 0.
zmax = 3.
prob = DAEProblem(test_implicit,[0.0,0.0], [-1.0,4.0], (zmin, zmax),
p, differential_vars = [true,true], saveat=0.01)
sol = solve(prob1,DFBDF());
plot(reduce(hcat,sol.u)[1,:],sol.t)
plot!(reduce(hcat,sol.u)[2,:],sol.t)
At first, it appears to work – but that’s because the initial parameters \kappa and \dot{H} happen to define a regime where g<h everywhere. If instead we set \kappa=0.5, the integrator doesn’t return anything, as a ``regime change" occurs in the domain. We can confirm this by setting res[2] = func_g
and res[2] = func_h
in separate runs, and see that both run, and neither case blows up.
At this point I’m pretty certain I need to be using ContinuousCallbacks, but all of the examples I found were for explicit, not implicit function definitions. So taking the bouncing ball example code (just to make something work, it won’t do anything meaningful here),
condition(out, du, u, p, z, integrator) = u[1]
function affect!(integrator)
integrator.u[2] = -integrator.u[2]
end
cb = ContinuousCallback(condition, affect!)
I get the error,
MethodError: no method matching test_implicit(::Vector{Float64}, ::Vector{Float64}, ::Tuple{Float64, Float64}, ::Float64)
Closest candidates are:
test_implicit(::Any, ::Any, ::Any, ::Any, ::Any)
It seems I can’t supply enough arguments to my condition function. I admit I don’t really understand the integrator interface, and I also notice that none of the examples with ContinuousCallback use du in the condition
(which I will need to do, as g and h depend on the derivatives), so I hope that is possible.
Thanks in advance!