这是我的代码,用于求解微分方程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()
这是一个情节:
我是以错误的方式使用odeint还是错误?
答案 0 :(得分:2)
请注意,如果您将x
更改为x = np.linspace(-5.0, 5.0, 10000)
,那么您的代码就可以运行。因此,我怀疑当exp(-x*x)
非常小或非常大时,问题与x
太小有关。 [总推测:也许odeint(lsoda)算法根据x = -10
周围的值调整其步长,并以x = 0
周围的值丢失的方式增加步长?]
可以使用tcrit
参数修复代码,该参数告诉odeint
围绕某些关键点要特别注意。
所以,通过设置
y3 = integrate.odeint(df, f0, x, tcrit = [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()