2011-04-13 55 views
4

我是相對較新的python和scipy,是從MATLAB轉換。我正在做scipy.integrate中的odeint函數的快速測試,並遇到了這個潛在的錯誤。考慮下面的片段:odeint中可能存在的錯誤<-> interp1d interplay?

from scipy import * 
from scipy.integrate import odeint 
from scipy.interpolate import interp1d 
from pylab import * 

# ODE system with forcing function u(t) 
def sis(x,t,u): 
    return [x[1], u(t)] 

# Solution time span 
t = linspace(0, 10, 1e3) 

# Profile for forcing function u(t) 
acel = lambda t: 3*(t<2)-3*(t>8) 

# Interpolator for acelerator 
acel_interp = interp1d(t, acel(t), bounds_error=False, fill_value=0)  

# ODE integration with u(t) = acel, a lambda function 
x_1 = odeint(sis, [0,0], t, args=(acel,))   # Correct result 
# ODE integration with u(t) = acel_interp, an interpolator 
x_2 = odeint(sis, [0,0], t, args=(acel_interp,))  # Incorrect result 

我做了一個情節,說明兩個結果的差異,click here

你對此有何看法,至少對我而言,結果之間存在着毫無根據的區別?我在Python 2.6.6上使用NumPy版本1.5.0和SciPy版本0.8.0

+1

恭喜從Matlab開關。我在18個月前採取行動。能夠訪問所有其他Python功能並能夠與尚未支付數千次Matlab許可證的人分享您的代碼是非常好的。 – 2011-04-17 11:41:37

回答

3

這不是一個錯誤。問題在於,您已將bound_error設爲False,並用零填充這些值。如果您在原始代碼中將bound_error設置爲True,則可以看到您超出了插值的範圍,因此在積分中置入了零(因此產生的值與您在範圍如同您對x_1的lambda所做的那樣)。

請嘗試以下操作,您會看到事情正常運行。基本上我只是擴展了t來覆蓋足夠大的值範圍,以覆蓋您使用插值的範圍。

from scipy import * 
from scipy.integrate import odeint 
from scipy.interpolate import interp1d 
from pylab import * 

# ODE system with forcing function u(t) 
def sis(x,t,u): 
    return [x[1], u(t)] 

# Solution time span 
t = linspace(0, 10, 1e3) 
t_interp = linspace(0,20,2e3) 

# Profile for forcing function u(t) 
acel = lambda t: 3*(t<2)-3*(t>8) 

# Interpolator for acelerator 
acel_interp = interp1d(t_interp, acel(t_interp))  

# ODE integration with u(t) = acel, a lambda function 
x_1 = odeint(sis, [0,0], t, args=(acel,))    
# ODE integration with u(t) = acel_interp, an interpolator 
x_2 = odeint(sis, [0,0], t, args=(acel_interp,))  
+0

你用13分鐘打我:)當's()'被評估時,當我捕捉到'u(t)'引發的第一個異常時,'t'的值是'17.8811987021'。然而,'odeint()'被告知從0到10進行整合。這是如何工作的? – lafras 2011-04-13 14:32:20

+1

看看'x_2,idct = odeint(sis,[0,0],t,args =(acel_interp,),full_output = True); IDCT [ 'TCUR']'。無論採用何種整合方案,都需要在't'範圍之外進行評估。正如文檔所述:「'tcur' - 每個時間步長到達t值的矢量(總是至少與輸入時間一樣大)」。 – JoshAdel 2011-04-13 14:40:47

+0

感謝您的智慧!我已經接受你的答案,因爲它正確工作。但是我仍然不明白爲什麼它不能與原始代碼一起工作,因爲最初的時間間隔('t'數組)包含'acel(t)'中的所有相關變化(最後一次轉換髮生在t = 8 ,時間跨度設爲t = 10)。你能否詳細闡述一下呢? – 2011-04-15 10:50:54

相關問題