Python odeint中可能存在的错误<-&燃气轮机;1D相互作用?

Python odeint中可能存在的错误<-&燃气轮机;1D相互作用?,python,scipy,interpolation,ode,numerical-integration,Python,Scipy,Interpolation,Ode,Numerical Integration,我对python和scipy比较陌生,是MATLAB的一个转换。我在scipy.integrate中快速测试了odeint函数,发现了这个潜在的bug。考虑下面的片段: from scipy import * from scipy.integrate import odeint from scipy.interpolate import interp1d from pylab import * # ODE system with forcing function u(t) def sis(x,

我对python和scipy比较陌生,是MATLAB的一个转换。我在scipy.integrate中快速测试了odeint函数,发现了这个潜在的bug。考虑下面的片段:

from scipy import *
from scipy.integrate import odeint
from scipy.interpolate import interp1d
from pylab import *

# ODE system with forcing function u(t)
def sis(x,t,u):
    return [x[1], u(t)]

# Solution time span
t = linspace(0, 10, 1e3)

# Profile for forcing function u(t)
acel = lambda t: 3*(t<2)-3*(t>8)

# Interpolator for acelerator
acel_interp = interp1d(t, acel(t), bounds_error=False, fill_value=0)    

# ODE integration with u(t) = acel, a lambda function
x_1 = odeint(sis, [0,0], t, args=(acel,) )            # Correct result
# ODE integration with u(t) = acel_interp, an interpolator
x_2 = odeint(sis, [0,0], t, args=(acel_interp,) )     # Incorrect result
从scipy导入*
从scipy.integrate导入odeint
从scipy.interpolate导入interp1d
从派拉布进口*
#具有强制功能u(t)的常微分方程系统
def sis(x、t、u):
返回[x[1],u(t)]
#求解时间跨度
t=linspace(0,10,1e3)
#强制功能u(t)的配置文件
acel=λt:3*(t8)
#加速器内插器
acel\u interp=interp1d(t,acel(t),界限错误=False,填充值=0)
#与u(t)=acel(一个lambda函数)的ODE积分
x_1=odeint(sis,[0,0],t,args=(acel,)#正确结果
#ODE积分与u(t)=acel_interp,插值器
x_2=odeint(sis[0,0],t,args=(acel_interp,)#结果不正确
我画了一个图,说明了两种结果的不同


至少对我来说,你对结果上的不必要的差异有什么看法?我在Python 2.6.6的基础上使用NumPy 1.5.0版和SciPy 0.8.0版,这不是一个bug。问题在于,您已将
bound_error
设置为False,并用零填充这些值。如果在原始代码中将
bound_error
设置为True,则可以看到您超出了插值的边界,因此在积分中加入了零(从而产生了一个不同的值,而不是像对
x_1
的lambda那样在范围之外的点上计算函数)

试试下面的方法,你会发现一切正常。基本上,我刚刚扩展了
t
,以覆盖一个足够大的值范围,从而覆盖您在上面使用插值的范围

from scipy import *
from scipy.integrate import odeint
from scipy.interpolate import interp1d
from pylab import *

# ODE system with forcing function u(t)
def sis(x,t,u):
    return [x[1], u(t)]

# Solution time span
t = linspace(0, 10, 1e3)
t_interp = linspace(0,20,2e3)

# Profile for forcing function u(t)
acel = lambda t: 3*(t<2)-3*(t>8)

# Interpolator for acelerator
acel_interp = interp1d(t_interp, acel(t_interp))    

# ODE integration with u(t) = acel, a lambda function
x_1 = odeint(sis, [0,0], t, args=(acel,) )            
# ODE integration with u(t) = acel_interp, an interpolator
x_2 = odeint(sis, [0,0], t, args=(acel_interp,) )     
从scipy导入*
从scipy.integrate导入odeint
从scipy.interpolate导入interp1d
从派拉布进口*
#具有强制功能u(t)的常微分方程系统
def sis(x、t、u):
返回[x[1],u(t)]
#求解时间跨度
t=linspace(0,10,1e3)
t_interp=linspace(0,20,2e3)
#强制功能u(t)的配置文件
acel=λt:3*(t8)
#加速器内插器
acel_interp=interp1d(t_interp,acel(t_interp))
#与u(t)=acel(一个lambda函数)的ODE积分
x_1=odeint(sis,[0,0],t,args=(acel,)
#ODE积分与u(t)=acel_interp,插值器
x_2=odeint(sis,[0,0],t,args=(acel_interp,)

你比我快了13分钟:)当我捕捉到
u(t)
抛出的第一个异常时,当
sis()
被计算时,
t
的值是
17.8811987021
。然而,
odeint()
被告知从0到10进行积分。这是如何工作的?看看
x2,idct=odeint(sis[0,0],t,args=(acel\u interp,),full\u output=True);idct['tcur']
。无论使用什么集成方案,都需要超出
t
范围的评估。正如文档中所述:“'tcur'-向量,每个时间步的t值都达到。(始终至少与输入时间一样大)。”感谢您的智慧!我接受了你的答案,因为它是正确的。但是我仍然不明白为什么它不能与原始代码一起工作,因为初始时间跨度(
t
数组)包括
acel(t)
中的所有相关更改(最后一次转换发生在t=8,时间跨度设置为t=10)。你能详细解释一下吗?@Luis:你必须查看odeint的实现,它基于ODEPACK的lsoda算法,才能准确地回答这个问题。祝贺你从Matlab切换过来。我是18个月前搬家的。能够访问所有其他Python功能,并能够与那些没有支付数千美元购买Matlab许可证的人共享您的代码,这真是太棒了。