How can I use @register_symbolic inside of a function?

I want to solve a PDE-Problem that is a kind of an advection problem with dynamic boundary conditions. The PDE itself is solved with ModelingToolkit and Method of lines. the entire calculation should be called finally from one function in python with juliacall.
For the dynamic BCs i did an interpolation on the measured data and afterwards the function were registered symbolic with e.g. @register_symbolic func(t)
Now my problem is that since finally everything should be called from python inside one function also the several @ register_symbolics need to be put in a function, but that caused errors.
This question is related to Registering a time dependent function inside a function in ModelingToolkit.jl, where @ChrisRackauckas said to do this a callable struct is needed, but I don´t know how I can do this. Any help is greatly appreciated.
Here is a minimal example of my code.


using PythonCall
using DomainSets
using Interpolations
using MethodOfLines
using ModelingToolkit
using OrdinaryDiffEq

function itp(interval::PyArray, function_vals::PyArray, t)
    """ returns interpolation"""
    interpolation = LinearInterpolation(interval["time"], interval[function_vals])
    itpFunction(t) = interpolation(t)
    return itpFunction(t)
end

function PDE_solve(interval_time::Float64,
                    T_fInit::Num,
                    Te_amb::Num,
                    eq_params)

     Dt = Differential(t); Dx = Differential(x);

    eq1 = Dt(T_s(t, x)) ~  - a1_m * (T_s(t, x)- Te_amb) -     a2_m * (T_s(t, x)- Te_amb)^2 - (alpha) * (T_s(t, x) - T_f(t, x)))

    ...second equation definition....

    ic_bc = [T_f(0.0, x) ~ T_fInit]

    domain = [x ∈ Interval(0.0, 1.0),
    t ∈ Interval(0.0, interval_time)]

    @named sys = PDESystem(eqs=[eq1, eq2], bcs=ic_bc, domain=domain, ivs= [t, x], dvs=[T_f(t, x), T_s(t, x)])

       # Determine the number of spatial grid points (Nx)
    Nx = 100
    @time discretization = MOLFiniteDifference([x => Nx], t, advection_scheme = UpwindScheme(),       
    approx_order = 2)
    # Convert the PDE problem into an ODE problem
    @time prob = discretize(sys, discretization)   
    @time sol = solve(prob, alg, abstol=1e-6, reltol=1e-4, saveat=4.0, dense=false

    return sol, discrete_, grid
end


fun(t) = itp(time_index, func_data)
@register_symbolic T_f_in(t)
...more registering of itp functions...

@parameters t, x;
@variables T_f(..), T_s(..)

sol = PDE_solve(data["index"], T_f_in(t), Te_amb(t), parameters)

You can’t. Just update Interpolations.jl itself to register the functions.

@ChrisRackauckas Thank you for your fast reply.
Do you mean my itp(…) function should be updated or what do you mean by updating? How would I do that? Or that my Interpolations.jl package is outdated? I have version 0.14.7, thats the latest I think.

Package status:
[5b8099bc] DomainSets v0.6.7
[a98d9a8b] Interpolations v0.14.7
[94925ecb] MethodOfLines v0.9.4
[961ee093] ModelingToolkit v8.62.0
[1dea7af3] OrdinaryDiffEq v6.53.3
[6099a3de] PythonCall v0.9.13
[0c5d862f] Symbolics v5.5.0

I tried now several things to write my code without the @register_symbolic macro, but nothing worked.
I always end up with the TypeError: non-boolean (Num) used in boolean context, when i call the interpolated functions directly in the PDE_solve(…) function
It would be really cool to have a solution for this problem.
Thanks in advance.

Try replacing Interpolations.jl with DataInterpolations.jl. It has more registrations already.

using DataInterpolations

"""
returns interpolation, which is a callable struct of a single variable
It is already registered as symbolic, so passing a symbolic t as the
argument will return a Num
"""
function itp(interval::PyArray, function_vals::PyArray)
    interpolation = LinearInterpolation(interval["time"], interval[function_vals])
    return interpolation
end

T_f_in = itp(time_index, func_data)

Thank you very much!
Replacing Interpolations.jl with DataInterpolations.jl made my code also working when running inside a function. :slight_smile: