| 
 | 1 | +# Callable parameters and interpolating data  | 
 | 2 | + | 
 | 3 | +ModelingToolkit.jl allows creating parameters that represent functions to be called. This  | 
 | 4 | +is especially useful for including interpolants and/or lookup tables inside ODEs. In this  | 
 | 5 | +tutorial we will create an `ODESystem` which employs callable parameters to interpolate data  | 
 | 6 | +inside an ODE and go over the various syntax options and their implications.  | 
 | 7 | + | 
 | 8 | +## Callable parameter syntax  | 
 | 9 | + | 
 | 10 | +The syntax for callable parameters declared via `@parameters` must be one of the following  | 
 | 11 | + | 
 | 12 | +1. `(fn::FType)(..)`  | 
 | 13 | +2. `fn(::argType1, ::argType2, ...)`  | 
 | 14 | + | 
 | 15 | +In the first case, the parameter is callable with any number/combination of arguments, and  | 
 | 16 | +has a type of `FType` (the callable must be a subtype of `FType`). In the second case,  | 
 | 17 | +the parameter is callable with as many arguments as declared, and all must match the  | 
 | 18 | +declared types.  | 
 | 19 | + | 
 | 20 | +By default, the return type of the callable symbolic is inferred to be `Real`. To change  | 
 | 21 | +this, a `::retType` annotation can be added at the end.  | 
 | 22 | + | 
 | 23 | +To declare a function that returns an array of values, the same array syntax can be used  | 
 | 24 | +as for normal variables:  | 
 | 25 | + | 
 | 26 | +```julia  | 
 | 27 | +@parameters (foo::FType)(..)[1:3]::retType  | 
 | 28 | +@parameters foo(::argType1, ::argType2)[1:3]::retType  | 
 | 29 | +```  | 
 | 30 | + | 
 | 31 | +`retType` here is the `eltype` of the retured array.  | 
 | 32 | + | 
 | 33 | +## Storage of callable parameters  | 
 | 34 | + | 
 | 35 | +Callable parameters declared with the `::FType` syntax will be stored in a `Vector{FType}`.  | 
 | 36 | +Thus, if `FType` is non-concrete, the buffer will also be non-concrete. This is sometimes  | 
 | 37 | +necessary to allow the value of the callable to be switched out for a different type without  | 
 | 38 | +rebuilding the model. Typically this syntax is preferable when `FType` is concrete or  | 
 | 39 | +a small union.  | 
 | 40 | + | 
 | 41 | +Callable parameters declared with the `::argType1, ...` syntax will be stored in a  | 
 | 42 | +`Vector{FunctionWrappers.FunctionWrapper{retType, Tuple{argType1, ...}}}`. This suffers  | 
 | 43 | +the small overhead of a `FunctionWrapper` and restricts the signature of the callable,  | 
 | 44 | +symbolic, but allows storing the parameter in a type-stable manner and swapping it out.  | 
 | 45 | +This is preferable when the values that the callable can take do not share a common  | 
 | 46 | +subtype. For example, when a callable can represent the activation of a neural network  | 
 | 47 | +and can be `tanh`, `sigmoid`, etc. which have a common ancestor of `Function`.  | 
 | 48 | + | 
 | 49 | +If both `::FType` and `::argType`s are specified, `::FType` takes priority. For example,  | 
 | 50 | + | 
 | 51 | +```julia  | 
 | 52 | +@parameters (p::LinearInterpolation)(::Real)  | 
 | 53 | +```  | 
 | 54 | + | 
 | 55 | +`p` will be stored in a `Vector{LinearInterpolation}`. If `::LinearInterpolation` was not  | 
 | 56 | +specified, it would be stored in a `Vector{FunctionWrapper{Real, Tuple{Real}}}`.  | 
 | 57 | + | 
 | 58 | +## Example using interpolations  | 
 | 59 | + | 
 | 60 | +```@example callable  | 
 | 61 | +using ModelingToolkit  | 
 | 62 | +using OrdinaryDiffEq  | 
 | 63 | +using DataInterpolations  | 
 | 64 | +using ModelingToolkit: t_nounits as t, D_nounits as D  | 
 | 65 | +
  | 
 | 66 | +ts = collect(0.0:0.1:10.0)  | 
 | 67 | +spline = LinearInterpolation(ts .^ 2, ts)  | 
 | 68 | +Tspline = typeof(spline)  | 
 | 69 | +@variables x(t)  | 
 | 70 | +@parameters (interp::Tspline)(..)  | 
 | 71 | +
  | 
 | 72 | +@mtkbuild sys = ODESystem(D(x) ~ interp(t), t)  | 
 | 73 | +```  | 
 | 74 | + | 
 | 75 | +The derivative of `x` is obtained via an interpolation from DataInterpolations.jl. Note  | 
 | 76 | +the parameter syntax. The `(..)` marks the parameter as callable. `(interp::Tspline)`  | 
 | 77 | +indicates that the parameter is of type `Tspline`.  | 
 | 78 | + | 
 | 79 | +```@example callable  | 
 | 80 | +prob = ODEProblem(sys, [x => 0.0], (0.0, 1.0), [interp => spline])  | 
 | 81 | +solve(prob)  | 
 | 82 | +```  | 
 | 83 | + | 
 | 84 | +Note that the the following will not work:  | 
 | 85 | + | 
 | 86 | +```julia  | 
 | 87 | +ODEProblem(sys; [x => 0.0], (0.0, 1.0), [interp => LinearInterpolation(0.0:0.1:1.0, 0.0:0.1:1.0)])  | 
 | 88 | +```  | 
 | 89 | + | 
 | 90 | +Since the type of the spline doesn't match.  | 
0 commit comments