【问题标题】:How to pass more data into scipy.integrate.odeint如何将更多数据传递到 scipy.integrate.odeint
【发布时间】:2016-06-05 19:35:13
【问题描述】:

我正在使用 odeint 并且需要传递一个随时间变化的力以及我正在积分的位置和速度。力是一个已知的数据数组,因此不需要求解,只需将其代入方程即可。

代码如下:

def dr_dt(y, t):

    RHO = 1225.0          
    C_D = 0.75             
    A = 6.25e-4            
    G = 9.81               
    M_O = 100.0            
    M_P = 10.8             
    M_F = M_O - M_P        
    T = 1.86               

    M_E = (M_O - M_F) / T

    dy0 = y[1]
    dy1 = (f / (M_O - M_E * t)) - ((1.0 * RHO * C_D * A * y[1]**2)  / (2.0 * (M_O - M_E * t))) - G
    return dy0, dy1

t = np.array([0.031, 0.092, 0.139, 0.192, 0.209, 0.231, 0.248, 0.292, 0.370, 0.475, 0.671, 0.702,
          0.723, 0.850, 1.063, 1.211, 1.242, 1.303, 1.468, 1.656, 1.821, 1.834, 1.847, 1.860])
f = np.array([0.946, 4.826, 9.936, 14.090, 11.446, 7.381, 6.151, 5.489, 4.921, 4.448, 4.258, 
          4.542, 4.164, 4.448, 4.353, 4.353, 4.069, 4.258, 4.353, 4.448, 4.448, 2.933, 1.325, 0.000])

r_o = 0.0
v_o = 0.0
y = odeint(dr_dt, [r_o, v_o], t)

我知道 odeint 中有 Dfun 参数,我相信在这种情况下可以帮助我,但我找不到太多关于如何使用它的信息。如果有人可以传递一些信息,那就太好了。或者关于在这种情况下如何使用 interp1d 的任何信息,或者只是将 f 带入方程的任何其他方法。

谢谢

(如果标题中没有包含 scipy 的话,这是使用 python 2.7。)

【问题讨论】:

    标签: python-2.7 scipy interpolation ode


    【解决方案1】:

    您可以尝试从您的力数据创建一个插值对象并将其作为参数发送到dr_dt

    import numpy as np
    from scipy.integrate import odeint
    from scipy.interpolate import interp1d
    
    def dr_dt(y, t, fint):
    
        RHO = 1225.0          
        C_D = 0.75             
        A = 6.25e-4            
        G = 9.81               
        M_O = 100.0            
        M_P = 10.8             
        M_F = M_O - M_P        
        T = 1.86               
    
        M_E = (M_O - M_F) / T
    
        dy0 = y[1]
        dy1 = (fint(t) / (M_O - M_E * t)) - ((1.0 * RHO * C_D * A * y[1]**2)  / (2.0 * (M_O - M_E * t))) - G
        return dy0, dy1
    
    t = np.array([0.031, 0.092, 0.139, 0.192, 0.209, 0.231, 0.248, 0.292, 0.370, 0.475, 0.671, 0.702,
              0.723, 0.850, 1.063, 1.211, 1.242, 1.303, 1.468, 1.656, 1.821, 1.834, 1.847, 1.860])
    f = np.array([0.946, 4.826, 9.936, 14.090, 11.446, 7.381, 6.151, 5.489, 4.921, 4.448, 4.258, 
              4.542, 4.164, 4.448, 4.353, 4.353, 4.069, 4.258, 4.353, 4.448, 4.448, 2.933, 1.325, 0.000])
    
    r_o = 0.0
    v_o = 0.0
    
    fint = interp1d(t, f)
    y = odeint(dr_dt, [r_o, v_o], t[:-1], args=(fint,))
    

    (我发现我必须省略最后一个时间点,否则它会尝试插入超出原始数据的范围......我不知道这对你是否重要)。

    编辑:如果这对您来说很重要,那么还有其他 ode 函数可以积分您的微分方程,而不会超出系列中的最后一个时间点,如 this question 中所述。

    【讨论】:

    • 亲爱的,谢谢你帮了大忙。一切正常,除了我还有一个问题。我刚刚意识到我仍然收到不正确的值,并意识到我在 f 上的单位是错误的。我需要将它们缩放一个因子或 1000,现在收到与您在保留所有 t 值时收到的相同错误。A value in x_new is above the interpolation range。有什么建议吗?
    • 因此,据我观察,t 的值运行并最终达到 1.86672,超过了提供的值,然后引发错误。唯一的问题是我不明白如何防止这种情况/为什么会发生。
    • 另一个更新。看起来 f 停止在 4448 上。所以据我所知, odeint 强制 t 跳过其限制,反过来,停止 f 短(无法插值)并引发错误。但仍然没有修复。
    • 已解决。结果odeint 经常运行函数超过请求的值。不完全确定为什么。但这就是一旦引入interp1d 就会导致错误的原因。我假设interp1d 不允许函数超过其值,但odeint 尝试这样做。在stackoverflow.com/questions/25031966/…找到解决方案。
    • 太好了——我很高兴你让插值工作。我将在此问题/答案的链接中进行编辑。
    猜你喜欢
    • 1970-01-01
    • 2011-05-14
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-24
    相关资源
    最近更新 更多