Skip to content

Commit 027fe71

Browse files
docs: add doc example for faster linearization
1 parent c17ce0a commit 027fe71

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

docs/src/basics/Linearization.md

+70-1
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,74 @@ 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+
@named y = Blocks.RealOutput()
75+
@named u = Blocks.RealInput()
76+
77+
eqs = [D(x) ~ v
78+
D(v) ~ -k * x - k3 * x^3 - c * v + 10u.u
79+
y.u ~ x]
80+
81+
@named duffing = ODESystem(eqs, t, systems = [y, u], defaults = [u.u => 0])
82+
83+
# pass a constant value for `x`, since it is the variable we will change in operating points
84+
linfun, simplified_sys = linearization_function(duffing, [u.u], [y.u]; op = Dict(x => NaN));
85+
86+
println(linearize(simplified_sys, linfun; op = Dict(x => 1.0)))
87+
println(linearize(simplified_sys, linfun; op = Dict(x => 0.0)))
88+
89+
@time linearize(simplified_sys, linfun; op = Dict(x => 0.0))
90+
91+
nothing # hide
92+
```
93+
94+
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
95+
[`ModelingToolkit.LinearizationProblem`](@ref). This object is symbolically indexable, and can thus integrate with SymbolicIndexingInterface.jl for fast updates.
96+
97+
```@example LINEARIZE
98+
using SymbolicIndexingInterface
99+
100+
# The second argument is the value of the independent variable `t`.
101+
linprob = LinearizationProblem(linfun, 1.0)
102+
# It can be mutated
103+
linprob.t = 0.0
104+
# create a setter function to update `x` efficiently
105+
setter! = setu(linprob, x)
106+
107+
function fast_linearize!(problem, setter!, value)
108+
setter!(problem, value)
109+
solve(problem)
110+
end
111+
112+
println(fast_linearize!(linprob, setter!, 1.0))
113+
println(fast_linearize!(linprob, setter!, 0.0))
114+
115+
@time fast_linearize!(linprob, setter!, 1.0)
116+
117+
nothing # hide
118+
```
119+
120+
Note that `linprob` above can be interacted with similar to a normal `ODEProblem`.
121+
122+
```@repl LINEARIZE
123+
prob[x]
124+
prob[x] = 1.5
125+
prob[x]
126+
```
127+
60128
## Symbolic linearization
61129

62130
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 +157,5 @@ Pages = ["Linearization.md"]
89157
linearize
90158
ModelingToolkit.linearize_symbolic
91159
ModelingToolkit.linearization_function
160+
ModelingToolkit.LinearizationProblem
92161
```

0 commit comments

Comments
 (0)