Skip to content

Commit 9584e81

Browse files
docs: add doc example for faster linearization
1 parent d101856 commit 9584e81

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

docs/src/basics/Linearization.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ The `linearize` function expects the user to specify the inputs ``u`` and the ou
2222
```@example LINEARIZE
2323
using ModelingToolkit
2424
using ModelingToolkit: t_nounits as t, D_nounits as D
25-
@variables x(t)=0 y(t)=0 u(t)=0 r(t)=0
25+
@variables x(t)=0 y(t) u(t) r(t)=0
2626
@parameters kp = 1
2727
2828
eqs = [u ~ kp * (r - y) # P controller
@@ -57,6 +57,76 @@ The operating point to linearize around can be specified with the keyword argume
5757

5858
If linearization is to be performed around multiple operating points, the simplification of the system has to be carried out a single time only. To facilitate this, the lower-level function [`ModelingToolkit.linearization_function`](@ref) is available. This function further allows you to obtain separate Jacobians for the differential and algebraic parts of the model. For ODE models without algebraic equations, the statespace representation above is available from the output of `linearization_function` as `A, B, C, D = f_x, f_u, h_x, h_u`.
5959

60+
All variables that will be fixed by an operating point _must_ be provided in the operating point to `linearization_function`. For example, if the operating points fix the value of
61+
`x`, `y` and `z` then an operating point with constant values for these variables (e.g. `Dict(x => 1.0, y => 1.0, z => 1.0)`) must be provided. The constant values themselves
62+
do not matter and can be changed by subsequent operating points.
63+
64+
One approach to batch linearization would be to call `linearize` in a loop, providing a different operating point each time. For example:
65+
66+
```@example LINEARIZE
67+
using ModelingToolkitStandardLibrary
68+
using ModelingToolkitStandardLibrary.Blocks
69+
70+
@parameters k=10 k3=2 c=1
71+
@variables x(t)=0 [bounds = (-0.5, 1.5)]
72+
@variables v(t)=0
73+
74+
75+
@named y = Blocks.RealOutput()
76+
@named u = Blocks.RealInput()
77+
78+
eqs = [D(x) ~ v
79+
D(v) ~ -k * x - k3 * x^3 - c * v + 10u.u
80+
y.u ~ x]
81+
82+
83+
@named duffing = ODESystem(eqs, t, systems=[y, u], defaults=[u.u => 0])
84+
85+
# pass a constant value for `x`, since it is the variable we will change in operating points
86+
linfun, simplified_sys = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN));
87+
88+
println(linearize(simplified_sys, linfun; op = Dict(x => 1.0)))
89+
println(linearize(simplified_sys, linfun; op = Dict(x => 0.0)))
90+
91+
@time linearize(simplified_sys, linfun; op = Dict(x => 0.0))
92+
93+
nothing # hide
94+
```
95+
96+
However, this route is still expensive since it has to repeatedly process the symbolic map provided to `op`. `linearize` is simply a wrapper for creating and solving a
97+
[`ModelingToolkit.LinearizationProblem`](@ref). This object is symbolically indexable, and can thus integrate with SymbolicIndexingInterface.jl for fast updates.
98+
99+
```@example LINEARIZE
100+
using SymbolicIndexingInterface
101+
102+
# The second argument is the value of the independent variable `t`.
103+
linprob = LinearizationProblem(linfun, 1.0)
104+
# It can be mutated
105+
linprob.t = 0.0
106+
# create a setter function to update `x` efficiently
107+
setter! = setu(linprob, x)
108+
109+
function fast_linearize!(problem, setter!, value)
110+
setter!(problem, value)
111+
solve(problem)
112+
end
113+
114+
println(fast_linearize!(linprob, setter!, 1.0))
115+
println(fast_linearize!(linprob, setter!, 0.0))
116+
117+
@time fast_linearize!(linprob, setter!, 1.0)
118+
119+
nothing # hide
120+
```
121+
122+
Note that `linprob` above can be interacted with similar to a normal `ODEProblem`.
123+
124+
```@repl LINEARIZE
125+
prob[x]
126+
prob[x] = 1.5
127+
prob[x]
128+
```
129+
60130
## Symbolic linearization
61131

62132
The function [`ModelingToolkit.linearize_symbolic`](@ref) works similar to [`ModelingToolkit.linearize`](@ref) but returns symbolic rather than numeric Jacobians. Symbolic linearization have several limitations and no all systems that can be linearized numerically can be linearized symbolically.
@@ -89,4 +159,5 @@ Pages = ["Linearization.md"]
89159
linearize
90160
ModelingToolkit.linearize_symbolic
91161
ModelingToolkit.linearization_function
162+
ModelingToolkit.LinearizationProblem
92163
```

0 commit comments

Comments
 (0)