|
| 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 returned 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( |
| 88 | + sys; [x => 0.0], (0.0, 1.0), [interp => LinearInterpolation(0.0:0.1:1.0, 0.0:0.1:1.0)]) |
| 89 | +``` |
| 90 | + |
| 91 | +Since the type of the spline doesn't match. |
0 commit comments