[英]scipy.odeint strange behavior
Here is my code to solve differential equation dy / dt = 2 / sqrt(pi) * exp(-x * x) to plot erf(x). 这是我的代码,用于求解微分方程dy / dt = 2 / sqrt(pi)* exp(-x * x)以绘制erf(x)。
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import numpy as np
import math
def euler(df, f0, x):
h = x[1] - x[0]
y = [f0]
for i in xrange(len(x) - 1):
y.append(y[i] + h * df(y[i], x[i]))
return y
def i(df, f0, x):
h = x[1] - x[0]
y = [f0]
y.append(y[0] + h * df(y[0], x[0]))
for i in xrange(1, len(x) - 1):
fn = df(y[i], x[i])
fn1 = df(y[i - 1], x[i - 1])
y.append(y[i] + (3 * fn - fn1) * h / 2)
return y
if __name__ == "__main__":
df = lambda y, x: 2.0 / math.sqrt(math.pi) * math.exp(-x * x)
f0 = 0.0
x = np.linspace(-10.0, 10.0, 10000)
y1 = euler(df, f0, x)
y2 = i(df, f0, x)
y3 = odeint(df, f0, x)
plt.plot(x, y1, x, y2, x, y3)
plt.legend(["euler", "modified", "odeint"], loc='best')
plt.grid(True)
plt.show()
And here is a plot: 这是一个情节:
Am I using odeint in a wrong way or it's a bug? 我是以错误的方式使用odeint还是错误?
Notice that if you change x
to x = np.linspace(-5.0, 5.0, 10000)
, then your code works. 请注意,如果将
x
更改为x = np.linspace(-5.0, 5.0, 10000)
,则代码可以正常工作。 Therefore, I suspect the problem has something to do with exp(-x*x)
being too small when x
is very small or very large. 因此,我怀疑当
x
非常小或非常大时,问题与exp(-x*x)
太小有关。 [Total speculation: Perhaps the odeint (lsoda) algorithm adapts its stepsize based on values sampled around x = -10
and increases the stepsize in such a way that values around x = 0
are missed?] [总推测:也许odeint(lsoda)算法根据围绕
x = -10
采样的值调整其步长,并以这样的方式增加步长,使x = 0
左右的值丢失?]
The code can be fixed by using the tcrit
parameter, which tells odeint
to pay special attention around certain critical points. 可以使用
tcrit
参数修复代码,该参数告诉odeint
在某些关键点周围要特别注意。
So, by setting 所以,通过设置
y3 = integrate.odeint(df, f0, x, tcrit = [0])
we tell odeint
to sample more carefully around 0. 我们告诉
odeint
在0附近更仔细地采样。
import matplotlib.pyplot as plt
import scipy.integrate as integrate
import numpy as np
import math
def euler(df, f0, x):
h = x[1] - x[0]
y = [f0]
for i in xrange(len(x) - 1):
y.append(y[i] + h * df(y[i], x[i]))
return y
def i(df, f0, x):
h = x[1] - x[0]
y = [f0]
y.append(y[0] + h * df(y[0], x[0]))
for i in xrange(1, len(x) - 1):
fn = df(y[i], x[i])
fn1 = df(y[i - 1], x[i - 1])
y.append(y[i] + (3 * fn - fn1) * h / 2)
return y
def df(y, x):
return 2.0 / np.sqrt(np.pi) * np.exp(-x * x)
if __name__ == "__main__":
f0 = 0.0
x = np.linspace(-10.0, 10.0, 10000)
y1 = euler(df, f0, x)
y2 = i(df, f0, x)
y3 = integrate.odeint(df, f0, x, tcrit = [0])
plt.plot(x, y1)
plt.plot(x, y2)
plt.plot(x, y3)
plt.legend(["euler", "modified", "odeint"], loc='best')
plt.grid(True)
plt.show()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.