10

谁能提供一个为integrate.odeintSciPy 中的函数提供雅可比行列式的示例?我尝试从 SciPy 教程odeint 示例中运行此代码,但似乎Dfun()从未调用过(雅可比函数)。

from numpy import * # added
from scipy.integrate import odeint
from scipy.special import gamma, airy
y1_0 = 1.0/3**(2.0/3.0)/gamma(2.0/3.0)
y0_0 = -1.0/3**(1.0/3.0)/gamma(1.0/3.0)
y0 = [y0_0, y1_0]


def func(y, t):
    return [t*y[1],y[0]]
    
    
def gradient(y,t):
    print 'jacobian'  # added
    return [[0,t],[1,0]]
    
    
x = arange(0,4.0, 0.01)
t = x
ychk = airy(x)[0]
y = odeint(func, y0, t)
y2 = odeint(func, y0, t, Dfun=gradient)
print y2 # added
4

1 回答 1

17

在后台,scipy.integrate.odeint使用ODEPACK FORTRAN 库中的 LSODA 求解器。为了处理您尝试积分的函数是刚性的情况,LSODA 在两种不同的积分计算方法之间自适应切换 - Adams 方法更快但不适合刚性系统,BDF速度较慢但稳健到僵硬。

您尝试集成的特定功能是非刚性的,因此 LSODA 将在每次迭代中使用 Adams。您可以通过返回infodict( ...,full_output=True) 并检查来检查这一点infodict['mused']

由于 Adams 的方法不使用 Jacobian,因此您的梯度函数永远不会被调用。但是,如果您给出odeint一个刚性函数进行积分,例如Van der Pol 方程

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,并且现在调用 Jacobian 函数。

如果您想对求解器进行更多控制,您应该查看scipy.integrate.ode,这是一个针对多个不同集成器的更灵活的面向对象接口。

于 2013-07-09T02:07:39.637 回答