# Interpolation within ModelingToolkit framework

**URL:** <https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432>\
**Category:** New to Julia\
**Tags:** modelingtoolkit\
**Created:** [April 16, 2021, 6:35pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432 "2021-04-16T18:35:06Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![jairorua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jairorua/32/24109_2.png) [@jairorua](https://discourse.julialang.org/u/jairorua)\
**Post date:** [April 16, 2021, 6:35pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/1 "2021-04-16T18:35:06Z")

</div>

Hello,

Is there a way to interpolate within a ModelingToolkit’s (MTK) component model using the parameters/variables of the model? Interpolations.jl seems to struggle with Num types, and from the example in the documentation ([Composing Ordinary Differential Equations · ModelingToolkit.jl](https://mtk.sciml.ai/stable/tutorials/ode_modeling/#Specifying-a-time-variable-forcing-function-1)) I understand that it is only possible to use pre-interpolated data that is then fed to the model as a time-variable function (?).

To illustrate this idea, I include a simple example using _t_ as coordinate to obtain the interpolated variable.

```nohighlight
using ModelingToolkit
using DifferentialEquations
using Interpolations

# Function to interpolate a time series
function interpolateTimeSeries(t, time, values)

	interpolator = CubicSplineInterpolation(time, values)
	interpolatedValue = interpolator(t)

end

@register interpolateTimeSeries(t, time, values)

# Source to produce the output of a timeseries table
function lookupTable(;name, time, values)
	
	@parameters t
	@variables output(t)

	equations = [output ~ interpolateTimeSeries(t, time, values)]

	ODESystem(equations, t, output, []; name=name)

end

############################## lookupTable source model #################
# Data
time = LinRange(1, 100, 100)
values = randn(100)

# Instantiate lookup-table source model
@named sourceLookupTable = lookupTable(time = time, values = values)
simpSource = structural_simplify(sourceLookupTable)
u0 = [sourceLookupTable =>]

# Define the problem
prob = ODEProblem(simpSource, u0, (0.0, 100.0))
sol = solve(prob, Tsit5())

```

This produces the following error:

```nohighlight
ERROR: LoadError: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
 [1] inbounds_index at $PATH\.julia\packages\Interpolations\qHlUr\src\extrapolation\extrapolation.jl:108 [inlined]
 [2] inbounds_position at $PATH\.julia\packages\Interpolations\qHlUr\src\extrapolation\extrapolation.jl:99 [inlined]
 [3] Extrapolation at $PATH\.julia\packages\Interpolations\qHlUr\src\extrapolation\extrapolation.jl:48 [inlined]
 [4] interpolateTimeSeries(::Num, ::LinRange{Float64}, ::Array{Float64,1}) at $PATH\SourcesSinks.jl:10
 [5] lookupTable(; name::Symbol, time::LinRange{Float64}, values::Array{Float64,1}) at $PATH\SourcesSinks.jl:22
 [6] top-level scope at $PATH\SourcesSinks.jl:34
 [7] include(::String) at .\client.jl:457
 [8] top-level scope at REPL[7]:1
in expression starting at $PATH\SourcesSinks.jl:34

```

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [April 16, 2021, 7:30pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/2 "2021-04-16T19:30:56Z")

</div>

> **[GitHub - SciML/DataInterpolations.jl: A library of data interpolation and...](https://github.com/SciML/DataInterpolations.jl)**
>
> A library of data interpolation and smoothing functions - GitHub - SciML/DataInterpolations.jl: A library of data interpolation and smoothing functions

That works IIRC? But even if it doesn’t, you can just `@register` your function.

---

<div class="post-metadata">

**Author:** ![jairorua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jairorua/32/24109_2.png) [@jairorua](https://discourse.julialang.org/u/jairorua)\
**Post date:** [April 19, 2021, 12:14pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/4 "2021-04-19T12:14:08Z")

</div>

Thanks for the quick reply @ChrisRackauckas. I did `@register` my function in the previous example (maybe not correctly?).

I also tried DataInterpolations.jl as you suggested, both with and without an external registered function, but I get the same error as in the example included in the first post.

Without external function

```julia
using ModelingToolkit
using DifferentialEquations
using Interpolations
using DataInterpolations

function lookupTable(;name, time, values)
	
	@parameters t
	@variables output(t)
 	interpolator = CubicSpline(values, time)

	equations = [output - interpolator(t)]

	ODESystem(equations, t, [output], []; name=name)

end

# Data
time = LinRange(1, 100, 100)
values = randn(100)

# Instantiate lookup-table source model
@named sourceLookupTable = lookupTable(time = time, values = values)
simpSource = structural_simplify(sourceLookupTable)

```

With external registered function

```julia
# Function to interpolate a time series
function interpolateTimeSeries(t, time, values)

	interpolator = CubicSpline(values, time)
	interpolatedValue = interpolator(t)

end

@register interpolateTimeSeries(t, time, values)

# Source to produce the output of a timeseries table
function lookupTable(;name, time, values)
	
	@parameters t
	@variables output(t)

	equations = [output ~ interpolateTimeSeries(t, time, values)]

	ODESystem(equations, t, [output], []; name=name)

end

############################## lookupTable source model #################
# Data
time = LinRange(1, 100, 100)
values = randn(100)

# Instantiate lookup-table source model
@named sourceLookupTable = lookupTable(time = time, values = values)
#@named sourceLookupTable = lookupTable()
simpSource = structural_simplify(sourceLookupTable)

```

In both cases, and the first example using Interpolations.jl, I get the same error:

```julia
ERROR: LoadError: TypeError: non-boolean (Num) used in boolean context

```

These errors originate from the use of `@parameters ` as an input during the interpolation, e.g. `interpolator(t)` or `interpolateTimeSeries(t, time, values)` .

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [April 22, 2021, 7:59am UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/5 "2021-04-22T07:59:44Z")

</div>

You just forgot to specify the non-symbolic parts arguments. The fix is:

```julia
@register interpolateTimeSeries(t, time::AbstractVector, values::AbstractVector)

```

---

<div class="post-metadata">

**Author:** ![jairorua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jairorua/32/24109_2.png) [@jairorua](https://discourse.julialang.org/u/jairorua)\
**Post date:** [April 22, 2021, 8:07pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/6 "2021-04-22T20:07:56Z")

</div>

Many thanks for your help @ChrisRackauckas. The work of the MKT team in this package is fantastic.

Just some constructive feedback. I feel that the `@register` functionality might be useful to many people. However, a quick search of `@register` in the search docs bar only leads to Composing Ordinary Differential Equations - Specifying a time-variable forcing function, where it says:

" MTK allows to “register” arbitrary Julia functions, which are excluded from symbolic transformations but are just used as-is. So, you could, for example, interpolate a given time series using [DataInterpolations.jl](https://github.com/PumasAI/DataInterpolations.jl)."

From this description, at least for a new user of MTK like me, it is a bit difficult to infer that I can specify some variables as non-symbolic and the remaining as symbolic. I took the liberty of using the example included in the documentation and include a function that interpolates some time-series data with a mix of non-symbolic and symbolic inputs. Here is the code:

```julia
using ModelingToolkit
using DifferentialEquations
using DataInterpolations 

@parameters tau
@variables t, x(t), f(t)
D = Differential(t)

function f_interpolate(t, table_t, table_u)

	interpolator = QuadraticInterpolation(table_u, table_t)
	output = interpolator(t)

end

@register f_interpolate(t, table_t::AbstractVector, table_u::AbstractVector)

table_t, table_u = LinRange(0.5, 10.5, 10), randn(10)

@named fol_external_f = ODESystem([f ~ f_interpolate(t, table_t, table_u), D(x) ~ (f - x) / tau])
prob = ODEProblem(structural_simplify(fol_external_f), [x => 0.0], (0.0, 10.0), [tau => 0.75])

sol = solve(prob)
plot(sol, vars=[x, f])
scatter!(table_t, table_u)

```

![Capture3](https://global.discourse-cdn.com/julialang/original/3X/4/7/47f1eb12dada2572274456c3a3e7d7d1af401a03.png)

If you feel this may complement the existing documentation, feel free to add it. Otherwise it is left here so it may help future new users.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [April 22, 2021, 9:32pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/7 "2021-04-22T21:32:02Z")

</div>

That would be a good tutorial: Mixing Symbolic Models with Data, or something.

---

<div class="post-metadata">

**Author:** ![lstagner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lstagner/32/448_2.png) [@lstagner](https://discourse.julialang.org/u/lstagner)\
**Post date:** [April 23, 2021, 2:06am UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/8 "2021-04-23T02:06:30Z")

</div>

This is just a performance tip but I would have `f_interpolate` return the interpolating function. Right now every time `f_interpolate` is called it constructs a interpolation object. I would rewrite it as follows

```julia
f_interpolate = QuadraticInterpolation(table_u, table_t)
@register f_interpolate(t)

```

Assuming `@register` accepts DataInterpolations

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [April 23, 2021, 4:34am UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/9 "2021-04-23T04:34:40Z")

</div>

> [@lstagner](#):
>
> Assuming `@register` accepts DataInterpolations

It accepts any Julia function.

---

<div class="post-metadata">

**Author:** ![jairorua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jairorua/32/24109_2.png) [@jairorua](https://discourse.julialang.org/u/jairorua)\
**Post date:** [April 23, 2021, 6:14am UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/10 "2021-04-23T06:14:36Z")

</div>

Agree. Thanks for the remark. The code above can become inefficient when one considers arrays.

---

<div class="post-metadata">

**Author:** ![astrobc1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/astrobc1/32/45632_2.png) [@astrobc1](https://discourse.julialang.org/u/astrobc1)\
**Post date:** [April 22, 2022, 7:51pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/11 "2022-04-22T19:51:13Z")

</div>

I tried some of the above answers, but I too am running into errors trying to include CubicSpline interpolation from DataInterpolations.jl in my loss function. In the example below I am interpolating the model onto the same grid just as a test. Thank you in advance!

```julia
julia> using ModelingToolkit, DataInterpolations, Polynomials

julia> @variables c0 c1
2-element Vector{Num}:
 c0
 c1

julia> @parameters x[1:10] data[1:10]
2-element Vector{Symbolics.Arr{Num, 1}}:
 x[1:10]
 data[1:10]

julia> function f_interpolate(t, table_t, table_u)

               interpolator = CubicSpline(table_u, table_t)
               output = interpolator.(t)

       end
f_interpolate (generic function with 1 method)

julia> rms(x,y) = sqrt(sum((x .- y).^2) / length(x))
rms (generic function with 1 method)

julia> typeof(x)
Symbolics.Arr{Num, 1}

julia> @register f_interpolate(t::Vector{Symbolics.Arr{Num, 1}}, table_t::Vector{Symbolics.Arr{Num, 1}}, table_u::Vector{Symbolics.Arr{Num, 1}})

julia> loss = rms(data, f_interpolate(x, x, Polynomial([c0, c1]).(x)))
ERROR: MethodError: no constructors have been defined for Any
Stacktrace:
 [1] _broadcast_getindex_evalf
   @ ./broadcast.jl:670 [inlined]
 [2] _broadcast_getindex
   @ ./broadcast.jl:643 [inlined]
 [3] getindex
   @ ./broadcast.jl:597 [inlined]
 [4] copy
   @ ./broadcast.jl:899 [inlined]
 [5] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, Type{Any}, Tuple{Vector{Term{Any, Nothing}}}})
   @ Base.Broadcast ./broadcast.jl:860
 [6] munge_data(u::Symbolics.Arr{Any, 1}, t::Symbolics.Arr{Num, 1})
   @ DataInterpolations ~/.julia/packages/DataInterpolations/HJsu4/src/interpolation_utils.jl:44
 [7] CubicSpline(u::Symbolics.Arr{Any, 1}, t::Symbolics.Arr{Num, 1})
   @ DataInterpolations ~/.julia/packages/DataInterpolations/HJsu4/src/interpolation_caches.jl:161
 [8] f_interpolate(t::Symbolics.Arr{Num, 1}, table_t::Symbolics.Arr{Num, 1}, table_u::Symbolics.Arr{Any, 1})
   @ Main ./REPL[4]:3
 [9] top-level scope
   @ REPL[9]:1

julia> 

```

---

<div class="post-metadata">

**Author:** ![mloizzo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mloizzo/32/45932_2.png) [@mloizzo](https://discourse.julialang.org/u/mloizzo)\
**Post date:** [January 17, 2023, 9:43am UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/12 "2023-01-17T09:43:19Z")

</div>

Hi,  
I’m getting the same error when I try to interpolate 2 (or more) dimensional data even if I register the function.

Hereafter a simplified version of my code for a 4D interpolation.

```julia
using ModelingToolkit
using Interpolations

@variables t

function interpolateMatrix(X1,X2,X3,X4,Data,bp1,bp2,bp3,bp4)

    interpolator = linear_interpolation((bp1, bp2, bp3, bp4), Data)
    output = interpolator(X1, X2, X3, X4)

end

@register interpolateMatrix(X1,X2,X3,X4,Data::AbstractVector,bp1::AbstractVector,bp2::AbstractVector,bp3::AbstractVector,bp4::AbstractVector)

function lookup_table_4D(Data,bp1,bp2,bp3,bp4;name)

    @variables X1(t), X2(t), X3(t), X4(t), output(t)

    eqs = [output ~ interpolateMatrix(X1,X2,X3,X4,Data,bp1,bp2,bp3,bp4)]

    ODESystem(eqs;name)
    
end

A = randn(9,9,9,4)
X1 = 1:9
X2 = 1:9
X3 = 1:9
X4 = 1:4

@named matA = lookup_table_4D(A, X1, X2, X3, X4)

```

The error I get is

```julia
ERROR: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
 [1] inbounds_index
   @ $PATH\.julia\packages\Interpolations\nDwIa\src\extrapolation\extrapolation.jl:111 [inlined]
 [2] inbounds_position
   @ $PATH\.julia\packages\Interpolations\nDwIa\src\extrapolation\extrapolation.jl:102 [inlined]
 [3] Extrapolation
   @ $PATH\.julia\packages\Interpolations\nDwIa\src\extrapolation\extrapolation.jl:48 [inlined]
 [4] interpolateMatrix(X1::Num, X2::Num, X3::Num, X4::Num, Data::Array{Float64, 4}, bp1::UnitRange{Int64}, bp2::UnitRange{Int64}, bp3::UnitRange{Int64}, bp4::UnitRange{Int64})
   @ Main $PATH\4D_lut.jl:10
 [5] lookup_table_4D(Data::Array{Float64, 4}, bp1::UnitRange{Int64}, bp2::UnitRange{Int64}, bp3::UnitRange{Int64}, bp4::UnitRange{Int64}; name::Symbol)
   @ Main$PATH\4D_lut.jl:21
 [6] top-level scope
   @ $PATH\.julia\packages\ModelingToolkit\oE1IR\src\systems\abstractsystem.jl:923

```

Any idea on how to solve this problem ?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 17, 2023, 3:23pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/13 "2023-01-17T15:23:47Z")

</div>

Can you open an issue for that? DataInterpolations.jl should be fine, it has overloads and such. Interpolations.jl, not so much. It might need a different registration given it’s weird constructors.

---

<div class="post-metadata">

**Author:** ![mikeonly](https://avatars.discourse-cdn.com/v4/letter/m/67e7ee/32.png) [@mikeonly](https://discourse.julialang.org/u/mikeonly)\
**Post date:** [January 18, 2023, 12:34pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/14 "2023-01-18T12:34:28Z")

</div>

I have encountered the same problem just yesterday also using Interpolations.jl, but I have overcome it by a combination of `extrapolate` and `interpolate` functions, together with `@register`, as it seemed that the error above indicates that there is a check on whether a symbol is within the bounds of the interpolating function. However, I have a complete beginner with the ModelingToolkit and Julia and I am not sure if my solution is correct.

I would also be willing to follow-up and raise the issue for that, should it be done at [GitHub - JuliaMath/Interpolations.jl: Fast, continuous interpolation of discrete datasets in Julia](https://github.com/JuliaMath/Interpolations.jl)?

---

<div class="post-metadata">

**Author:** ![mloizzo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mloizzo/32/45932_2.png) [@mloizzo](https://discourse.julialang.org/u/mloizzo)\
**Post date:** [February 8, 2023, 2:53pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/15 "2023-02-08T14:53:09Z")

</div>

The problem was that `Data` isn’t a vector. The correct syntax for the register is

```julia
@register interpolateMatrix(X1,X2,X3,X4,Data::AbstractArray,bp1::AbstractVector,bp2::AbstractVector,bp3::AbstractVector,bp4::AbstractVector)

```

The solution here : [#2039](https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FSciML%2FModelingToolkit.jl%2Fissues%2F2039&data=05%7C01%7Cmichele.loizzo%40skf.com%7Cba66901b997e4366dcde08dafb66f406%7C41875f2b33e8467092a8f643afbb243a%7C0%7C0%7C638098716841088961%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=9ZR1EIVeD%2BLDSzJzbvd%2BrBrq9HO5skQp%2FTitZiSJ1O4%3D&reserved=0)

---

<div class="post-metadata">

**Author:** ![mloizzo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mloizzo/32/45932_2.png) [@mloizzo](https://discourse.julialang.org/u/mloizzo)\
**Post date:** [February 8, 2023, 2:58pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/16 "2023-02-08T14:58:17Z")

</div>

However, I get the same error when `X4` is a vector instead of a scalar. I have tried to give the type `::Vector{Float64}` or `::AbstractVector` for this variable but none of them is working.

Here is the code:

```julia
using ModelingToolkit
using Interpolations
using Symbolics: scalarize

@variables t
δ = Differential(t)

function interpolateMatrix(X1,X2,X3,X4,Data,bp1,bp2,bp3,bp4)

    interpolator = linear_interpolation((bp1, bp2, bp3, bp4), Data)
    output = interpolator(X1, X2, X3, X4)
    
end

@register interpolateMatrix(X1,X2,X3,X4::Vector{Float64},Data::AbstractArray,bp1::AbstractVector,bp2::AbstractVector,bp3::AbstractVector,bp4::AbstractVector)::Vector{Float64}

function lookup_table_4D(Data,bp1,bp2,bp3,bp4;name)

    @parameters X4 = 1:4
    @variables X1(t) X2(t) X3(t) output(t)[1:4]
    
    eqs = [scalarize(output .~ interpolateMatrix(X1,X2,X3,X4,Data,bp1,bp2,bp3,bp4));]

    ODESystem(eqs;name)
end

A = randn(2,2,2,4)
bp1 = 1:2
bp2 = 1:2
bp3 = 1:2
bp4 = 1:4

@named matA = lookup_table_4D(A, bp1, bp2, bp3, bp4)

```

I have also noticed that the registered function `interpolationMatrix` has 19683 methods.

```julia
julia> interpolateMatrix
interpolateMatrix (generic function with 19683 methods)

```

I suppose that’s because the register generates a method for each combination of inputs’ type. However, if the types of inputs and parameters are known and fixed, only one of these methods is useful (ex: `X#::Vector{Float64}` ,`Data::Array{Float64, 4}` and `bp#::Vector{Float64}`). Is there a way to register only the required method?

---

<div class="post-metadata">

**Author:** ![HamzaKh99](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hamzakh99/32/49279_2.png) [@HamzaKh99](https://discourse.julialang.org/u/HamzaKh99)\
**Post date:** [April 27, 2023, 9:46am UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/17 "2023-04-27T09:46:16Z")

</div>

I tried some of the codes above and they work, but the performance and number of allocations are very high how can I reduce it?

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [May 1, 2023, 4:41pm UTC](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/18 "2023-05-01T16:41:51Z")

</div>

Hard to say without seeing your code, but [this](https://discourse.julialang.org/t/interpolation-within-modelingtoolkit-framework/59432/8) comment above is good advice.
