Skip to content

Commit f7089f0

Browse files
committed
add more robustness options in causal simplification
1 parent 80af1c9 commit f7089f0

File tree

3 files changed

+34
-29
lines changed

3 files changed

+34
-29
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
name = "ControlSystemsMTK"
22
uuid = "687d7614-c7e5-45fc-bfc3-9ee385575c88"
33
authors = ["Fredrik Bagge Carlson"]
4-
version = "2.4.1"
5-
4+
version = "2.5.0"
65

76
[deps]
87
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
@@ -28,9 +27,10 @@ julia = "1.6"
2827

2928
[extras]
3029
ControlSystems = "a6e380b2-a6ca-5380-bf3e-84a91bcd477e"
30+
GenericLinearAlgebra = "14197337-ba66-59df-a3e3-ca00e7dcff7a"
3131
OrdinaryDiffEqNonlinearSolve = "127b3ac7-2247-4354-8eb6-78cf4e7c58e8"
3232
OrdinaryDiffEqRosenbrock = "43230ef6-c299-4910-a778-202eb28ce4ce"
3333
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3434

3535
[targets]
36-
test = ["Test", "ControlSystems", "OrdinaryDiffEqRosenbrock", "OrdinaryDiffEqNonlinearSolve"]
36+
test = ["Test", "ControlSystems", "GenericLinearAlgebra", "OrdinaryDiffEqRosenbrock", "OrdinaryDiffEqNonlinearSolve"]

src/ode_system.jl

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -151,26 +151,28 @@ function get_x_names(lsys, sys; descriptor, simple_infeigs, balance)
151151
end
152152

153153
"""
154-
causal_simplification(sys, u2duinds::Vector{Pair{Int, Int}}; descriptor=true, simple_infeigs=true, balance=false)
154+
causal_simplification(sys, u2duinds::Vector{Pair{Int, Int}}; descriptor=true, simple_infeigs=true, balance=false, big=false)
155155
156156
If `descriptor = true`, the function `DescriptorSystems.dss2ss` is used. In this case,
157157
- `balance`: indicates whether to balance the system using `DescriptorSystems.gprescale` before conversion to `StateSpace`. Balancing changes the state realization (through scaling).
158158
- `simple_infeigs`: if set to false, further simplification may be performed in some cases.
159159
160-
If `descriptor = false`, the argument `big = true` performs computations in `BigFloat` precision, useful for poorly scaled systems.
160+
The argument `big = true` performs computations in `BigFloat` precision, useful for poorly scaled systems. This may require the user to install and load `GenericLinearAlgebra` (if you get error `no method matching svd!(::Matrix{BigFloat})`).
161161
"""
162162
function causal_simplification(sys, u2duinds::Vector{Pair{Int, Int}}; balance=false, descriptor=true, simple_infeigs = true, big = false)
163-
fm(x) = convert(Matrix{Float64}, x)
163+
T = big ? BigFloat : Float64
164+
b1 = big ? Base.big(1.0) : 1.0
165+
fm(x) = convert(Matrix{T}, x)
164166
nx = size(sys.A, 1)
165167
ny = size(sys.C, 1)
166168
ndu = length(u2duinds)
167169
nu = size(sys.B, 2) - ndu
168170
u_with_du_inds = first.(u2duinds)
169171
duinds = last.(u2duinds)
170-
B = sys.B[:, 1:nu]
171-
= sys.B[:, duinds]
172-
D = sys.D[:, 1:nu]
173-
= sys.D[:, duinds]
172+
B = b1*sys.B[:, 1:nu]
173+
= b1*sys.B[:, duinds]
174+
D = b1*sys.D[:, 1:nu]
175+
= b1*sys.D[:, duinds]
174176
iszero(fm(D̄)) || error("Nonzero feedthrough matrix from input derivative not supported")
175177
if descriptor
176178
Iu = u_with_du_inds .== (1:nu)'
@@ -191,22 +193,11 @@ function causal_simplification(sys, u2duinds::Vector{Pair{Int, Int}}; balance=fa
191193

192194
return ss(RobustAndOptimalControl.DescriptorSystems.dss2ss(dsys; simple_infeigs, fast=false)[1])
193195
else
194-
if big
195-
b1 = Base.big(1.0)
196-
ss(b1*sys.A, b1*B, b1*sys.C, b1*D) + diff_out(ss(b1*sys.A, b1*B̄, b1*sys.C, b1*D̄))
197-
else
198-
b = balance ? s->balance_statespace(sminreal(s))[1] : identity
199-
b(ss(sys.A, B, sys.C, D)) + b(ss(sys.A, B̄, sys.C, D̄))*tf('s')
200-
end
196+
b = balance ? s->balance_statespace(sminreal(s))[1] : identity
197+
b(ss(sys.A, B, sys.C, D)) + b(ss(sys.A, B̄, sys.C, D̄))*tf('s')
201198
end
202199
end
203200

204-
function diff_out(sys)
205-
A,B,C,D = ssdata(sys)
206-
iszero(D) || error("Nonzero feedthrough matrix not supported")
207-
ss(A,B,C*A, C*B, sys.timeevol)
208-
end
209-
210201

211202
for f in [:sensitivity, :comp_sensitivity, :looptransfer]
212203
fnn = Symbol("get_named_$f")

test/test_ODESystem.jl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,18 +335,25 @@ op2[cart.f] = 0
335335
@test G.ny == length(lin_outputs)
336336

337337
## Test difficult `named_ss` simplification
338-
using ControlSystemsMTK, ControlSystemsBase, RobustAndOptimalControl
338+
using ControlSystemsMTK, ControlSystemsBase, RobustAndOptimalControl, Test, GenericLinearAlgebra
339339
lsys = (A = [0.0 2.778983834717109e8 1.4122312296634873e6 0.0; 0.0 0.0 0.0 0.037848975765016724; 0.0 24.837541148074962 0.12622006230897712 0.0; -0.0 -4.620724819774693 -0.023481719514324866 -0.6841991610512456], B = [-5.042589978197361e8 0.0; -0.0 0.0; -45.068824982602656 -0.0; 8.384511049369085 54.98555939873381], C = [0.0 0.0 0.954929658551372 0.0], D = [0.0 0.0])
340340

341341
# lsys = (A = [-0.0075449237853825925 1.6716817118020731e-6 0.0; 1864.7356343162514 -0.4131578457122937 0.0; 0.011864343330426718 -2.6287085638214332e-6 0.0], B = [0.0 0.0; 0.0 52566.418015009294; 0.0 0.3284546792274811], C = [1.4683007399899215e8 0.0 0.0], D = [-9.157636303058283e7 0.0])
342342

343343
G = ControlSystemsMTK.causal_simplification(lsys, [1=>2])
344+
G = minreal(G, 1e-12)
344345
G2 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=false)
345346
G2 = minreal(G2, 1e-12)
347+
G3 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], big=true)
348+
G3 = minreal(G3, 1e-12)
349+
G4 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=true, balance=true)
350+
G4 = minreal(G4, 1e-12)
351+
352+
w_test = [1e-5, 1, 10, 100]
353+
@test freqresp(G, w_test) freqresp(G2, w_test) rtol=1e-6
354+
@test freqresp(G, w_test) freqresp(G3, w_test) rtol=1e-6
355+
@test freqresp(G, w_test) freqresp(G4, w_test) rtol=1e-6
346356

347-
@test dcgain(G, 1e-5)[] dcgain(G2, 1e-5)[] rtol=1e-3
348-
@test freqresp(G, 1)[] freqresp(G2, 1)[]
349-
@test freqresp(G, 10)[] freqresp(G2, 10)[]
350357

351358
z = 0.462726166562343204837317130554462562
352359

@@ -366,15 +373,22 @@ w = exp10.(LinRange(-12, 2, 2000))
366373

367374
## artificial fully dense test
368375

369-
lsys = ssrand(2,2,3,proper=true)
376+
lsys = let
377+
tempA = [-0.8101413207021115 0.905054220094988 -0.12282983628692003; 0.9066960393438117 -1.3378400902008518 -0.0610101630607034; -0.07253623899748166 1.4118402411983302 -1.7957106725392422]
378+
tempB = [-0.8984842931160537 1.4012460461970973; -0.6086273804588082 0.9336277670619954; -0.1376448663325406 0.19241847208402496]
379+
tempC = [1.1228782382333735 0.041349950615147096 -1.3629397459682921; 0.10499710831314196 -1.228883432780842 0.044498460069701234]
380+
tempD = [0.0 0.0; 0.0 0.0]
381+
ss(tempA, tempB, tempC, tempD)
382+
end
370383
G = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=false)
371384
G2 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=true)
372385
G3 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=false, big=true)
373386
G4 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=true, simple_infeigs=false, balance=true)
387+
G5 = ControlSystemsMTK.causal_simplification(lsys, [1=>2], descriptor=true, big=true)
374388

375389
w_test = [1e-5, 1, 100]
376390
@test freqresp(G, w_test) freqresp(G2, w_test)
377391
@test freqresp(G, w_test) freqresp(G3, w_test)
378392
@test freqresp(G, w_test) freqresp(G4, w_test)
379393

380-
# bodeplot([G, G2, G3, G4], exp10.(LinRange(-2, 2, 200)))
394+
# bodeplot([G, G2, G3, G4, G5], exp10.(LinRange(-2, 2, 200)))

0 commit comments

Comments
 (0)