@@ -60,6 +60,14 @@ def siso_ss2(self, siso_ss1):
6060
6161 return T
6262
63+ @pytest .fixture
64+ def siso_ss2_dtnone (self , siso_ss2 ):
65+ """System with unspecified timebase"""
66+ ss2 = siso_ss2 .sys
67+ T = TSys (StateSpace (ss2 .A , ss2 .B , ss2 .C , 0 , None ))
68+ T .t = np .arange (0 , 10 , 1. )
69+ return T
70+
6371 @pytest .fixture
6472 def siso_tf1 (self ):
6573 # Create some transfer functions
@@ -349,7 +357,7 @@ def mimo_tf_step_info(self,
349357 @pytest .fixture
350358 def tsystem (self ,
351359 request ,
352- siso_ss1 , siso_ss2 , siso_tf1 , siso_tf2 ,
360+ siso_ss1 , siso_ss2 , siso_ss2_dtnone , siso_tf1 , siso_tf2 ,
353361 mimo_ss1 , mimo_ss2 , mimo_tf2 ,
354362 siso_dtf0 , siso_dtf1 , siso_dtf2 ,
355363 siso_dss1 , siso_dss2 ,
@@ -361,6 +369,7 @@ def tsystem(self,
361369 siso_tf_asymptotic_from_neg1 ):
362370 systems = {"siso_ss1" : siso_ss1 ,
363371 "siso_ss2" : siso_ss2 ,
372+ "siso_ss2_dtnone" : siso_ss2_dtnone ,
364373 "siso_tf1" : siso_tf1 ,
365374 "siso_tf2" : siso_tf2 ,
366375 "mimo_ss1" : mimo_ss1 ,
@@ -840,10 +849,11 @@ def test_default_timevector_functions_d(self, fun, dt):
840849 @pytest .mark .parametrize ("tsystem" ,
841850 ["siso_ss2" , # continuous
842851 "siso_tf1" ,
843- "siso_dss1" , # no timebase
852+ "siso_dss1" , # unspecified sampling time
844853 "siso_dtf1" ,
845854 "siso_dss2" , # matching timebase
846855 "siso_dtf2" ,
856+ "siso_ss2_dtnone" , # undetermined timebase
847857 "mimo_ss2" , # MIMO
848858 pytest .param ("mimo_tf2" , marks = slycotonly ),
849859 "mimo_dss1" ,
@@ -868,9 +878,9 @@ def test_time_vector(self, tsystem, fun, squeeze, matarrayout):
868878 kw ['T' ] = t
869879 if fun == forced_response :
870880 kw ['U' ] = np .vstack ([np .sin (t ) for i in range (sys .ninputs )])
871- elif fun == forced_response and isctime (sys ):
881+ elif fun == forced_response and isctime (sys , strict = True ):
872882 pytest .skip ("No continuous forced_response without time vector." )
873- if hasattr (tsystem . sys , "nstates" ):
883+ if hasattr (sys , "nstates" ):
874884 kw ['X0' ] = np .arange (sys .nstates ) + 1
875885 if sys .ninputs > 1 and fun in [step_response , impulse_response ]:
876886 kw ['input' ] = 1
@@ -884,14 +894,18 @@ def test_time_vector(self, tsystem, fun, squeeze, matarrayout):
884894 if hasattr (tsystem , 't' ):
885895 # tout should always match t, which has shape (n, )
886896 np .testing .assert_allclose (tout , tsystem .t )
897+ elif fun == forced_response and sys .dt in [None , True ]:
898+ np .testing .assert_allclose (
899+ np .diff (tout ), np .full_like (tout [:- 1 ], 1. ))
887900
888901 if squeeze is False or not sys .issiso ():
889902 assert yout .shape [0 ] == sys .noutputs
890903 assert yout .shape [- 1 ] == tout .shape [0 ]
891904 else :
892905 assert yout .shape == tout .shape
893906
894- if sys .dt > 0 and sys .dt is not True and not np .isclose (sys .dt , 0.5 ):
907+ if sys .isdtime (strict = True ) and sys .dt is not True and not \
908+ np .isclose (sys .dt , 0.5 ):
895909 kw ['T' ] = np .arange (0 , 5 , 0.5 ) # incompatible timebase
896910 with pytest .raises (ValueError ):
897911 fun (sys , ** kw )
0 commit comments