为什么我使用4th Runge-Kutta的代码不能给我预期的值?

时间:2017-04-18 19:56:47

标签: python numpy matplotlib runge-kutta

我在尝试理解代码错误方面遇到了一些麻烦,任何帮助都会非常有帮助。 我想解决这个简单的等式

enter image description here

然而,我的代码给出的值与我的书或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))

1 个答案:

答案 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) ]