diff --git a/docs/src/tutorials/input_component.md b/docs/src/tutorials/input_component.md index 292a8aa7a..05e769dd4 100644 --- a/docs/src/tutorials/input_component.md +++ b/docs/src/tutorials/input_component.md @@ -35,7 +35,7 @@ using Plots function MassSpringDamper(; name) @named input = RealInput() - @variables f(t)=0 x(t)=0 dx(t)=0 ddx(t)=0 + @variables f(t) x(t)=0 dx(t)=0 ddx(t) @parameters m=10 k=1000 d=1 eqs = [f ~ input.u @@ -74,6 +74,35 @@ sol = solve(prob) plot(sol) ``` +Note that in the case of the `Interpolation` block, the `data` and the `time` act like +structural parameters. + +As such, we can also build the interpolation object outside of the model + +```@example interpolation_block +my_interpolation = LinearInterpolation(df.data, df.time) + +@mtkmodel MassSpringDamperSystem2 begin + @components begin + src = Interpolation(itp=my_interpolation) + clk = ContinuousClock() + model = MassSpringDamper() + end + @equations begin + connect(src.input, clk.output) + connect(src.output, model.input) + end +end; +@mtkbuild sys = MassSpringDamperSystem2() + +prob = ODEProblem(sys, [], (0, df.time[end])) +sol = solve(prob, Tsit5()) +plot(sol) +``` + +Note that the interpolation is constructed outside of the model, so we cannot use `remake` to change the +data. For that usecase, see the `ParametrizedInterpolation`. + ## `ParametrizedInterpolation` Block The `ModelingToolkitStandardLibrary.Blocks.ParametrizedInterpolation` component is similar to `Interpolation`, but as the name suggests, it is parametrized by the data, allowing one to change the underlying data without rebuilding the model as the data is represented via vector parameters. @@ -145,7 +174,7 @@ plot(sol2) ``` !!! note - + Note that when changing the data, the length of the new data must be the same as the length of the original data. ## Custom Component with External Data diff --git a/src/Blocks/sources.jl b/src/Blocks/sources.jl index 4839ed908..abe3b34a8 100644 --- a/src/Blocks/sources.jl +++ b/src/Blocks/sources.jl @@ -755,10 +755,12 @@ such as `LinearInterpolation`, `ConstantInterpolation` or `CubicSpline`. """ function Interpolation(interp_type, u, x, args...; name) itp = interp_type(u, x, args...) - Interpolation(itp; name) + Interpolation(; itp, name) end -function Interpolation(itp; name) +@deprecate Interpolation(itp; name) Interpolation(; itp, name) + +function Interpolation(; itp, name) @parameters (interpolator::typeof(itp))(..) = itp @named input = RealInput() @named output = RealOutput() @@ -868,3 +870,7 @@ function ParametrizedInterpolation( systems = [input, output], name) end + +function ParametrizedInterpolation(; interp_type, u::AbstractVector, x::AbstractVector, name) + ParametrizedInterpolation(interp_type, u, x; name) +end diff --git a/test/Blocks/sources.jl b/test/Blocks/sources.jl index 3f3de37c9..f8afafbb0 100644 --- a/test/Blocks/sources.jl +++ b/test/Blocks/sources.jl @@ -500,6 +500,44 @@ end @test SciMLBase.successful_retcode(sol) end +@testset "Interpolation in model macro" begin + + function MassSpringDamper(; name) + @named input = RealInput() + @variables f(t) x(t)=0 dx(t)=0 ddx(t) + @parameters m=10 k=1000 d=1 + + eqs = [f ~ input.u + ddx * 10 ~ k * x + d * dx + f + D(x) ~ dx + D(dx) ~ ddx] + + ODESystem(eqs, t; name, systems = [input]) + end + + table_data = [1.0, 2.0, 3.0] + table_bkp = [0.0, 0.5, 1.0] + itp = LinearInterpolation(table_data, table_bkp) + + @mtkmodel model_with_lut begin + @components begin + src = Interpolation(itp) + clk = ContinuousClock() + model = MassSpringDamper() + end + @equations begin + connect(src.input, clk.output) + connect(src.output, model.input) + end + end; + @mtkbuild sys = model_with_lut() + + prob = ODEProblem(sys, [], (0.0, 1)) + sol = solve(prob, Tsit5()) + + @test SciMLBase.successful_retcode(sol) +end + @testset "ParametrizedInterpolation" begin @variables y(t) = 0 u = rand(15)