Skip to content

Commit 54bee46

Browse files
authored
Merge pull request #101 from JuliaControl/linearize_lessalloc
Reduce allocations in `linearize!`
2 parents 944a98a + 5621030 commit 54bee46

File tree

1 file changed

+28
-15
lines changed

1 file changed

+28
-15
lines changed

src/model/linearization.jl

+28-15
Original file line numberDiff line numberDiff line change
@@ -108,24 +108,37 @@ julia> linearize!(linmodel, model, x=[20.0], u=[0.0]); linmodel.A
108108
```
109109
"""
110110
function linearize!(
111-
linmodel::LinModel{NT}, model::SimModel; x=model.x0+model.xop, u=model.uop, d=model.dop
112-
) where NT<:Real
111+
linmodel::LinModel{NT}, model::SM; x=model.x0+model.xop, u=model.uop, d=model.dop
112+
) where {NT<:Real, SM<:SimModel{NT}}
113113
nonlinmodel = model
114-
u0, d0 = u - nonlinmodel.uop, d - nonlinmodel.dop
115-
xnext, y = Vector{NT}(undef, model.nx), Vector{NT}(undef, model.ny)
116-
# --- compute the nonlinear model output at operating points ---
117-
h!(y, nonlinmodel, x, d0)
118-
y .= y .+ nonlinmodel.yop
114+
buffer = nonlinmodel.buffer
115+
# --- remove the operating points of the nonlinear model (typically zeros) ---
116+
x0::Vector{NT}, u0::Vector{NT}, d0::Vector{NT} = buffer.x, buffer.u, buffer.d
117+
u0 .= u .- nonlinmodel.uop
118+
d0 .= d .- nonlinmodel.dop
119+
x0 .= x .- nonlinmodel.xop
119120
# --- compute the Jacobians at linearization points ---
120-
A, Bu, Bd, C, Dd = linmodel.A, linmodel.Bu, linmodel.Bd, linmodel.C, linmodel.Dd
121-
ForwardDiff.jacobian!(A, (xnext, x) -> f!(xnext, nonlinmodel, x, u0, d0), xnext, x)
122-
ForwardDiff.jacobian!(Bu, (xnext, u0) -> f!(xnext, nonlinmodel, x, u0, d0), xnext, u0)
123-
ForwardDiff.jacobian!(Bd, (xnext, d0) -> f!(xnext, nonlinmodel, x, u0, d0), xnext, d0)
124-
ForwardDiff.jacobian!(C, (y, x) -> h!(y, nonlinmodel, x, d0), y, x)
125-
ForwardDiff.jacobian!(Dd, (y, d0) -> h!(y, nonlinmodel, x, d0), y, d0)
121+
A::Matrix{NT}, Bu::Matrix{NT}, Bd::Matrix{NT} = linmodel.A, linmodel.Bu, linmodel.Bd
122+
C::Matrix{NT}, Dd::Matrix{NT} = linmodel.C, linmodel.Dd
123+
xnext0::Vector{NT}, y0::Vector{NT} = linmodel.buffer.x, linmodel.buffer.y
124+
myf_x0!(xnext0, x0) = f!(xnext0, nonlinmodel, x0, u0, d0)
125+
myf_u0!(xnext0, u0) = f!(xnext0, nonlinmodel, x0, u0, d0)
126+
myf_d0!(xnext0, d0) = f!(xnext0, nonlinmodel, x0, u0, d0)
127+
myh_x0!(y0, x0) = h!(y0, nonlinmodel, x0, d0)
128+
myh_d0!(y0, d0) = h!(y0, nonlinmodel, x0, d0)
129+
ForwardDiff.jacobian!(A, myf_x0!, xnext0, x0)
130+
ForwardDiff.jacobian!(Bu, myf_u0!, xnext0, u0)
131+
ForwardDiff.jacobian!(Bd, myf_d0!, xnext0, d0)
132+
ForwardDiff.jacobian!(C, myh_x0!, y0, x0)
133+
ForwardDiff.jacobian!(Dd, myh_d0!, y0, d0)
134+
# --- compute the nonlinear model output at operating points ---
135+
h!(y0, nonlinmodel, x0, d0)
136+
y = y0
137+
y .= y0 .+ nonlinmodel.yop
126138
# --- compute the nonlinear model next state at operating points ---
127-
f!(xnext, nonlinmodel, x, u, d)
128-
xnext .+= nonlinmodel.fop .- nonlinmodel.xop
139+
f!(xnext0, nonlinmodel, x0, u0, d0)
140+
xnext = xnext0
141+
xnext .= xnext0 .+ nonlinmodel.fop .- nonlinmodel.xop
129142
# --- modify the linear model operating points ---
130143
linmodel.uop .= u
131144
linmodel.yop .= y

0 commit comments

Comments
 (0)