@@ -286,19 +286,19 @@ def test_algebraic_loop(self):
286286 # Set up parameters for simulation
287287 T , U , X0 = self .T , self .U , self .X0
288288
289- # Single nonlinear system - no states
290- ios_t , ios_y = ios .input_output_response (nlios , T , U , X0 )
289+ # Single nonlinear system - no states
290+ ios_t , ios_y = ios .input_output_response (nlios , T , U )
291291 np .testing .assert_array_almost_equal (ios_y , U * U , decimal = 3 )
292292
293293 # Composed nonlinear system (series)
294- ios_t , ios_y = ios .input_output_response (nlios1 * nlios2 , T , U , X0 )
294+ ios_t , ios_y = ios .input_output_response (nlios1 * nlios2 , T , U )
295295 np .testing .assert_array_almost_equal (ios_y , U ** 4 , decimal = 3 )
296296
297297 # Composed nonlinear system (parallel)
298- ios_t , ios_y = ios .input_output_response (nlios1 + nlios2 , T , U , X0 )
298+ ios_t , ios_y = ios .input_output_response (nlios1 + nlios2 , T , U )
299299 np .testing .assert_array_almost_equal (ios_y , 2 * U ** 2 , decimal = 3 )
300300
301- # Nonlinear system composed with LTI system (series)
301+ # Nonlinear system composed with LTI system (series) -- with states
302302 ios_t , ios_y = ios .input_output_response (
303303 nlios * lnios * nlios , T , U , X0 )
304304 lti_t , lti_y , lti_x = ct .forced_response (linsys , T , U * U , X0 )
@@ -323,7 +323,7 @@ def test_algebraic_loop(self):
323323 (1 , (0 , 0 , - 1 ))),
324324 0 , 0
325325 )
326- args = (iosys , T , U , X0 )
326+ args = (iosys , T , U )
327327 self .assertRaises (RuntimeError , ios .input_output_response , * args )
328328
329329 # Algebraic loop due to feedthrough term
@@ -392,7 +392,7 @@ def test_neg(self):
392392 # Static nonlinear system
393393 nlios = ios .NonlinearIOSystem (None , \
394394 lambda t , x , u , params : u * u , inputs = 1 , outputs = 1 )
395- ios_t , ios_y = ios .input_output_response (- nlios , T , U , X0 )
395+ ios_t , ios_y = ios .input_output_response (- nlios , T , U )
396396 np .testing .assert_array_almost_equal (ios_y , - U * U , decimal = 3 )
397397
398398 # Linear system with input nonlinearity
@@ -807,6 +807,50 @@ def test_named_signals(self):
807807 np .testing .assert_array_almost_equal (ss_feedback .C , lin_feedback .C )
808808 np .testing .assert_array_almost_equal (ss_feedback .D , lin_feedback .D )
809809
810+ def test_named_signals_linearize_inconsistent (self ):
811+ """Mare sure that providing inputs or outputs not consistent with
812+ updfcn or outfcn fail
813+ """
814+
815+ def updfcn (t , x , u , params ):
816+ """2 inputs, 2 states"""
817+ return np .array (
818+ np .dot (self .mimo_linsys1 .A , np .reshape (x , (- 1 , 1 )))
819+ + np .dot (self .mimo_linsys1 .B , np .reshape (u , (- 1 , 1 )))
820+ ).reshape (- 1 ,)
821+
822+ def outfcn (t , x , u , params ):
823+ """2 states, 2 outputs"""
824+ return np .array (
825+ self .mimo_linsys1 .C * np .reshape (x , (- 1 , 1 ))
826+ + self .mimo_linsys1 .D * np .reshape (u , (- 1 , 1 ))
827+ ).reshape (- 1 ,)
828+
829+ for inputs , outputs in [
830+ (('u[0]' ), ('y[0]' , 'y[1]' )), # not enough u
831+ (('u[0]' , 'u[1]' , 'u[toomuch]' ), ('y[0]' , 'y[1]' )),
832+ (('u[0]' , 'u[1]' ), ('y[0]' )), # not enough y
833+ (('u[0]' , 'u[1]' ), ('y[0]' , 'y[1]' , 'y[toomuch]' ))]:
834+ sys1 = ios .NonlinearIOSystem (updfcn = updfcn ,
835+ outfcn = outfcn ,
836+ inputs = inputs ,
837+ outputs = outputs ,
838+ states = self .mimo_linsys1 .states ,
839+ name = 'sys1' )
840+ self .assertRaises (ValueError , sys1 .linearize , [0 , 0 ], [0 , 0 ])
841+
842+ sys2 = ios .NonlinearIOSystem (updfcn = updfcn ,
843+ outfcn = outfcn ,
844+ inputs = ('u[0]' , 'u[1]' ),
845+ outputs = ('y[0]' , 'y[1]' ),
846+ states = self .mimo_linsys1 .states ,
847+ name = 'sys1' )
848+ for x0 , u0 in [([0 ], [0 , 0 ]),
849+ ([0 , 0 , 0 ], [0 , 0 ]),
850+ ([0 , 0 ], [0 ]),
851+ ([0 , 0 ], [0 , 0 , 0 ])]:
852+ self .assertRaises (ValueError , sys2 .linearize , x0 , u0 )
853+
810854 def test_lineariosys_statespace (self ):
811855 """Make sure that a LinearIOSystem is also a StateSpace object"""
812856 iosys_siso = ct .LinearIOSystem (self .siso_linsys )
@@ -931,7 +975,7 @@ def predprey(t, x, u, params={}):
931975def pvtol (t , x , u , params = {}):
932976 from math import sin , cos
933977 m = params .get ('m' , 4. ) # kg, system mass
934- J = params .get ('J' , 0.0475 ) # kg m^2, system inertia
978+ J = params .get ('J' , 0.0475 ) # kg m^2, system inertia
935979 r = params .get ('r' , 0.25 ) # m, thrust offset
936980 g = params .get ('g' , 9.8 ) # m/s, gravitational constant
937981 c = params .get ('c' , 0.05 ) # N s/m, rotational damping
@@ -946,7 +990,7 @@ def pvtol(t, x, u, params={}):
946990def pvtol_full (t , x , u , params = {}):
947991 from math import sin , cos
948992 m = params .get ('m' , 4. ) # kg, system mass
949- J = params .get ('J' , 0.0475 ) # kg m^2, system inertia
993+ J = params .get ('J' , 0.0475 ) # kg m^2, system inertia
950994 r = params .get ('r' , 0.25 ) # m, thrust offset
951995 g = params .get ('g' , 9.8 ) # m/s, gravitational constant
952996 c = params .get ('c' , 0.05 ) # N s/m, rotational damping
0 commit comments