|
10 | 10 |
|
11 | 11 | import re
|
12 | 12 | import warnings
|
13 |
| -import pytest |
| 13 | +from math import sqrt |
14 | 14 |
|
15 | 15 | import numpy as np
|
16 |
| -from math import sqrt |
| 16 | +import pytest |
| 17 | +import scipy |
17 | 18 |
|
18 | 19 | import control as ct
|
19 | 20 |
|
@@ -2087,6 +2088,100 @@ def test_find_eqpt(x0, ix, u0, iu, y0, iy, dx0, idx, dt, x_expect, u_expect):
|
2087 | 2088 | np.testing.assert_allclose(np.array(ueq), u_expect, atol=1e-6)
|
2088 | 2089 |
|
2089 | 2090 |
|
| 2091 | +# Test out new operating point version of find_eqpt |
| 2092 | +def test_find_operating_point(): |
| 2093 | + dt = 1 |
| 2094 | + sys = ct.NonlinearIOSystem( |
| 2095 | + eqpt_rhs, eqpt_out, dt=dt, states=3, inputs=2, outputs=2) |
| 2096 | + |
| 2097 | + # Conditions that lead to no exact solution (from previous unit test) |
| 2098 | + x0 = 0; ix = None |
| 2099 | + u0 = [-1, 0]; iu = None |
| 2100 | + y0 = None; iy = None |
| 2101 | + dx0 = None; idx = None |
| 2102 | + |
| 2103 | + # Default version: no equilibrium solution => returns None |
| 2104 | + op_point = ct.find_operating_point( |
| 2105 | + sys, x0, u0, y0, ix=ix, iu=iu, iy=iy, dx0=dx0, idx=idx) |
| 2106 | + assert op_point.states is None |
| 2107 | + assert op_point.inputs is None |
| 2108 | + assert op_point.result.success is False |
| 2109 | + |
| 2110 | + # Change the method to Levenberg-Marquardt (gives nearest point) |
| 2111 | + op_point = ct.find_operating_point( |
| 2112 | + sys, x0, u0, y0, ix=ix, iu=iu, iy=iy, dx0=dx0, idx=idx, |
| 2113 | + root_method='lm') |
| 2114 | + assert op_point.states is not None |
| 2115 | + assert op_point.inputs is not None |
| 2116 | + assert op_point.result.success is True |
| 2117 | + |
| 2118 | + # Make sure we get a solution if we ask for the result explicitly |
| 2119 | + op_point = ct.find_operating_point( |
| 2120 | + sys, x0, u0, y0, ix=ix, iu=iu, iy=iy, dx0=dx0, idx=idx, |
| 2121 | + return_result=True) |
| 2122 | + assert op_point.states is not None |
| 2123 | + assert op_point.inputs is not None |
| 2124 | + assert op_point.result.success is False |
| 2125 | + |
| 2126 | + # Check to make sure unknown keywords are caught |
| 2127 | + with pytest.raises(TypeError, match="unrecognized keyword"): |
| 2128 | + ct.find_operating_point(sys, x0, u0, unknown=None) |
| 2129 | + |
| 2130 | + |
| 2131 | +def test_operating_point(): |
| 2132 | + dt = 1 |
| 2133 | + sys = ct.NonlinearIOSystem( |
| 2134 | + eqpt_rhs, eqpt_out, dt=dt, states=3, inputs=2, outputs=2) |
| 2135 | + |
| 2136 | + # Find the operating point near the origin |
| 2137 | + op_point = ct.find_operating_point(sys, 0, 0) |
| 2138 | + |
| 2139 | + # Linearize the old fashioned way |
| 2140 | + linsys_orig = ct.linearize(sys, op_point.states, op_point.inputs) |
| 2141 | + |
| 2142 | + # Linearize around the operating point |
| 2143 | + linsys_oppt = ct.linearize(sys, op_point) |
| 2144 | + |
| 2145 | + np.testing.assert_allclose(linsys_orig.A, linsys_oppt.A) |
| 2146 | + np.testing.assert_allclose(linsys_orig.B, linsys_oppt.B) |
| 2147 | + np.testing.assert_allclose(linsys_orig.C, linsys_oppt.C) |
| 2148 | + np.testing.assert_allclose(linsys_orig.D, linsys_oppt.D) |
| 2149 | + |
| 2150 | + # Call find_operating_point with method and keyword arguments |
| 2151 | + op_point = ct.find_operating_point( |
| 2152 | + sys, 0, 0, root_method='lm', root_kwargs={'tol': 1e-6}) |
| 2153 | + |
| 2154 | + # Make sure we can get back the right arguments in a tuple |
| 2155 | + op_point = ct.find_operating_point(sys, 0, 0, return_outputs=True) |
| 2156 | + assert len(op_point) == 3 |
| 2157 | + assert isinstance(op_point[0], np.ndarray) |
| 2158 | + assert isinstance(op_point[1], np.ndarray) |
| 2159 | + assert isinstance(op_point[2], np.ndarray) |
| 2160 | + |
| 2161 | + with pytest.warns(FutureWarning, match="return_outputs"): |
| 2162 | + op_point = ct.find_operating_point(sys, 0, 0, return_y=True) |
| 2163 | + assert len(op_point) == 3 |
| 2164 | + assert isinstance(op_point[0], np.ndarray) |
| 2165 | + assert isinstance(op_point[1], np.ndarray) |
| 2166 | + assert isinstance(op_point[2], np.ndarray) |
| 2167 | + |
| 2168 | + # Make sure we can get back the right arguments in a tuple |
| 2169 | + op_point = ct.find_operating_point(sys, 0, 0, return_result=True) |
| 2170 | + assert len(op_point) == 3 |
| 2171 | + assert isinstance(op_point[0], np.ndarray) |
| 2172 | + assert isinstance(op_point[1], np.ndarray) |
| 2173 | + assert isinstance(op_point[2], scipy.optimize.OptimizeResult) |
| 2174 | + |
| 2175 | + # Make sure we can get back the right arguments in a tuple |
| 2176 | + op_point = ct.find_operating_point( |
| 2177 | + sys, 0, 0, return_result=True, return_outputs=True) |
| 2178 | + assert len(op_point) == 4 |
| 2179 | + assert isinstance(op_point[0], np.ndarray) |
| 2180 | + assert isinstance(op_point[1], np.ndarray) |
| 2181 | + assert isinstance(op_point[2], np.ndarray) |
| 2182 | + assert isinstance(op_point[3], scipy.optimize.OptimizeResult) |
| 2183 | + |
| 2184 | + |
2090 | 2185 | def test_iosys_sample():
|
2091 | 2186 | csys = ct.rss(2, 1, 1)
|
2092 | 2187 | dsys = csys.sample(0.1)
|
|
0 commit comments