MATLAB - 将欧拉方法转换为Heun方法

时间:2015-12-10 00:07:08

标签: matlab numerical-methods differential-equations runge-kutta

我看到了这个计算错误的Euler方法:

function [t,le,ge] = euler_errors(h)

f=@(u) u*(2-u); % this is the function for the IVP
t0=0;
tn=1;
t=t0:h:tn;%we want to find the errors along this solutions
%here is the exact solution of the IVP
u_exact=(0.2*exp(2*t))./(2+0.1*(exp(2*t)+1)); %the with initial value u(0)=0.1

n=length(t);
u_e=zeros(1,n);
u_g=zeros(1,n);

i=1;
u_e(i)=0.1;
u_g(i)=0.1;

%u_e and u_g are both values given by Euler method
%u_e is for the local error
%u_g is for the global error
while (i<n)
    u_e(i+1)=u_e(i)+h*f(u_e(i));
    u_g(i+1)=u_g(i)+h*f(u_exact(i));
    i=i+1;
end;
%le1 is the local error
%ge1 is the global error
le=abs(u_e-u_exact);
ge=abs(u_g-u_exact);
end

我试图将方法转换为Heun的方法 - 这是我的尝试:

function [t,le,ge] = heun_errors(h)

f=@(u) u*(2-u); % this is the function for the IVP
t0=0;
tn=1;
t=t0:h:tn;%we want to find the errors along this solutions
%here is the exact solution of the IVP
u_exact=(0.2*exp(2*t))./(2+0.1*(exp(2*t)+1)); %the with initial value u(0)=0.1

n=length(t);
u_e=zeros(1,n);
u_g=zeros(1,n);

i=1;
u_e(i)=0.1;
u_g(i)=0.1;

%u_e and u_g are both values given by Euler method
%u_e is for the local error
%u_g is for the global error
while (i<n)
    u_e1(i+1)=u_e(i)+h*f(u_e(i));
u_e(i+1)=u_e(i)+(h/2)*(f(u_e(i))+f(u_e1(i+1)));
u_g1(i+1)=u_g(i)+h*f(u_exact(i));
u_g(i+1)=u_g(i)+(h/2)*(f(u_exact(i))+f(u_g1(i+1)));

    i=i+1;
end;
%le1 is the local error
%ge1 is the global error
le=abs(u_e-u_exact);
ge=abs(u_g-u_exact);
end

但现在错误实际上已经增加了。有人可以告诉我我做错了什么以及如何解决它?

1 个答案:

答案 0 :(得分:0)

首先,确切的解决方案有一个符号错误,该符号错误会使所有错误计算失效。作为伯努利方程,可以通过以下方式获得解决方案:

(e^(2t)/u)'=e^(2t)*(-u'/u^2 + 2/u) = e^(2t)

e^(2t)/u(t)-1/u0 = (e^(2t)-1)/2  

u(t) = 2*u0*exp(2*t) ./ ( 2 + u0*(exp(2*t)-1) )

Euler代码在概念上已经有些混淆。完全正常的积分给出了整体结果,因此也给出了与精确解有差异的整体误差。因此,所谓的u_e应该是u_g

局部错误将u_i(t)中开始的精确解(t_i,u_i)与同一点的方法步骤进行比较。由于只有一种精确的解决方案在起作用,因此它应执行(t_i,u_i) = (t(i), u_exact(i))的步骤,然后将其结果存储在u_e(i+1)中的方法步骤与精确值u_exact(i+1)进行比较。

两个发布都通过将循环更改为

来解决
while (i<n)
  u_g(i+1)=u_g(i)+h*f(u_g(i));
  u_g(i+1)=u_exact(i)+h*f(u_exact(i));
  i=i+1;
end;

类似地,这些问题也必须在Heun代码中解决,因此循环变为(使用阶段变量,如通用的Runge-Kutta方法一样)

while (i<n)
  k1=f(u_g(i));
  k2=f(u_g(i)+h*k1);
  u_g(i+1)=u_g(i)+(h/2)*(k1+k2);
  k1=f(u_exact(i));
  k2=f(u_exact(i)+h*k1);
  u_e(i+1)=u_exact(i)+(h/2)*(k1+k2);
  i=i+1;
end;

然后绘制le/h^(p+1)lg/h^p,误差顺序为p=1(对于Euler)和p=2(对于Heun),得出曲线图

error plots

在不同步长的图形叠加图中,步长在视觉上是不变的。

作为一致性检查,在相关区域中,局部欧拉误差在0.3*h^2附近,ODE的Lipschitz常数在2附近,因此,全局误差由Grönwall引理近似定律{{1 }}代表小型(exp(2*t)-1)*0.15*h。类似地,Heun方法在t附近有局部误差,对于小的0.15*h^3给出了全局误差(exp(2*t)-1)*0.075*h^2,这两者都与全局误差图兼容。

对于较大的t,局部错误的符号可以更改,从而补偿了先前的全局错误的一部分。但是,这不能保证会发生,也不容易预测。