我在尝试理解代码错误方面遇到了一些麻烦,任何帮助都会非常有帮助。 我想解决这个简单的等式
然而,我的代码给出的值与我的书或wolfram的值不匹配,因为随着x的增长,y会上升。
import matplotlib.pyplot as plt
from numpy import exp
from scipy.integrate import ode
# initial values
y0, t0 = [1.0], 0.0
def f(t, y):
f = [3.0*y[0] - 4.0/exp(t)]
return f
# initialize the 4th order Runge-Kutta solver
r = ode(f).set_integrator('dopri5')
r.set_initial_value(y0, t0)
t1 = 10
dt = 0.1
x, y = [], []
while r.successful() and r.t < t1:
x.append(r.t+dt); y.append(r.integrate(r.t+dt))
print(r.t+dt, r.integrate(r.t+dt))
答案 0 :(得分:1)
你的等式通常有解决方案
y(x) = (y0-1)*exp(3*x) + exp(-x)
由于初始条件的选择,确切的解决方案不包含第一项的增长成分。然而,由于离散化和浮点误差引起的小扰动将在增长期内产生非零系数。现在在积分区间结束时,此随机系数乘以exp(3*10)=1.107e+13
,这会将大小为1e-7
的小离散化误差放大到运行原始大小时观察到的大小1e+6
结果中的贡献代码。
您可以通过设置错误阈值来强制积分器在其内部步骤中更精确,而不会降低输出步长dt
,如
r = ode(f).set_integrator('dopri5', atol=1e-16, rtol=1e-20)
然而,由于大小为1e-16
的浮点错误被放大为大小为1e-3
的全局错误贡献,因此无法完全避免结果恶化。
此外,您应该注意到r.integrate(r.t+dt)
的每次调用都会使积分器前进dt
,以便存储的数组和打印值处于锁定状态。如果您只想打印积分器的当前状态,请使用
print(r.t,r.y,yexact(r.t,y0))
其中最后一个是与确切的解决方案进行比较,如前所述,
def yexact(x,y0):
return [ (y0[0]-1)*exp(3*x)+exp(-x) ]