使用solve_ivp解决ODE变得异常缓慢或完全冻结

时间:2019-01-25 15:41:54

标签: python scipy differential-equations

我使用solve_ivp来求解ODE:

def test_ode(t, y):
    dydt = C - y + (y ** 8 / (1 + y ** 8))
    return dydt

steady_state = []
for C in np.linspace(0, 1, 1001):
    sol = solve_ivp(test_ode, [0, 1e06], [0], method='BDF')
    steady_state.append(sol.y[0][-1])

这给了我一个RuntimeWarning

ETA:  --:--:--/anaconda3/lib/python3.6/site-packages/scipy/integrate/_ivp/bdf.py:418: 
RuntimeWarning: divide by zero encountered in power
  factors = error_norms ** (-1 / np.arange(order, order + 3))

但更糟糕的是,运行基本上停止了(或至少变得极其缓慢)。用[0]替换初始值[1e-08]不能解决问题。我该如何解决?

1 个答案:

答案 0 :(得分:1)

您可以使用 NumbaLSODA: https://github.com/Nicholaswogan/NumbaLSODA 。类似于solve_ivp,但是所有的代码都可以编译。所以速度非常快:

from NumbaLSODA import lsoda_sig, lsoda
import numpy as np
import numba as nb
import time

@nb.cfunc(lsoda_sig)
def test_ode(t, y_, dydt, p):
    y = y_[0]
    C = p[0]
    dydt[0] = C - y + (y ** 8 / (1 + y ** 8))
funcptr = test_ode.address

@nb.njit()
def main():
    steady_state = np.empty((1001,),np.float64)
    CC = np.linspace(0, 1, 1001)
    y0 = np.array([0.0])
    for i in range(len(CC)):
        data = np.array([CC[i]],np.float64)
        t_eval = np.array([0.0, 1.0e6])
        sol, success = lsoda(funcptr, y0, t_eval, data = data)
        steady_state[i] = sol[-1,0]
    return steady_state

main()
start = time.time()
steady_state = main()
end = time.time()
print(end-start)

结果是 0.013 秒