微分方程数值解法(1)——常微分方程初值问题的数值解法

此处参考教材为李荣华的《微分方程数值解法》
使用工具:Matlab

1. 算法


注: 最后一行应为k4,上面为笔误

2. 算法

I.需要求解的函数
function f=f1D(t,u,ft)
 
% ft为方程编号,u1D为精确解函数u(t),注意与f1D对应右端项函数f(t,u(t))
 
switch ft
    case 1 %P10 习题1
        %v=exp(-5*t);
        f=-5*u;
    case 2 % P27 例3.1
        %v=(1+t.^2).^2;
        f=4*t.*u.^(1/2);
	case 3 %补充练习 P54 例1
        %v=exp(-t);
        f=-u;
end

II.对应精确解
function v=u1D(t,ft)
 
% ft为方程编号,u1D为精确解函数u(t),注意与f1D 对应右端项函数f(t,u(t))
 
switch ft
    case 1 %P10 习题1
        v=exp(-5*t);
        %f=-5*u;
    case 2 % P27 例3.1
        v=(1+t.^2).^2;
        %f=4*t.*u.^(1/2);
	case 3 %补充练习 P54 例1
        %v=exp(-t);
        f=-u;
end

III.求解问题的主函数

function ODESolver(ft,t0,T,h)
 
t=(t0:h:T);%t节点
n=length(t);%步数
ExactU=u1D(t,ft);%精确解
%-------------------------------------- 
% 1)向前欧拉,单步显式,u(i)=u(i-1)+h*f(t(i-1),u(i-1))
u=0.*t;%数值解初始化
u(1)=ExactU(1);%设初值
tic; %记录CPU计算开始时间
for i=2:n
    u(i)=u(i-1)+h*f1D(t(i-1),u(i-1),ft);
end
time1=toc; %记录CPU计算结束时间
NumU1=u;%计算结束赋值
Err1=(NumU1(n)-ExactU(n));%T点处误差
RelErr1=Err1/ExactU(n);%相对误差
 
%--------------------------------------
% 2)向后Euler法,单步隐式,u(i)=u(i-1)+h*f(t(i),u(i))
u=0.*t;%数值解初始化
u(1)=ExactU(1);%设初值
tic; %记录CPU计算开始时间
for i=2:n
    uc1=u(i-1)-1;%非线性迭代设初值
    uc2=u(i-1);%非线性迭代设初值,因为迭代uc1=uc2,故初值uc2=u(i-1)
    delta=10^(-5);%迭代阈值
    while abs(uc2-uc1)>delta
        uc1=uc2;
        uc2=u(i-1)+h*f1D(t(i),uc1,ft);
    end
    u(i)=uc2;%非线性迭代结束
end
time2=toc; %记录CPU计算结束时间
NumU2=u; %计算结束赋值
Err2=NumU2(n)-ExactU(n); %T点处误差
RelErr2=Err2/ExactU(n); %相对误差
  
%--------------------------------------
% 3)梯形法,单步隐式法, u(i)=u(i-1)+(h/2)*(f(t(i-1),u(i-1))+f(t(i),u(i)))
u=0.*t; %数值解初始化
u(1)=ExactU(1); %设初值
tic; %记录CPU计算开始时间
for i=2:n
     uc1=u(i-1)-1; %非线性迭代设置初值
     uc2=u(i-1); %非线性迭代设置初值,因为迭代uc1=uc2,故初值uc2=u(i-1)
     delta=10^(-5); %d迭代阈值
     while abs(uc2-uc1)>delta
     	uc1=uc2;
      	uc2=u(i-1)+(h/2)*(f1D(t(i-1),u(i-1),ft)+f1D(t(i),uc1,ft));
     end
  u(i)=uc2; %非线性迭代结束
end
time3=toc; %记录CPU计算结束时间
NumU3=u; %计算结束赋值
Err3=NumU3(n)-ExactU(n); %T点处误差
RelErr3=Err3/ExactU(n); %相对误差
  
%--------------------------------------
% 4) 改进Euler法,单步显示法,uc(i)=u(i-1)+h*f(t(i-1),u(i-1)),u(i)=u(i-1)+(h/2)*(f(t(i-1),u(i-1))+f(t(i),uc(i)))
u=0.*t;%数值解法初始化
u(1)=ExactU(1);%设初值
tic;%记录CPU计算开始时间
for i=2:n
    uc1=u(i-1)+h*4*t(i-1)*(u(i-1)^(1/2));%用向前Euler法预估
    u(i)=u(i-1)+(h/2)*(f1D(t(i-1),u(i-1),ft)+f1D(t(i),uc1,ft));%用梯形法校正
end
time4=toc;%记录CPU计算结束时间
NumU4=real(u);%计算结束赋值
Err4=NumU4(n)-ExactU(n);%T点处误差
RelErr4=Err4/ExactU(n);%相对误差
 
%--------------------------------------
%5)二步法a=0,二步显式法,u(n+2)-(1+a)*u(n+1)+a*u(n)=(1/2)*h*((3-a)*f(n+1)-(1+a)*f(n))
u=0.*t;%数值解初始化
u(1)=ExactU(1);%设初值
u(2)=ExactU(2);%设初值
a=0;
tic;%记录CPU计算开始时间
for i=3:n
u(i)=(1+a)*u(i-1)-a*u(i-2)+(1/2)*h*((3-a)*f1D(t(i-1),u(i-1),ft)-(1+a)*f1D(t(i-2),u(i-2),ft));
end
time5=toc;%记录CPU计算结束时间
NumU5=u;%计算结束赋值
Err5=NumU5(n)-ExactU(n);%T点处误差
RelErr5=Err5/ExactU(n);%相对误差
 
%--------------------------------------
%6)二步法a=-5,二步显式法,u(n+2)-(1+a)*u(n+1)+a*u(n)=(1/2)*h*((3-a)*f(n+1)-(1+a)*f(n))
u=0.*t;%数值解初始化
u(1)=ExactU(1); %设初值
u(2)=ExactU(2); %设初值
a=-5;
tic; %记录CPU计算结束时间
for i=3:n
u(i)=(1+a)*u(i-1)-a*u(i-2)+(1/2)*h* ((3-a)*f1D(t(i-1),u(i-1),ft)-(1+a)*f1D(t(i-2),u(i-2),ft));
end
time6=toc;  %记录CPU计算结束时间
NumU6=real(u); %计算结束赋值,由于u计算出现负数,开根号出现复数,故取实部
Err6=NumU6(n)-ExactU(n); %T点处误差
RelErr6=Err6/ExactU(n); %相对误差
 
%--------------------------------------
% 7)Simpson法,二步隐式法,u(i)=u(i-2)+(2*h/6)*(f(t(i-2),u(i-2))+4*f(t(i-1),u(i-1))+f(t(i),u(i)))
u=0.*t; %数值解初始化
u(1)=ExactU(1); %设初值
u(2)=ExactU(2); %设初值
tic; %记录CPU计算结束时间
for i=3:n
    uc1=u(i-2); %非线性迭代设初值
    uc2=u(i-1); %非线性迭代设初值,因为迭代uc1=uc2,故初值uc2=u(i-1)
    delta=10^(-5); %迭代阈值,精度及运算时间受其影响
    while abs(uc2-uc1)>delta
        uc1=uc2;
uc2=u(i-2)+(h/3)*(f1D(t(i-2),u(i-2),ft)+4*f1D(t(i-1),u(i-1),ft)+f1D(t(i),uc1,ft));
    end
    u(i)=uc2; %非线性迭代结束
end
time7=toc; %记录CPU计算结束时间
NumU7=u; %计算结束赋值
Err7=NumU7(n)-ExactU(n);%T点处误差
RelErr7=Err7/ExactU(n);%相对误差

%--------------------------------------
% 8)四级四阶RK法,单步显式法
u=0.*t;%数值解初始化
u(1)=ExactU(1);%设初值
tic;%记录CPU开始计算的时间
for i=2:n
    k1=f1D(t(i-1),u(i-1),ft);
    k2=f1D(t(i-1)+h/2,u(i-1)+(h/2)*k1,ft);
    k3=f1D(t(i-1)+h/2,u(i-1)+(h/2)*k2,ft);
    k4=f1D(t(i-1)+h,u(i-1)+h*k3,ft);
    u(i)=u(i-1)+(h/6)*(k1+2*k2+2*k3+k4);
end
time8=toc;%记录CPU计算结束时间
NumU8=u;%计算结束赋值
Err8=(NumU8(n)-ExactU(n));%T点处误差
RelErr8=Err8/ExactU(n);%相对误差

%--------------------------------------
%画图
figure;
plot(t,ExactU,'k-*',t,NumU1,'r-o',t,NumU2,'b-o',t,NumU3,'g-o',t,NumU4,'c-o',t,NumU5,'r-d',t,NumU7,'g-d',t,NumU8,'b-d');
legend('精确解','1)向前欧拉','2)向后欧拉','3)梯形法','4)改进Euler','5)二步法a=0','7)Simpson法','8)RK法','Location','NorthEastOutside');

%制表
f=figure;
data=([t;ExactU;NumU1;NumU2;NumU3;NumU4;NumU5;NumU6;NumU7;NumU8])';
data=[data;[0,0,Err1,Err2,Err3,Err4,Err5,Err6,Err7,Err8];[0,0,RelErr1,RelErr2,RelErr3,RelErr4,RelErr5,RelErr6,RelErr7,RelErr8];[0,0,time1,time2,time3,time4,time5,time6,time7,time8]];
colnames={'t','精确解','1)向前欧拉','2)向后欧拉','3)梯形法','4)改进Euler','5)二步法a=0','6)二步法a=-5','7)Simpson法','8)RK法'};
tab=uitable(f,'Data',data,'ColumnName',colnames,'Position',[50 50 800 500]);


3.给出简单结果

[^此处图略,仅给出简单数字结果;感兴趣的读者可以复制代码运行一下]

P10页:习题1
(1) 步长0.1:

在命令行窗口输入
>>ODESolver(1,0,1,0.1)

所得最后一步误差结果:

Err1 =-0.0058
Err2 =0.0106
Err3 =-6.9002e-04
Err4 =-0.0098
Err5 =0.0045
Err6 =-2.1480e+04
Err7 =-3.0847e-04
Err8 =2.6728e-05

(2)步长0.05:

在命令行窗口输入
>>ODESolver(1,0,1,0.05)

所得结果:

Err1 =-0.0036
Err2 =0.0048
Err3 =-1.7339e-04
Err4 =-0.0069
Err5 = 9.8516e-04
Err6 = -2.1437e+10
Err7 =-1.2741e-05
Err8 = 1.3516e-06

P27页:例题3.1
(1)步长0.1:

在命令行窗口输入
>>ODESolver(2,0,5,0.1)
所得结果:

Err1 = -3.5381
Err2 = 4.0508
Err3 = 0.0806
Err4 = -0.0763
Err5 = -0.3675
Err6 = -6.9711e+08
Err7 = -1.3874e-06
Err8 = -9.5303e-05

(2)步长0.05:

在命令行窗口输入
>>ODESolver(2,0,2,0.05)
所得结果:

Err1 = -1.8298
Err2 = 1.9580
Err3 = 0.0201
Err4 = -0.0196
Err5 = -0.0963
Err6 = -5.4646e+21
Err7 = -1.4567e-06
Err8 = -6.2349e-06

P54 例1
(1)步长0.1:

在命令行窗口输入
>>ODESolver(3,0,2,0.1)
所得结果:

Err1 = -0.0138
Err2 = 0.0133
Err3 = -2.2421e-04
Err4 = -0.0974
Err5 = 0.0011
Err6 = -1.2434e+08
Err7 = 1.8151e-08
Err8 = 2.4519e-07

4.对算例结果进行简单的分析

从整体来看:

第一道题在靠近1的附近,数值解精确度都比较高。第二道题在靠近0的附近,数值解精确度都比较高。其中,向前Euler法和向后Euler法落在精确解的两侧。图表的最后三行分别表示最后一步的数值误差、最后一步的相对误差、每个算法所花费的时间。

从步长来看:

图像中可以较直观的发现,h=0.05比h=0.1的精度整体更高一些。当步长变小时,对结果的分析更加清晰。

从八种不同的算法来看:

利用直观的图像以及数据表,Simpson方法误差最小,其次是RK法,二步法的误差最大(因为这种算法不稳定,可从图表中看出当a=-5时,二步法显示出不稳定性,且当步长缩小,时间增加时,不稳定性表现得非常明显)。在所有的单步法中,梯形法和改进欧拉法效果也比较好。

  • 2
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

limo_hui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值