Skip to content

Commit dbce83a

Browse files
committed
add scaling capability to model reduction
1 parent 7addea4 commit dbce83a

File tree

2 files changed

+61
-10
lines changed

2 files changed

+61
-10
lines changed

src/descriptor.jl

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,16 @@ Compute the a balanced truncation of order `n` and the hankel singular values
8787
For keyword arguments, see the docstring of `DescriptorSystems.gbalmr`, reproduced below
8888
$(@doc(DescriptorSystems.gbalmr))
8989
"""
90-
function baltrunc2(sys::LTISystem; residual=false, n=missing, kwargs...)
91-
sysr, hs = DescriptorSystems.gbalmr(dss(sys); matchdc=residual, ord=n, kwargs...)
92-
ss(sysr), hs
90+
function baltrunc2(sys::LTISystem; residual=false, n=missing, scaleY=1.0, scaleU=1.0, kwargs...)
91+
# Apply scaling if needed
92+
Ts = isdiscrete(sys) ? sys.Ts : 0
93+
A, B, C, D = ssdata(sys)
94+
sys_scaled = ss(A, B*scaleU, scaleY*C, scaleY*D*scaleU, Ts)
95+
sysr, hs = DescriptorSystems.gbalmr(dss(sys_scaled); matchdc=residual, ord=n, kwargs...)
96+
# Inverse scaling after reduction
97+
Ar, Br, Cr, Dr = ssdata(ss(sysr))
98+
sys_final = ss(Ar, Br/scaleU, Cr/scaleY, Dr/(scaleY*scaleU), Ts)
99+
sys_final, hs
93100
end
94101

95102
"""
@@ -105,11 +112,15 @@ Coprime-factor reduction performs a coprime factorization of the model into \$P(
105112
- `kwargs`: Are passed to `DescriptorSystems.gbalmr`, the docstring of which is reproduced below:
106113
$(@doc(DescriptorSystems.gbalmr))
107114
"""
108-
function baltrunc_coprime(sys, info=nothing; residual=false, n=missing, factorization::F = DescriptorSystems.gnlcf, kwargs...) where F
115+
function baltrunc_coprime(sys, info=nothing; residual=false, n=missing, factorization::F = DescriptorSystems.gnlcf, scaleY=1.0, scaleU=1.0, kwargs...) where F
116+
# Apply scaling if needed
117+
Ts = isdiscrete(sys) ? sys.Ts : 0
118+
A, B, C, D = ssdata(sys)
119+
sys_scaled = ss(A, B*scaleU, scaleY*C, scaleY*D*scaleU, Ts)
109120
if info !== nothing && hasproperty(info, :NM)
110121
@unpack N, M, NM = info
111122
else
112-
N,M = factorization(dss(sys))
123+
N,M = factorization(dss(sys_scaled))
113124
A,E,B,C,D = DescriptorSystems.dssdata(N)
114125
NM = DescriptorSystems.dss(A,E,[B M.B],C,[D M.D])
115126
end
@@ -128,7 +139,9 @@ function baltrunc_coprime(sys, info=nothing; residual=false, n=missing, factoriz
128139
Br = BN - BM * (DMi * DN)
129140
Dr = (DMi * DN)
130141

131-
ss(Ar,Br,Cr,Dr,sys.timeevol), hs, (; NM, N, M, NMr)
142+
# Inverse scaling after reduction
143+
sys_final = ss(Ar, Br/scaleU, Cr/scaleY, Dr/(scaleY*scaleU), Ts)
144+
sys_final, hs, (; NM, N, M, NMr)
132145
end
133146

134147

@@ -139,18 +152,25 @@ Balanced truncation for unstable models. An additive decomposition of sys into `
139152
140153
See `baltrunc2` for other keyword arguments.
141154
"""
142-
function baltrunc_unstab(sys::LTISystem, info=nothing; residual=false, n=missing, kwargs...)
155+
function baltrunc_unstab(sys::LTISystem, info=nothing; residual=false, n=missing, scaleY=1.0, scaleU=1.0, kwargs...)
156+
# Apply scaling if needed
157+
Ts = isdiscrete(sys) ? sys.Ts : 0
158+
A, B, C, D = ssdata(sys)
159+
sys_scaled = ss(A, B*scaleU, scaleY*C, scaleY*D*scaleU, Ts)
143160
if info !== nothing && hasproperty(info, :stab)
144161
@unpack stab, unstab = info
145162
else
146-
stab, unstab = DescriptorSystems.gsdec(dss(sys); job="stable", kwargs...)
163+
stab, unstab = DescriptorSystems.gsdec(dss(sys_scaled); job="stable", kwargs...)
147164
end
148165
nx_unstab = size(unstab.A, 1)
149166
if n isa Integer && n < nx_unstab
150167
error("The model contains $(nx_unstab) poles outside the stability region, the reduced-order model must be of at least this order.")
151168
end
152169
sysr, hs = DescriptorSystems.gbalmr(stab; matchdc=residual, ord=n-nx_unstab, kwargs...)
153-
ss(sysr + unstab), hs, (; stab, unstab)
170+
# Inverse scaling after reduction
171+
Ar, Br, Cr, Dr = ssdata(ss(sysr + unstab))
172+
sys_final = ss(Ar, Br/scaleU, Cr/scaleY, Dr/(scaleY*scaleU), Ts)
173+
sys_final, hs, (; stab, unstab)
154174
end
155175

156176

test/test_reduction.jl

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,35 @@ Ksr, hs, infor = baltrunc_coprime(info.Ks; n)
300300
controller_reduction_plot(info.Gs,info.Ks)
301301
controller_reduction_plot(info.Gs,info.Ks, method=:cr)
302302

303-
# ncfmargin(P, W1*Ksr)
303+
# ncfmargin(P, W1*Ksr)
304+
305+
306+
# === Scaling tests for model reduction ===
307+
using RobustAndOptimalControl: baltrunc2, baltrunc_coprime, baltrunc_unstab
308+
309+
# Simple SISO system
310+
As = [-1.0]
311+
Bs = [2.0]
312+
Cs = [3.0]
313+
Ds = [0.5]
314+
sys_siso = ss(As, Bs, Cs, Ds)
315+
316+
# Non-unit scaling factors
317+
scaleY = 5.0
318+
scaleU = 0.2
319+
320+
# baltrunc2 scaling test
321+
sysr, _ = baltrunc2(sys_siso; n=1, scaleY, scaleU)
322+
@test sysr.nx == 1
323+
@test abs(dcgain(sys_siso) - dcgain(sysr)) < 1e-8
324+
325+
# baltrunc_coprime scaling test
326+
sysr_coprime, _, _ = baltrunc_coprime(sys_siso; n=1, scaleY, scaleU)
327+
@test sysr_coprime.nx == 1
328+
@test abs(dcgain(sys_siso) - dcgain(sysr_coprime)) < 1e-8
329+
330+
# baltrunc_unstab scaling test
331+
sys_unstab = ss([1.0], [1.0], [1.0], [0.0]) # Unstable pole
332+
sysr_unstab, _, _ = baltrunc_unstab(sys_unstab; n=1, scaleY, scaleU)
333+
@test sysr_unstab.nx == 1
334+
@test abs(dcgain(sys_unstab) - dcgain(sysr_unstab)) < 1e-8

0 commit comments

Comments
 (0)