在引擎盖下,scipy.integrate.odeint https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html#scipy.integrate.odeint使用 LSODA 求解器ODEPACK FORTRAN 库 http://www.netlib.org/odepack/opks-sum。为了处理您尝试集成的功能的情况stiff http://en.wikipedia.org/wiki/Stiffness_%28mathematics%29,LSODA 自适应地在两种不同的积分计算方法之间切换 -亚当斯法 http://mathworld.wolfram.com/AdamsMethod.html,速度更快,但不适合刚性系统,并且BDF https://en.wikipedia.org/wiki/Backward_differentiation_formula,速度较慢但对刚度具有鲁棒性。
您尝试集成的特定函数是非刚性的,因此 LSODA 将在每次迭代中使用 Adams。您可以通过返回来检查这一点infodict
(...,full_output=True
)并检查infodict['mused']
.
由于 Adams 的方法不使用雅可比行列式,因此您的梯度函数永远不会被调用。但是如果你给odeint
需要积分的刚性函数,例如范德波尔方程 http://en.wikipedia.org/wiki/Van_der_Pol_equation:
def vanderpol(y, t, mu=1000.):
return [y[1], mu*(1. - y[0]**2)*y[1] - y[0]]
def vanderpol_jac(y, t, mu=1000.):
return [[0, 1], [-2*y[0]*y[1]*mu - 1, mu*(1 - y[0]**2)]]
y0 = [2, 0]
t = arange(0, 5000, 1)
y,info = odeint(vanderpol, y0, t, Dfun=vanderpol_jac, full_output=True)
print info['mused'] # method used (1=adams, 2=bdf)
print info['nje'] # cumulative number of jacobian evaluations
plot(t, y[:,0])
你应该看到odeint
切换到使用 BDF,并且现在调用雅可比函数。
如果您想更好地控制求解器,您应该研究scipy.integrate.ode http://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.ode.html,这是一个更灵活的面向对象的接口,适用于多个不同的集成器。