ModelingToolkit.jl and differential equations with step/pulse inputs

Ah, on closer inspection it looks like someone tried that:

Unfortunately, ifelse is not in Base, but Core. This means that it’s a builtin function and cannot be extended, so that idea is moot. However, it is possible to do:

julia> @inline function if_else(condition::Bool, @nospecialize(trueval), @nospecialize(falseval))
           return ifelse(condition, trueval, falseval)
       end
if_else (generic function with 1 method)

julia> ModelingToolkit.@register if_else(x, trueval, falseval)
if_else (generic function with 8 methods)

julia> if_else |> methods
# 8 methods for generic function "if_else":
[1] if_else(condition::Bool, trueval, falseval) in Main at REPL[13]:2
[2] if_else(x::Expression, trueval::Expression, falseval::Expression) in Main
[3] if_else(x::Number, trueval::Expression, falseval::Expression) in Main
[4] if_else(x::Expression, trueval::Number, falseval::Expression) in Main
[5] if_else(x::Number, trueval::Number, falseval::Expression) in Main
[6] if_else(x::Expression, trueval::Expression, falseval::Number) in Main
[7] if_else(x::Number, trueval::Expression, falseval::Number) in Main
[8] if_else(x::Expression, trueval::Number, falseval::Number) in Main

julia> nasty(i) = if_else(i > 1, 1, 0)
nasty (generic function with 1 method)

julia> @variables t
(t,)

julia> nasty(t)
if_else(t > 1, 1, 0)

This should work in a differential equation.

Indeed,

julia> prob = create(nasty)
ODEProblem with uType Array{Float64,1} and tType Float64. In-place: true
timespan: (0.0, 100.0)
u0: [1.0, 0.0]

cc @ChrisRackauckas

Edit: Oh, I forgot about this…functions are eval’ed in ModelingToolkit’s scope, so you would get

var"##MTIIPVar#258"[2] = (ModelingToolkit).:-((ModelingToolkit).if_else((ModelingToolkit).:>(t, 1), 1, 0), (ModelingToolkit).:*((ModelingToolkit).:/(1, m), (ModelingToolkit).:+((ModelingToolkit).:*(c, vel), (ModelingToolkit).:*(k, pos))))

this IR. Note the ModelingToolkit.if_else - you may have to @eval ModelingToolkit using Main: if_else.

1 Like