-
-
Notifications
You must be signed in to change notification settings - Fork 232
Description
How can one implement multimode systems that also include continuous events effectively❓
I would like to create a multimode system, where the derivative of some unknowns depend on the (discrete) mode
, and where the mode
is changed by continuous events.
- Firstly, should
mode
be a time-dependent parameter, or a variable/unknown❓
On the one hand, if mode
is a time-dependent parameter, then according to the Event Handling and Callback Functions tutorial it needs to be marked as a discrete parameter within the continuous event. However, using the @continuous_events
macro does not seem to set mode
as a discrete parameter, and it also does not seem to accept SymbolicContinuousCallback()
.
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
@mtkmodel MultiModeSystem begin
@parameters begin
mode(t)::Bool = false
end
@variables begin
# Depends on "mode"
x(t) = 0.0
# Event triggerer var. - "mode" depends on it
v(t) = 0.0
d_v(t) = 10.0
end
@equations begin
# Depends on "mode"
D(x) ~ mode * 1.0
# Event triggerer var. - "mode" depends on it
D(v) ~ d_v
D(d_v) ~ 0.0
end
@continuous_events begin
[v ~ 10.0] => [v ~ 0.0, d_v ~ -10.0, mode ~ true]
[v ~ -10.0] => [v ~ 0.0, d_v ~ 10.0, mode ~ false]
end
end
@mtkcompile sys = MultiModeSystem()
prob = ODEProblem(sys, [], (0, 3.0))
using OrdinaryDiffEq: solve
sol = solve(prob)
# Incorrect solution because "x" does not change!
Using SymbolicContinuousCallback()
within @continuous_events
results in the following error during system definition:
ERROR: LoadError: Malformed continuous event ModelingToolkit.SymbolicContinuousCallback([v ~ 10.0] => [v ~ 0.0, d_v ~ -10.0, mode ~ true], discrete_parameters = [mode]).
Stacktrace:
[1] error(s::String)
@ Base .\error.jl:35
[2] parse_continuous_events!(c_evts::Vector{Any}, dict::Dict{Symbol, Any}, body::Expr)
@ ModelingToolkit ..\.julia\packages\ModelingToolkit\hlGut\src\systems\model_parsing.jl:1164
[3] parse_model!(exprs::Vector{…}, comps::Vector{…}, ext::Vector{…}, eqs::Vector{…}, icon::Base.RefValue{…}, vs::Vector{…}, ps::Vector{…}, sps::Vector{…}, c_evts::Vector{…}, d_evts::Vector{…}, cons::Vector{…}, costs::Vector{…}, dict::Dict{…}, mod::Module, arg::Expr, kwargs::OrderedCollections.OrderedSet{…}, where_types::Vector{…})
@ ModelingToolkit ..\.julia\packages\ModelingToolkit\hlGut\src\systems\model_parsing.jl:667
[4] _model_macro(mod::Module, fullname::Symbol, expr::Expr, isconnector::Bool)
@ ModelingToolkit ..\.julia\packages\ModelingToolkit\hlGut\src\systems\model_parsing.jl:82
[5] var"@mtkmodel"(__source__::LineNumberNode, __module__::Module, fullname::Union{Expr, Symbol}, body::Any)
@ ModelingToolkit ..\.julia\packages\ModelingToolkit\hlGut\src\systems\model_parsing.jl:33
in expression starting at ..\Coding\ModularEnergySystemSim.jl\dev\features\dev_degmin_calc_with_events.jl:7
On the other hand, if mode
is a variable/unknown an additional equation needs to be added. This could be D(mode) ~ 0
, however D()
unsurprisingly only supports continuous variable/unknown.
-
During the previous question, I assumed that
mode
is discrete (is of type bool or int). Would it help if it was treated as a continuous parameter or variable/unknown❓ -
If so, how could one implement the "mode conditions" within equations robustly❓
For example, ifmode
is a variabe/unknown a tiny numerical errorifelse(mode == 1.0, cond_true_eq, cond_false_eq)
could still "trigger" the use of "cond_false_eq" equations even ifD(mode) ~ 0
andmode
is set to 1.0 by a continuous event. (In production code I also would like to avoid the use ofisapprox()
.) Whereas, ifmode
is a continuous parameter, then the continuous events cannot be defined with the@continuous_events
macro.
I also think that a tutorial on multimode systems (using events) could be a great addition to the documentation and I would be happy to help with that if we can find an effective solution.