-
-
Notifications
You must be signed in to change notification settings - Fork 240
Description
I want to evaluate a spline and its derivative(s) through an ODESystem. This works beautifully:
using Test
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
using DifferentialEquations
using DataInterpolations
ts = 0.0:0.1:1.0
Fspline_t² = CubicSpline(ts .^ 2, ts) # spline for F(t) = t²
@variables F(t) F′(t)
@named sys = ODESystem([
F ~ Fspline_t²(t)
F′ ~ D(F)
], t)
ssys = structural_simplify(sys)
prob = ODEProblem(ssys, [], (0.0, 1.0), [])
sol = solve(prob)
@test sol(0.5, idxs=F′) ≈ 2 * 0.5 # F′(t) = 2tHowever, to pass different splines, I want to make it a parameter:
using Test
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
using DifferentialEquations
using DataInterpolations
ts = 0.0:0.1:1.0
Fspline_t² = CubicSpline(ts .^ 2, ts) # spline for F(t) = t²
@parameters Fspline::CubicSpline = Fspline_t²
@variables F(t) F′(t)
@named sys = ODESystem([
F ~ Fspline(t)
F′ ~ D(F)
], t)
ssys = structural_simplify(sys)
prob = ODEProblem(ssys, [], (0.0, 1.0), [])
sol = solve(prob)
@test sol(0.5, idxs=F′) ≈ 2 * 0.5 # F′(t) = 2tThis fails with ERROR: LoadError: Sym Fspline is not callable. Use @syms Fspline(var1, var2,...) to create it as a callable. Accordingly, I tried to declare @parameters Fspline(t)::CubicSpline = Fspline_t² instead, but it does not help. Is there a bug here?
I have worked around half the problem by evaluating the spline like F ~ spleval(x, Fspline) through a proxy function
@register_symbolic spleval(x, spline::CubicSpline)
spleval(x, spline) = spline(x)This works for F. But it does not work for F′, which then evaluates to e.g. Differential(t)(1.0). Also, it feels unnecessarily complicated, because I believe these derivative rules are already defined in DataInterpolations.jl.
I really wish that the second example worked like the first, without the complicating workarounds. Is that possible?
Thanks!