Skip to content

Commit 793f0d6

Browse files
author
Henrik Sandberg
committed
Added:
* type check when calling ct.norm * metod argument in ct.norm (slycot or scipy)
1 parent 6f810ba commit 793f0d6

1 file changed

Lines changed: 38 additions & 17 deletions

File tree

control/sysnorm.py

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,36 @@
2424

2525
#------------------------------------------------------------------------------
2626

27+
def _slycot_or_scipy(method):
28+
""" Copied from ct.mateqn. For internal use."""
29+
30+
if method == 'slycot' or (method is None and ct.slycot_check()):
31+
return 'slycot'
32+
elif method == 'scipy' or (method is None and not ct.slycot_check()):
33+
return 'scipy'
34+
else:
35+
raise ct.ControlArgument(f"Unknown argument '{method}'.")
36+
37+
#------------------------------------------------------------------------------
38+
2739
def _h2norm_slycot(sys, print_warning=True):
2840
"""H2 norm of a linear system. For internal use. Requires Slycot.
2941
3042
See also
3143
--------
32-
slycot.ab13bd : the Slycot routine that does the calculation
33-
https://github.com/python-control/Slycot/issues/199 : Post on issue with ab13bf
44+
``slycot.ab13bd`` : the Slycot routine that does the calculation
45+
https://github.com/python-control/Slycot/issues/199 : Post on issue with ``ab13bf``
3446
"""
3547

3648
try:
3749
from slycot import ab13bd
3850
except ImportError:
39-
ct.ControlSlycot("Can't find slycot module 'ab13bd'!")
51+
ct.ControlSlycot("Can't find slycot module ``ab13bd``!")
4052

4153
try:
4254
from slycot.exceptions import SlycotArithmeticError
4355
except ImportError:
44-
raise ct.ControlSlycot("Can't find slycot class 'SlycotArithmeticError'!")
56+
raise ct.ControlSlycot("Can't find slycot class ``SlycotArithmeticError``!")
4557

4658
A, B, C, D = ct.ssdata(ct.ss(sys))
4759

@@ -85,7 +97,7 @@ def _h2norm_slycot(sys, print_warning=True):
8597

8698
#------------------------------------------------------------------------------
8799

88-
def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
100+
def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
89101
"""Computes norm of system.
90102
91103
Parameters
@@ -99,13 +111,15 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
99111
unless p='inf'.
100112
print_warning : bool
101113
Print warning message in case norm value may be uncertain.
102-
use_slycot : bool
103-
Use Slycot routines if available.
114+
method : str, optional
115+
Set the method used for computing the result. Current methods are
116+
'slycot' and 'scipy'. If set to None (default), try 'slycot' first
117+
and then 'scipy'.
104118
105119
Returns
106120
-------
107-
norm_value : float or NoneType
108-
Norm value of system (float) or None if computation could not be completed.
121+
norm_value : float
122+
Norm value of system.
109123
110124
Notes
111125
-----
@@ -114,17 +128,24 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
114128
Examples
115129
--------
116130
>>> Gc = ct.tf([1], [1, 2, 1])
117-
>>> ct.norm(Gc,2)
131+
>>> ct.norm(Gc, 2)
118132
0.5000000000000001
119-
>>> ct.norm(Gc,'inf',tol=1e-10)
120-
1.0000000000582077
133+
>>> ct.norm(Gc, 'inf', tol=1e-11, method='scipy')
134+
1.000000000007276
121135
"""
136+
137+
if not isinstance(system, (ct.StateSpace, ct.TransferFunction)):
138+
raise TypeError('Parameter ``system``: must be a ``StateSpace`` or ``TransferFunction``')
139+
122140
G = ct.ss(system)
123141
A = G.A
124142
B = G.B
125143
C = G.C
126144
D = G.D
127145

146+
# Decide what method to use
147+
method = _slycot_or_scipy(method)
148+
128149
# -------------------
129150
# H2 norm computation
130151
# -------------------
@@ -151,12 +172,12 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
151172

152173
else:
153174
# Use slycot, if available, to compute (finite) norm
154-
if ct.slycot_check() and use_slycot:
175+
if method == 'slycot':
155176
return _h2norm_slycot(G, print_warning)
156177

157178
# Else use scipy
158179
else:
159-
P = ct.lyap(A, B@B.T) # Solve for controllability Gramian
180+
P = ct.lyap(A, B@B.T, method=method) # Solve for controllability Gramian
160181

161182
# System is stable to reach this point, and P should be positive semi-definite.
162183
# Test next is a precaution in case the Lyapunov equation is ill conditioned.
@@ -189,12 +210,12 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
189210

190211
else:
191212
# Use slycot, if available, to compute (finite) norm
192-
if ct.slycot_check() and use_slycot:
213+
if method == 'slycot':
193214
return _h2norm_slycot(G, print_warning)
194215

195216
# Else use scipy
196217
else:
197-
P = ct.dlyap(A, B@B.T)
218+
P = ct.dlyap(A, B@B.T, method=method)
198219

199220
# System is stable to reach this point, and P should be positive semi-definite.
200221
# Test next is a precaution in case the Lyapunov equation is ill conditioned.
@@ -228,7 +249,7 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
228249
return float('inf')
229250

230251
# Use slycot, if available, to compute (finite) norm
231-
if ct.slycot_check() and use_slycot:
252+
if method == 'slycot':
232253
return ct.linfnorm(G, tol)[0]
233254

234255
# Else use scipy

0 commit comments

Comments
 (0)