簡體   English   中英

使用odeint在數組中具有時間相關常數的微分方程系統

[英]System of differential equations with time dependent constants in arrays, using odeint

假設我有一個微分方程組,我想用odeint求解。 系統的某些常量與時間有關,我將它們的值存儲在數組中(形狀為(8000,)的a,b,c和d)。 我希望系統在每個時間步使用這些常量的不同值。 請參見簡化的代碼示例:

t = np.linspace(0,100,8000)

a = np.array([0, 5, 6, 12, 1.254, ..., 0.145])     # shape (8000, )
b = np.array([1.45, 5.9125, 1.367, ..., 3.1458])
c = np.array([0.124, 0.258, 0.369, ..., 0.147])
d = np.array([7.145, 5.123, 6.321, ..., 0.125])

def system(k,t):
    vcx_i = k[0]
    vcy_i = k[1]
    psi_i = k[2]
    wz_i = k[3]

    vcx_i_dot = a*np.cos(psi_i)-b*np.sin(psi_i)
    vcy_i_dot = b*np.cos(psi_i)+a*np.sin(psi_i)
    psi_i_dot = wz_i
    wz_i_dot = c*vcx_i-a*np.sin(psi_i)-d*np.sin(psi_i)-b*np.cos(psi_i)

    return [vcx_i_dot, vcy_i_dot, psi_i_dot wz_i_dot]

k0 = [0.1257, 0, 0, 0]

k = odeint(system, k0, t)

vcx_i = k[:,0]
vcy_i = k[:,1]
psi_i = k[:,2]
wz_i = k[:,3]

psi_i = [system(t_i, k_i)[2] for k_i, t_i in zip(k,t)]
wz_i = [system(t_i, k_i)[3] for k_i, t_i in zip(k,t)]

到目前為止,我找到的最相關的解決方案是: 使用scipy.integrate.odeint解決一個odes系統(具有不斷變化的常數!)? 但是由於我只有數組中變量的值,而沒有依賴於時間的變量方程(例如a = f(t)),因此我嘗試在數組中的值之間進行插值,如下所示: ODEINT使用多個參數(與時間有關)時,我設法使代碼運行時沒有錯誤,但是總時間卻急劇增加,解決的系統結果是完全錯誤的。 我嘗試了在這里找到的任何可能的插值類型: https : //docs.scipy.org/doc/scipy/reference/generation/scipy.interpolate.interp1d.html但結果仍然錯誤。 這意味着我的插值方法不是最好的,或者我在數組中的點(8000個值)太多,無法在它們之間進行插值並正確地求解系統。 解決這樣一個系統的正確方法是什么? 我是python的新手,並且在Ubuntu 16.04 LTS上使用python 2.7.12。 先感謝您。

插值器通常非常快,因此您的函數中可能還有其他內容。 但是,您可以嘗試使用不同的插值器(例如InterpolatedUnivariateSpline ),或減少插值節點以提高速度。 但我的目標是您的集成。

最近, odeodeint被其他更靈活的功能所取代(請參閱此處

我將從顯式方法而不是隱式方法開始( solve_ivp默認值為runge kutta,而odeint默認值為LSODA):

interp = scipy.interpolate.interp1d(t,(a,b,c,d))

def system(t,k):
    vcx_i = k[0]
    vcy_i = k[1]
    psi_i = k[2]
    wz_i = k[3]
    a, b, c, d = interp(t)

    vcx_i_dot = a*np.cos(psi_i)-b*np.sin(psi_i)
    vcy_i_dot = b*np.cos(psi_i)+a*np.sin(psi_i)
    psi_i_dot = wz_i
    wz_i_dot = c*vcx_i-a*np.sin(psi_i)-d*np.sin(psi_i)-b*np.cos(psi_i)
    return [vcx_i_dot, vcy_i_dot, psi_i_dot, wz_i_dot]

k0 = [0.1257, 0, 0, 0]
steps = 1
method = 'RK23'
atol = 1e-3
s = solve_ivp(dydt, (0, 100), k0, method=method, t_eval=t, atol=atol, vectorized=True)

您可以增加/減少atol或更改方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM