Skip to content

Commit 70fcf00

Browse files
docs: update docs for interpolations
Co-authored-by: Fredrik Bagge Carlson <[email protected]>
1 parent fe4853b commit 70fcf00

File tree

2 files changed

+90
-32
lines changed

2 files changed

+90
-32
lines changed

docs/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[deps]
22
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
3+
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
4+
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
35
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
46
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
57
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
@@ -10,6 +12,8 @@ Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
1012

1113
[compat]
1214
ControlSystemsBase = "1.1"
15+
DataFrames = "1.7"
16+
DataInterpolations = "6.4"
1317
DifferentialEquations = "7.6"
1418
Documenter = "1"
1519
IfElse = "0.1"

docs/src/tutorials/input_component.md

Lines changed: 86 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,91 @@
22

33
There are 4 ways to include data as part of a model.
44

5-
1. using `ModelingToolkitStandardLibrary.Blocks.InterpolationBlock`
6-
2. using `ModelingToolkitStandardLibrary.Blocks.ParametrizedInterpolationBlock`
5+
1. using `ModelingToolkitStandardLibrary.Blocks.Interpolation`
6+
2. using `ModelingToolkitStandardLibrary.Blocks.ParametrizedInterpolation`
77
3. using a custom component with external data (not recommended)
88
4. using `ModelingToolkitStandardLibrary.Blocks.SampledData` (legacy)
99

1010
This tutorial demonstrate each case and explain the pros and cons of each.
1111

12-
## `InterpolationBlock` Component
12+
## `Interpolation` Block
1313

14-
The `ModelingToolkitStandardLibrary.Blocks.InterpolationBlock` component is easy to use and is performant.
15-
It is simlar to using callable paramterers, but it provides a block interface and a `RealOutput` connector.
16-
The `InterpolationBlock` is compatible with interpolation types from `DataInterpolation`.
17-
Here is an example on how to use it
14+
The `ModelingToolkitStandardLibrary.Blocks.Interpolation` component is easy to use and is performant.
15+
It is simlar to using callable paramterers, but it provides a block interface with `RealInput` and `RealOutput` connectors.
16+
The `Interpolation` is compatible with interpolation types from `DataInterpolation`.
17+
18+
```@docs
19+
ModelingToolkitStandardLibrary.Blocks.Interpolation
20+
```
21+
22+
Here is an example on how to use it. Let's consider a mass-spring-damper system, where
23+
we have an external force as an input. We then generate some example data in a `DataFrame`
24+
that would represent a measurement of the input. In a more realistic case, this `DataFrame`
25+
would be read from a file.
1826

1927
```@example interpolation_block
2028
using ModelingToolkit
2129
using ModelingToolkit: t_nounits as t, D_nounits as D
2230
using ModelingToolkitStandardLibrary.Blocks
2331
using DataInterpolations
2432
using OrdinaryDiffEq
33+
using DataFrames
2534
using Plots
2635
27-
function System(data, time; name)
28-
@named src = InterpolationBlock(LinearInterpolation, data, time)
36+
function MassSpringDamper(; name)
37+
@named input = RealInput()
38+
@variables f(t)=0 x(t)=0 dx(t)=0 ddx(t)=0
39+
@parameters m=10 k=1000 d=1
2940
30-
vars = @variables f(t)=0 x(t)=0 dx(t)=0 ddx(t)=0
31-
pars = @parameters m=10 k=1000 d=1
32-
33-
eqs = [f ~ src.output.u
41+
eqs = [
42+
f ~ input.u
3443
ddx * 10 ~ k * x + d * dx + f
3544
D(x) ~ dx
3645
D(dx) ~ ddx]
3746
38-
ODESystem(eqs, t, vars, pars; systems = [src], name)
47+
ODESystem(eqs, t, [], []; name, systems = [input])
3948
end
4049
41-
dt = 4e-4
42-
time = 0:dt:0.1
43-
data = sin.(2 * pi * time * 100) # example data
50+
function MassSpringDamperSystem(data, time; name)
51+
@named src = Interpolation(LinearInterpolation, data, time)
52+
@named clk = ContinuousClock()
53+
@named model = MassSpringDamper()
4454
45-
@named system = System(data, time)
55+
eqs = [
56+
connect(src.input, clk.output)
57+
connect(src.output, model.input)
58+
]
59+
60+
ODESystem(eqs, t, [], []; name, systems = [src, clk, model])
61+
end
62+
63+
function generate_data()
64+
dt = 4e-4
65+
time = 0:dt:0.1
66+
data = sin.(2 * pi * time * 100)
67+
68+
return DataFrame(; time, data)
69+
end
70+
71+
df = generate_data() # example data
72+
73+
@named system = MassSpringDamperSystem(df.data, df.time)
4674
sys = structural_simplify(system)
47-
prob = ODEProblem(sys, [], (0, time[end]))
75+
prob = ODEProblem(sys, [], (0, df.time[end]))
4876
sol = solve(prob)
4977
plot(sol)
5078
```
5179

52-
## `ParametrizedInterpolationBlock` Component
80+
## `ParametrizedInterpolation` Block
81+
82+
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.
83+
The main advantage of this block over the [`Interpolation`](@ref) one is that one can use it for optimization problems. Currently, this supports forward mode AD via ForwardDiff, but due to the increased flexibility of the types in the component, this is not as fast as the `Interpolation` block,
84+
so it is recommended to use only when the added flexibility is required.
85+
86+
```@docs
87+
ModelingToolkitStandardLibrary.Blocks.ParametrizedInterpolation
88+
```
5389

54-
The `ModelingToolkitStandardLibrary.Blocks.ParametrizedInterpolationBlock` component is similar to `InterpolationBlock`, 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.
55-
The `ParametrizedInterpolationBlock` is compatible with interpolation types from `DataInterpolation`.
5690
Here is an example on how to use it
5791

5892
```@example parametrized_interpolation
@@ -61,29 +95,49 @@ using ModelingToolkit: t_nounits as t, D_nounits as D
6195
using ModelingToolkitStandardLibrary.Blocks
6296
using DataInterpolations
6397
using OrdinaryDiffEq
98+
using DataFrames
6499
using Plots
65100
66-
function System(data, time; name)
67-
@named src = ParametrizedInterpolation(LinearInterpolation, data, time)
68-
101+
function MassSpringDamper(; name)
102+
@named input = RealInput()
69103
vars = @variables f(t)=0 x(t)=0 dx(t)=0 ddx(t)=0
70104
pars = @parameters m=10 k=1000 d=1
71105
72-
eqs = [f ~ src.output.u
106+
eqs = [
107+
f ~ input.u
73108
ddx * 10 ~ k * x + d * dx + f
74109
D(x) ~ dx
75110
D(dx) ~ ddx]
76111
77-
ODESystem(eqs, t, vars, pars; systems = [src], name)
112+
ODESystem(eqs, t, vars, pars; name, systems = [input])
113+
end
114+
115+
function MassSpringDamperSystem(data, time; name)
116+
@named src = ParametrizedInterpolation(LinearInterpolation, data, time)
117+
@named clk = ContinuousClock()
118+
@named model = MassSpringDamper()
119+
120+
eqs = [
121+
connect(model.input, src.output)
122+
connect(src.input, clk.output)
123+
]
124+
125+
ODESystem(eqs, t, [], []; name, systems = [src, clk, model])
78126
end
79127
80-
dt = 4e-4
81-
time = 0:dt:0.1
82-
data = sin.(2 * pi * time * 100) # example data
128+
function generate_data()
129+
dt = 4e-4
130+
time = 0:dt:0.1
131+
data = sin.(2 * pi * time * 100)
83132
84-
@named system = System(data, time)
133+
return DataFrame(; time, data)
134+
end
135+
136+
df = generate_data() # example data
137+
138+
@named system = MassSpringDamperSystem(df.data, df.time)
85139
sys = structural_simplify(system)
86-
prob = ODEProblem(sys, [], (0, time[end]))
140+
prob = ODEProblem(sys, [], (0, df.time[end]))
87141
sol = solve(prob)
88142
plot(sol)
89143
```

0 commit comments

Comments
 (0)