|
2 | 2 |
|
3 | 3 | import numpy as np |
4 | 4 | import pytest |
| 5 | +from .conftest import editsdefaults |
5 | 6 |
|
| 7 | +import control as ct |
6 | 8 | from control import c2d, tf, tf2ss, NonlinearIOSystem |
7 | 9 | from control.lti import (LTI, common_timebase, damp, dcgain, isctime, isdtime, |
8 | 10 | issiso, pole, timebaseEqual, zero) |
9 | 11 | from control.tests.conftest import slycotonly |
10 | | - |
| 12 | +from control.exception import slycot_check |
11 | 13 |
|
12 | 14 | class TestLTI: |
13 | 15 |
|
@@ -153,3 +155,47 @@ def test_isdtime(self, objfun, arg, dt, ref, strictref): |
153 | 155 | strictref = not strictref |
154 | 156 | assert isctime(obj) == ref |
155 | 157 | assert isctime(obj, strict=True) == strictref |
| 158 | + |
| 159 | + @pytest.mark.usefixtures("editsdefaults") |
| 160 | + @pytest.mark.parametrize("fcn", [ct.ss, ct.tf, ct.frd]) |
| 161 | + @pytest.mark.parametrize("nstate, nout, ninp, squeeze, shape", [ |
| 162 | + [1, 1, 1, None, (8,)], # SISO |
| 163 | + [2, 1, 1, True, (8,)], |
| 164 | + [3, 1, 1, False, (1, 1, 8)], |
| 165 | + [1, 2, 1, None, (2, 1, 8)], # SIMO |
| 166 | + [2, 2, 1, True, (2, 1, 8)], |
| 167 | + [3, 2, 1, False, (2, 1, 8)], |
| 168 | + [1, 1, 2, None, (1, 2, 8)], # MISO |
| 169 | + [2, 1, 2, True, (1, 2, 8)], |
| 170 | + [3, 1, 2, False, (1, 2, 8)], |
| 171 | + [1, 2, 2, None, (2, 2, 8)], # MIMO |
| 172 | + [2, 2, 2, True, (2, 2, 8)], |
| 173 | + [3, 2, 2, False, (2, 2, 8)] |
| 174 | + ]) |
| 175 | + def test_squeeze(self, fcn, nstate, nout, ninp, squeeze, shape): |
| 176 | + # Compute the length of the frequency array |
| 177 | + omega = np.logspace(-2, 2, 8) |
| 178 | + |
| 179 | + # Create the system to be tested |
| 180 | + if fcn == ct.frd: |
| 181 | + sys = fcn(ct.rss(nstate, nout, ninp), omega) |
| 182 | + elif fcn == ct.tf and (nout > 1 or ninp > 1) and not slycot_check(): |
| 183 | + pytest.skip("Conversion of MIMO systems to transfer functions " |
| 184 | + "requires slycot.") |
| 185 | + else: |
| 186 | + sys = fcn(ct.rss(nstate, nout, ninp)) |
| 187 | + |
| 188 | + # Pass squeeze argument and make sure the shape is correct |
| 189 | + mag, phase, _ = sys.frequency_response(omega, squeeze=squeeze) |
| 190 | + assert mag.shape == shape |
| 191 | + assert phase.shape == shape |
| 192 | + assert sys(omega * 1j, squeeze=squeeze).shape == shape |
| 193 | + assert ct.evalfr(sys, omega * 1j, squeeze=squeeze).shape == shape |
| 194 | + |
| 195 | + # Changing config.default to False should return 3D frequency response |
| 196 | + ct.config.set_defaults('control', squeeze=False) |
| 197 | + mag, phase, _ = sys.frequency_response(omega) |
| 198 | + assert mag.shape == (sys.outputs, sys.inputs, 8) |
| 199 | + assert phase.shape == (sys.outputs, sys.inputs, 8) |
| 200 | + assert sys(omega * 1j).shape == (sys.outputs, sys.inputs, 8) |
| 201 | + assert ct.evalfr(sys, omega * 1j).shape == (sys.outputs, sys.inputs, 8) |
0 commit comments