常微分方程数值解.docx
《常微分方程数值解.docx》由会员分享,可在线阅读,更多相关《常微分方程数值解.docx(12页珍藏版)》请在冰豆网上搜索。
常微分方程数值解
数学与计算科学学院
实验报告
实验项目名称常微分方程数值解
所属课程名称微分方程数值解法
实验类型验证
实验日期
班级
学号
姓名
成绩
一、实验概述:
【实验目的】
掌握求解常微分方程的欧拉法,Runge-Kutta方法(二阶的预估校正法,经典的四阶R-K法)
【实验原理】
1,欧拉法的格式如下:
其中n从0开始取值,
为微分方程中的dy/dx的值,而
是我们根据题目设定的初值。
2,预估校正法格式如下:
其中第一个式子为预报格式,第二个式子为校正格式,第三个式子也是给定的初值。
3,经典四阶Runge-Kutta格式,亦即R-K法格式如下:
【实验环境】
MicrosoftVisualC++6.0
二、实验内容:
【实验方案】
用欧拉法,预估校正法,经典的四阶龙格库塔方法求解初值问题
dy/dx=
,初值y(0)=1;将计算结果与精确解为
比较
在区间[0,1]上分别取步长h=0.1;0.05时进行计算。
对三个算法的收敛性进行分析比较,
【实验过程】(实验步骤、记录、数据、分析)
1,部分算法代码:
(1)欧拉算法代码
voidruler(doublex[n+1],doubley[n+1],doubleh)//欧拉法
{
intj;
for(j=0;j{
y[j+1]=y[j]+h*f(x[j],y[j]);
}
}
(2)预步校正法代码
voidyugu_jz(doublex[n+1],doubley[n+1],doubleh)//预估校正法
{
doubleyy[n+1][2];
intj;
yy[0][1]=y[0];
for(j=0;j{
yy[j+1][0]=yy[j][1]+h*f(x[j],yy[j][1]);
yy[j+1][1]=yy[j][1]+h/2*(f(x[j],yy[j][1])+f(x[j],yy[j+1][0]));//预估校正法的解
y[j+1]=yy[j+1][1];
}
}
(3)Runge_Kutta法代码
voidRunge_Kutta(doublex[n+1],doubley[n+1],doubleh)//Runge_Kutta法
{
doublek1,k2,k3,k4;
inti;
for(i=0;i{
k1=f(x[i],y[i]);
k2=f(x[i]+h/2,y[i]+h/2*k1);
k3=f(x[i]+h/2,y[i]+h/2*k2);
k4=f(x[i]+h,y[i]+h*k3);
y[i+1]=y[i]+h/6*(k1+2*k2+2*k3+k4);
}
}
(4)目标函数及解析解
doublef(doublea,doubleb)//目标函数
{
doublefun;
fun=a*exp(-a)-b;
returnfun;
}
voidprecise(doublex[n+1],doubley[n+1])//精确解
{
intj;
for(j=0;j{
y[j+1]=(pow(x[j+1],2)+2)*exp(-x[j+1])/2;
}
}
2,结果分析:
根据下面的实验结果,可以得出:
当步长取0.1时,三种算法收敛性的关系为:
欧拉法<预步校正法,略高于欧拉法,Runge_Kutta法的精确度达到
,远远优于欧拉法和预步校正法。
当步长取0.05时,三种算法收敛性的关系不变,但三种方法的精确度均有提高,相对于步长0.1时,Runge_Kutta法收敛速度高于另外两种,可得其误差项阶数高于欧拉法和预步校正法,即结果均与理论相符。
【实验结论】(结果)
当步长为0.1时,结果及误差如下:
当步长为0.05时,结果及误差如下:
【实验小结】(收获体会)
通过本次实验,我熟悉了欧拉法,预步校正法以及Runge_Kutta法的算法思想,还有它们之间的收敛性差异,精确度差异,同时对也提高了自己的上机编程能力,感受到了理论与实践相结合的乐趣。
三、指导教师评语及成绩:
评语
评语等级
优
良
中
及格
不及格
1.实验报告按时完成,字迹清楚,文字叙述流畅,逻辑性强
2.实验方案设计合理
3.实验过程(实验步骤详细,记录完整,数据合理,分析透彻)
4实验结论正确.
成绩:
指导教师签名:
批阅日期:
附录1:
源程序
#include
#include
#definen10
voidprecise(doublex[n+1],doubley[n+1]);//精确解
voidruler(doublex[n+1],doubley[n+1],doubleh);//欧拉法
voidyugu_jz(doublex[n+1],doubley[n+1],doubleh);//预估校正法
voidRunge_Kutta(doublex[n+1],doubley[n+1],doubleh);//Runge_Kutta法
doublef(doublea,doubleb);//定义函数
voidmain()
{
printf("***该程序解决微分方程y`=x*e^(-x)-y的数值解问题***\n");
printf("***区间为[0,1],步长h=0.1\n\n");
doublex[n+1],y[4][n+1];
doubleh;
inti,k;
h=0.1;//步长赋值
//初值赋值
x[0]=0.0;
for(i=0;i<4;i++)
y[i][0]=1;
for(i=1;ix[i]=x[0]+h*i;
precise(x,y[0]);
ruler(x,y[1],h);
yugu_jz(x,y[2],h);
Runge_Kutta(x,y[3],h);
printf("x精确解欧拉法的解预估校正法Runge_Kutta\n");
for(k=0;k{
printf("%-3.2lf%-12.8lf%-12.8lf%-12.8lf%-12.8lf\n",x[k],y[0][k],y[1][k],y[2][k],y[3][k]);
}
printf("x精确解欧拉法误差预校法误差R_K法误差\n");
for(k=0;k{
printf("%-3.2lf%-12.8lf%e%e%e\n",x[k],y[0][k],fabs(y[1][k]-y[0][k]),fabs(y[2][k]-y[0][k]),fabs(y[3][k]-y[0][k]));
}
}
voidprecise(doublex[n+1],doubley[n+1])//精确解
{
intj;
for(j=0;j{
y[j+1]=(pow(x[j+1],2)+2)*exp(-x[j+1])/2;
}
}
voidruler(doublex[n+1],doubley[n+1],doubleh)//欧拉法
{
intj;
for(j=0;j{
y[j+1]=y[j]+h*f(x[j],y[j]);
}
}
voidyugu_jz(doublex[n+1],doubley[n+1],doubleh)//预估校正法
{
doubleyy[n+1][2];
intj;
yy[0][1]=y[0];
for(j=0;j{
yy[j+1][0]=yy[j][1]+h*f(x[j],yy[j][1]);
yy[j+1][1]=yy[j][1]+h/2*(f(x[j],yy[j][1])+f(x[j],yy[j+1][0]));//预估校正法的解
y[j+1]=yy[j+1][1];
}
}
voidRunge_Kutta(doublex[n+1],doubley[n+1],doubleh)//Runge_Kutta法
{
doublek1,k2,k3,k4;
inti;
for(i=0;i{
k1=f(x[i],y[i]);
k2=f(x[i]+h/2,y[i]+h/2*k1);
k3=f(x[i]+h/2,y[i]+h/2*k2);
k4=f(x[i]+h,y[i]+h*k3);
y[i+1]=y[i]+h/6*(k1+2*k2+2*k3+k4);
}
}
doublef(doublea,doubleb)//目标函数
{
doublefun;
fun=a*exp(-a)-b;
returnfun;
}
附录2:
实验报告填写说明
1.实验项目名称:
要求与实验教学大纲一致。
2.实验目的:
目的要明确,要抓住重点,符合实验教学大纲要求。
3.实验原理:
简要说明本实验项目所涉及的理论知识。
4.实验环境:
实验用的软、硬件环境。
5.实验方案(思路、步骤和方法等):
这是实验报告极其重要的内容。
概括整个实验过程。
对于验证性实验,要写明依据何种原理、操作方法进行实验,要写明需要经过哪几个步骤来实现其操作。
对于设计性和综合性实验,在上述内容基础上还应该画出流程图、设计思路和设计方法,再配以相应的文字说明。
对于创新性实验,还应注明其创新点、特色。
6.实验过程(实验中涉及的记录、数据、分析):
写明具体实验方案的具体实施步骤,包括实验过程中的记录、数据和相应的分析。
7.实验结论(结果):
根据实验过程中得到的结果,做出结论。
8.实验小结:
本次实验心得体会、思考和建议。
9.指导教师评语及成绩:
指导教师依据学生的实际报告内容,给出本次实验报告的评价。