python - 与 c++ 相比,与solve_ivp 集成非常慢

标签 python scipy numerical-integration

使用 scipy.integrate 中的solve_ivp 来集成刚性系统大约需要 3 分钟才能完成。积分器是:

sol = solve_ivp(DC_model,[t0,tf],y0,method='LSODA')

使用 C++ 和 Boost 库求解同一系统需要 2.12742 秒。这是一个巨大的差异。 有办法缩短 python 脚本的执行时间吗?

完整代码:

import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import solve_ivp 
import time

def DC_model(t,y):
    T,H,CTL,Den,IL2,FBeta,FGamma,Ml = y

    dT = 0.002 * T * np.log(1e12 / T) - (0.1136 * T * CTL * Ml / (50 + Ml)) * ((0.69 * FBeta + 1e4) / (FBeta + 1e4))
    dH = 1e-4 - 0.005 * H + 10e-2 * Den*(H*(1 - H / 1))
    dC = 1e-4 - 0.01925 * CTL + 0.00004e-2 * IL2*(CTL*(1 - CTL / 1))
    dDen = -0.009625 * Den * CTL
    dI = 1e-2 * H * Den - 1e-7 * CTL * IL2 - 1e-2 * IL2
    dFbeta = 5.57e-6 * T - 6.93 * FBeta
    dFgamma = 1.02e-4 * CTL - 0.102 * FGamma
    dMl = 1.44 + (2.89 * FGamma) / (FGamma + 3.38e5) - 0.0144 * Ml

    return np.array([dT,dH,dC,dDen,dI,dFbeta,dFgamma,dMl])


y0 = [6e4, 0, 0, 0, 0, 0, 0, 0]
t0 = 0.0 
delay = 232
tf = 168 + delay
ef=0.05
start = time.time()
sol = solve_ivp(DC_model,[t0,tf],y0,method='LSODA')

y0 = sol.y[:,-1] + [0, 0, 0, 1e6 * ef, 0, 0, 0, 0]
t0 = tf 
tf = tf + 168   
sol = solve_ivp(DC_model,[t0,tf],y0,method='LSODA')

y0 = sol.y[:,-1] + [0, 0, 0, 1e6 * ef, 0, 0, 0, 0]
t0 = tf 
tf = tf + 168   
sol = solve_ivp(DC_model,[t0,tf],y0,method='LSODA')

y0 = sol.y[:,-1] + [0, 0, 0, 1e6 * ef, 0, 0, 0, 0]
t0 = tf 
tf = 1400   
sol = solve_ivp(DC_model,[t0,tf],y0,method='LSODA')
end = time.time()
print('Solving took: ' + str((end-start)/60) + ' min')

最佳答案

我为 LSODA 编写了一个 python 包装器,它应该与 C/C++ 一样快:https://github.com/Nicholaswogan/NumbaLSODA .

不过我有点困惑,因为当我运行上面的代码时,它使用 solve_ivp 执行得非常快。无论如何,这是使用 NumbaLSODA 的代码:

import matplotlib.pyplot as plt
import numpy as np 
import time

from NumbaLSODA import lsoda_sig, lsoda
import numba as nb


@nb.cfunc(lsoda_sig)
def DC_model(t, y_, dy, p):
    y = nb.carray(y_, (8,))

    
    T,H,CTL,Den,IL2,FBeta,FGamma,Ml = y

    dT = 0.002 * T * np.log(1e12 / T) - (0.1136 * T * CTL * Ml / (50 + Ml)) * ((0.69 * FBeta + 1e4) / (FBeta + 1e4))
    dH = 1e-4 - 0.005 * H + 10e-2 * Den*(H*(1 - H / 1))
    dC = 1e-4 - 0.01925 * CTL + 0.00004e-2 * IL2*(CTL*(1 - CTL / 1))
    dDen = -0.009625 * Den * CTL
    dI = 1e-2 * H * Den - 1e-7 * CTL * IL2 - 1e-2 * IL2
    dFbeta = 5.57e-6 * T - 6.93 * FBeta
    dFgamma = 1.02e-4 * CTL - 0.102 * FGamma
    dMl = 1.44 + (2.89 * FGamma) / (FGamma + 3.38e5) - 0.0144 * Ml

    dy_ = np.array([dT,dH,dC,dDen,dI,dFbeta,dFgamma,dMl])
    for i in range(len(dy_)):
        dy[i] = dy_[i]

funcptr = DC_model.address

@nb.njit
def main():
    y0 = np.array([6e4, 0, 0, 0, 0, 0, 0, 0],np.float64)
    t0 = 0.0 
    delay = 232
    tf = 168 + delay
    ef=0.05
    t_eval = np.linspace(t0,tf,100)
    sol, success = lsoda(funcptr, y0, t_eval)

    y0 = sol[-1] + np.array([0, 0, 0, 1e6 * ef, 0, 0, 0, 0],np.float64)
    t0 = tf 
    tf = tf + 168   
    t_eval = np.linspace(t0,tf,100)
    sol, success = lsoda(funcptr, y0, t_eval)

    y0 = sol[-1] + np.array([0, 0, 0, 1e6 * ef, 0, 0, 0, 0],np.float64)
    t0 = tf 
    tf = tf + 168 
    t_eval = np.linspace(t0,tf,100)
    sol, success = lsoda(funcptr, y0, t_eval)

    y0 = sol[-1] + np.array([0, 0, 0, 1e6 * ef, 0, 0, 0, 0],np.float64)
    t0 = tf 
    tf = 1400   
    t_eval = np.linspace(t0,tf,100)
    sol, success = lsoda(funcptr, y0, t_eval)
   
main() # to compile the code
start = time.time()
main()
end = time.time()
print('Solving took: ' + str((end-start)) + ' sec')

结果

Solving took: 0.00039005279541015625 sec

关于python - 与 c++ 相比,与solve_ivp 集成非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55000533/

相关文章:

python - 使用 Python 的 ctypes 传递/读取声明为 "struct_name *** param_name"的参数?

python - 在 Python 中从图像中提取连接的对象

python - 二维高斯函数的积分(python)

python - 将 MATLAB quadgk 集成转换为具有长函数的 Scipy quad 以进行集成(传递 lambda 函数的任何替代方法?)

python - BeautifulSoup- find_all- 订单保存

python - Cloud Dataflow python 转换函数可以使用第三方库吗?

javascript - 如何将 Google 地点自动完成功能添加到 Flask 中?

python - 使用分组边界的 SciPy 优化

python - 没有名为 scipy.stats 的模块 - 为什么尽管安装了 scipy

python - Python 中的 Verlet 集成导致粒子逃跑