目录
一、方法背景
欧拉法、梯形法、改进欧拉法以及龙格-库塔法都属于单步法,即计算的时候只用到上一步的值。如果可以将已经计算出来的结果值用于的计算,就能够增加计算精度。我们尝试使用前面已经计算出来的k个值来提高求解的精度,即线性多步法的思路。通常线性k步法的公式为:
式中且,和为待定系数。如果,就是单步法:
,其中
若,得到,即为欧拉法;
若,得到,即为隐式欧拉法;
若,得到,即为梯形法。
同时,如果时是显格式;如果时是隐格式。
龙格-库塔法的原理是利用函数在某点处的函数值的线性组合来计算导数,而线性多步法的原理则是利用已经算出的函数值的线性组合来计算导数。
二、算法原理及推导过程
我们尝试推导k=3时的隐式线性多步法数值计算公式(即),阶数为四阶:
对于上式,其截断误差为:
假设,则,在处对分别使用泰勒公式,将得到的展开式带入到截断误差计算公式中可得:
为了得到四阶格式,需要满足:
上式有无穷多解,只要满足上式条件的系数、所组成的隐式线性多步格式都是四阶的。
其中,满足和系数条件的个别情况下的著名方法有:
1、辛普森(Simpson)方法
取,可得:
2、汉明(Hamming)方法
取,可得:
3、隐式四阶阿当姆斯(Adams)方法
取,可得:
在线性多步法中,形如:
的k步法称为阿当姆斯法。当时为阿当姆斯显格式,称为Adams-Bashforth公式;当时为阿当姆斯隐格式,称为Adams-Monlton公式。
4、预估-校正阿当姆斯法
与改进欧拉法类似,可以通过显示法预测初值,然后利用隐式法进行迭代。阿当姆斯法也可以使用预估-校正的方式进行计算:
显式阿当姆斯法为:
隐式阿当姆斯法为:
于是,预估-校正阿当姆斯法为:
①预估:
②校正:
三、算例实现
求解初值问题:
步长h=0.2。已知精确解为:
代码如下:
#include <cmath>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
int i,N;
double a,b,h,y0,k1,k2,k3,k4,err,y_predict;
double *x,*y;
double exact(double x);
double f(double x, double y);
a=0.0;
b=1.0;
N=5;
h=(b-a)/N;
x=(double*)malloc(sizeof(double)*(N+1));
y=(double*)malloc(sizeof(double)*(N+1));
for(i=0;i<=N;i++)
x[i]=a+i*h;
y0=1.0;
y[0]=y0;
for(i=0;i<3;i++)
{
k1=h*f(x[i],y[i]);
k2=h*f(x[i]+0.5*h,y[i]+0.5*k1);
k3=h*f(x[i]+0.5*h,y[i]+0.5*k2);
k4=h*f(x[i]+h,y[i]+k3);
y[i+1]=y[i]+(k1+2*k2+2*k3+k4)/6.0;
}
for(i=3;i<N;i++)
{
//显示预测初值
y_predict=y[i]+h*(55*f(x[i],y[i])-59*f(x[i-1],y[i-1])+37*f(x[i-2],y[i-2])-9*f(x[i-3],y[i-3]))/24.0;
//隐式求解
y[i+1]=y[i]+h*(9*f(x[i+1],y_predict)+19*f(x[i],y[i])-5*f(x[i-1],y[i-1])+f(x[i-2],y[i-2]))/24.0;
}
for(i=0;i<=N;i++)
{
printf("x[%d]=%.2f, y=%f, exact=%f, err=%.4e.\n",i,x[i],y[i],exact(x[i]),fabs(y[i]-exact(x[i])));
}
free(x);
free(y);
return 0;
}
double f(double x, double y)
{
return -y+x+1;
}
double exact(double x)
{
return x+exp(-x);
}
N=5时,运行结果如下:
x[0]=0.00, y=1.000000, exact=1.000000, err=0.0000e+00.
x[1]=0.20, y=1.018733, exact=1.018731, err=2.5803e-06.
x[2]=0.40, y=1.070324, exact=1.070320, err=4.2251e-06.
x[3]=0.60, y=1.148817, exact=1.148812, err=5.1888e-06.
x[4]=0.80, y=1.249323, exact=1.249329, err=6.4190e-06.
x[5]=1.00, y=1.367866, exact=1.367879, err=1.3775e-05.
N=10时,运行结果如下:
x[0]=0.00, y=1.000000, exact=1.000000, err=0.0000e+00.
x[1]=0.10, y=1.004838, exact=1.004837, err=8.1964e-08.
x[2]=0.20, y=1.018731, exact=1.018731, err=1.4833e-07.
x[3]=0.30, y=1.040818, exact=1.040818, err=2.0132e-07.
x[4]=0.40, y=1.070320, exact=1.070320, err=1.2779e-07.
x[5]=0.50, y=1.106530, exact=1.106531, err=3.9130e-07.
x[6]=0.60, y=1.148811, exact=1.148812, err=6.0354e-07.
x[7]=0.70, y=1.196585, exact=1.196585, err=7.7242e-07.
x[8]=0.80, y=1.249328, exact=1.249329, err=9.0367e-07.
x[9]=0.90, y=1.306569, exact=1.306570, err=1.0029e-06.
x[10]=1.00, y=1.367878, exact=1.367879, err=1.0751e-06.