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+
2739def _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