使用odeint在数组中具有时间相关常数的微分方程系统

时间:2019-02-21 13:30:48

标签: arrays python-2.7 scipy odeint

比方说,我有一个微分方程组,我想用odeint求解。系统的某些常量与时间有关,我将它们的值存储在数组中(形状为(8000,)的a,b,c和d)。我希望系统在每个时间步使用这些常量的不同值。请参见简化的代码示例:

resolv.conf

到目前为止,我发现的最相关的解决方案是:Solving a system of odes (with changing constant!) using scipy.integrate.odeint?但由于我只有数组中变量的值,而没有依赖于时间的变量方程(例如a = f(t)) ,我尝试在数组中的值之间进行插值,如下所示:ODEINT with multiple parameters (time-dependent)我设法使代码运行时没有错误,但是总时间急剧增加,解决的系统结果完全错误。我尝试了在https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html处找到的任何可能的插值类型,但结果仍然错误。这意味着我的插值方法不是最好的,或者我在数组中的点(8000个值)太多,无法在它们之间进行插值并正确地求解系统。解决这样一个系统的正确方法是什么? 我是python的新手,并且在Ubuntu 16.04 LTS上使用python 2.7.12。先感谢您。

1 个答案:

答案 0 :(得分:1)

内插器通常非常快,因此您的函数中可能还有其他内容。但是,您可以尝试使用不同的插值器(例如InterpolatedUnivariateSpline),或减少插值节点以提高速度。但我的目标是您的集成。

最近,odeodeint被其他更灵活的功能所取代(请参见here

我将从显式方法而不是隐式方法开始(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或更改方法。