Here I have a problem where I’d like a constraint equation to switch once a constraint has been met for one of the auxiliary variables. This is a buildup to a
large, stiff system that benefits greatly in performance from using multistep methods. The code works for the Rodas5 solver, but not for QNDF.
The equation relating the two auxiliary variables is: x_3 = x_1 + x_4
The initial constraint equation is: x_4 = 0.5
Once the value of x_3 reaches 50.0, I would like to switch the constraint equation to x_3 = 50.0, as done in the code.
The value of x_3 for QNDF at the condition appears to reach ~53.
Please let me know if I have constructed something erroneously in the callback or how I may be able to contribute to understanding this and fixing what is happening.
Thank you
using ModelingToolkit
import ModelingToolkit: t_nounits as t, D_nounits as D
using Parameters
using OrdinaryDiffEq
function build_system(; name = :sys)
states = @variables begin
x_1(t) = 1.0
x_2(t) = 1.0
x_3(t) = 1.5, [irreducible=true]
x_4(t) = 0.5, [irreducible=true]
end
params = @parameters begin
α_1 = 0.5
α_2 = 0.5
α_4 = 0.5
mode::Int = 1
end
equations = [
D(x_1) ~ α_1 * x_1 + α_2 * x_2,
D(x_2) ~ α_2 * x_2,
x_3 ~ x_1 + x_4,
0 ~ ((mode - 1) == 0) * (x_4 - α_4) + ((mode - 2) == 0) * (x_3 - 50.0)
]
return ODESystem(equations, t, [states...], params, name=name)
end
sys = build_system()
simp = structural_simplify(sys)
prob_rodas = ODEProblem(simp, ModelingToolkit.get_defaults(simp), (0, 7.0))
function cb_condition(u,t,integ)
return u[ModelingToolkit.variable_index(integ.f.sys, :x_3)] - 50.0
end
function cb_affect!(integ)
integ.ps[:mode] = 2
end
cb = ContinuousCallback(cb_condition, cb_affect!, save_positions=(true, true), interp_points=0)
# solves and the switch in equations is handled expectedly
sol_rodas = solve(prob_rodas, Rodas5(), callback = cb, initializealg=CheckInit())
# set up new problem since mode was changed in previous integrator from callback
prob_qndf = ODEProblem(simp, ModelingToolkit.get_defaults(simp), (0, 7.0))
# reinitialization after affect has been applied is not consistent because x_3 does not equal 50.0
sol_qndf = solve(prob_qndf, QNDF(), callback = cb, initializealg=CheckInit())