odeint
是 C 代码的 Python 包装器,它调用 LSODA(一个 Fortran 子例程),它调用 C 代码来调用代表 dy/dt 的 Python 回调。LSODA 不会传递 Python 异常,从 C 代码的一个位跳转到另一个 C 代码执行起来很麻烦。
我已经找到了一个令人满意的解决方案,只是使用ode
而不是odeint
. 我发现ode
开始使用比较复杂,但是当 Python 中抛出异常时,它的行为是正确的。下面的fake_odeint()
函数是创建一个odeint
对我的目的来说足够好的函数的开始,这样我就可以在我现有的代码中将它换掉。使用ode
代替的缺点odeint
是 LSODA 在每个时间步被调用一次;这个调用发生在 C 中,odeint
并且在 Python 中更慢ode
。
import numpy as np
from scipy.integrate import ode
def fake_odeint(func, y0, t, Dfun=None):
ig = ode(func, Dfun)
ig.set_integrator('lsoda',
method='adams')
ig.set_initial_value(y0, t=0.)
y = []
for tt in t:
y.append(ig.integrate(tt))
return np.array(y)
我在这个 SO question中研究了如何使用 Fortran、C 和 Python 代码来允许odeint
与 LSODA 通信的机制。