ModelingToolkit.jl
ModelingToolkit.jl copied to clipboard
Array variable not recognized in registered function call
I was experimenting with a replacement for the SampledData
component from MTKstdlib that leverages array variables. The idea is to call
f ~ interpolate(int_type, int_data, int_time, t)
where int_data, int_time
are symbolic arrays, such that they can be replaced by replacing the parameters. I can't get @register_symbolic
to handle this signature, so I registered manually using
interpolate(int, d::Symbolics.Arr, time, t::Num, args...) = SymbolicUtils.term(interpolate, int, d, time, t, type = Real)
However, the symbolic array variables do not appear to be recognized as present in the system, because the generated code does not unpack them from the parameter object:
julia> prob.f.f.f_oop
RuntimeGeneratedFunction(#=in ModelingToolkit=#, #=using ModelingToolkit=#, :((ˍ₋arg1, ˍ₋arg2, t)->begin
#= /home/fredrikb/.julia/packages/SymbolicUtils/0opve/src/code.jl:373 =#
#= /home/fredrikb/.julia/packages/SymbolicUtils/0opve/src/code.jl:374 =#
#= /home/fredrikb/.julia/packages/SymbolicUtils/0opve/src/code.jl:375 =#
begin
begin
begin
var"f(t)" = (interpolate)(Linear(), int_data, int_time, t)
var"ddx(t)" = (*)(1//10, (+)((+)(var"f(t)", (*)(ˍ₋arg2[2], ˍ₋arg1[2])), (*)(ˍ₋arg2[8], ˍ₋arg1[1])))
begin
#= /home/fredrikb/.julia/packages/SymbolicUtils/0opve/src/code.jl:468 =#
(SymbolicUtils.Code.create_array)(typeof(ˍ₋arg1), nothing, Val{1}(), Val{(2,)}(), ˍ₋arg1[2], var"ddx(t)")
end
end
end
end
end))
and calling solve
thus fails with
julia> sol = solve(prob, Tsit5())
ERROR: UndefVarError: `int_data` not defined
Here's the current implementation of the new SampledData
that reproduces the error
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
using DataInterpolations
using DataInterpolations: AbstractInterpolation
using OrdinaryDiffEq
interpolate(::Type{T}, data::AbstractArray, time, t::AbstractFloat) where T = T(data, time)(t)
# @register_symbolic interpolate(int_type, data, time, t)
# interpolate(int::SymbolicUtils.BasicSymbolic{Interpolation}, args...) = SymbolicUtils.term(interpolate, int, args..., type = Real)
interpolate(int, d::Symbolics.Arr, time, t::Num, args...) = SymbolicUtils.term(interpolate, int, d, time, t, type = Real)
# Base.delete_method.(methods(interpolate))
@mtkmodel SystemWithInput begin
@parameters begin
m=10
k=1000
d=1
int_time[1:11]
int_data[1:11]
# int::AbstractInterpolation
end
@structural_parameters begin
int_type#::Interpolation
end
@variables begin
f(t) = 0
x(t) = 0
dx(t) = 0
ddx(t) = 0
end
@equations begin
f ~ interpolate(int_type, int_data, int_time, t)
# f ~ int(t)
ddx * 10 ~ k * x + d * dx + f
D(x) ~ dx
D(dx) ~ ddx
end
end
tv = 0:10
data = rand(length(tv))
int = LinearInterpolation(data, tv)
# @mtkbuild sys = SystemWithInput(; int)
int_time = tv
int_data = data
int_type = LinearInterpolation
@mtkbuild sys = SystemWithInput(; int_time, int_data, int_type)
prob = ODEProblem(sys, [], (0.0, 10.0))
sol = solve(prob, Tsit5())