求解常微分方程组初值问题的龙格库塔法分析及其C代码1、概述由高等数学的知识可知,一些特殊类型的常微分方程(组)能够求出给定初始值的解析解,而在科学与工程问题中遇到的常微分方程(组)往往是极其复杂的,要想求得其给定初始值的解析解就变得极其困难,甚至是得不到解析解。尽管如此,在研究实际问题时,往往只需要获得若干点上的近似值就行了,这就说明研究常微分方程(组)的数值解法是很有必要的。求解常微分方程(组)的数值解法有多种,比如欧拉法、龙格库塔法、线性多步法等等,其中龙格库塔法是这几种方法中比较常用的,因为其计算精度较高且具有自启动的特点。对于用龙格库塔法求解单个常微分方程和求解常微分方程组的思路基本相似(注意一点一个微分方程组是常微分方程组即表明微分方程中的各阶导数都是对同一个变量求导,例如可以把各个量对时间求导得到一个常微分方程组,如果一个微分方程组中的有对不同变量的导数那么这个方程组就成了偏微分方程组),都是根据泰勒展开得到其迭代计算形式,其基本思想都是按照一定原则求取当前点附近一些点的斜率,通过这些斜率的线性组合作为当前点处的斜率,进行递推求解。2、数学模型2.1常微分方程初值问题的数学模型000(,)()()dyfxyxxdxyxy(1)式中(,)fxy为,xy的已知函数,0y为给定的初始值。常微分方程的数值解法的任务就是要求出函数值y在微分自变量x取如下序列:012nxxxx时的值()(1,2,3,)iyxin的近似值(1,2,3,)iyin,一般情况下都采取等距结点的方式,即:0(1,2,)ixxihin,其中h为相邻两结点的距离,称为步长。2.2常微分方程组初值问题的数学模型11122212121010202000(,,,,)(,,,,)(,,,,)()()()mmmmmmmdyfxyyydxdyfxyyydxdyfxyyydxyxyyxyyxy(2)式中12,,,mfff为12,,,,mxyyy的已知函数,010200,,,,mxyyy为初始值,利用数值解法求解常微分方程组的任务就是求出函数值12(),(),,()myxyxyx在微分自变量x取如下序列:012nxxxx时其值12(),(),,()(=1,2,,)iimiyxyxyxin的近似值12,,,(=1,2,,)iimiyyyin3龙格库塔法的迭代形式龙格库塔法的迭代形式推导在相关的数值分析书籍中均有详细的讲解,这里就不进行推导直接给出常用的四阶龙格库塔法的形式作为例子。3.1单个常微分方程的迭代形式对应于2.1节的数学模型有:112341213243(2*2*)6(,)(/2,*/2)(/2,*/2)(,*)nnnnnnnnnnhyyKKKKKfxyKfxhyKhKfxhyKhKfxhyhK(3)通过上面的迭代形式可知1234,,,KKKK实际上就是如下四个点(,)nnxy(点1)1(/2,*/2)nnxhyKh(点2)2(/2,*/2)nnxhyKh(点3)3(,*)nnxhyhK(点4)处函数y关于x的斜率。这四个点的确定又是一环扣一环的,比如要求得点2的位置,就必须先求得在点1处的斜率1K3.2常微分方程组的迭代形式对应于2.2节的数学模型有:,1,,1,2,3,4,112,211,122,1,1,311,222,2,2411,322,3,3(2*2*)6(,,,)(/2,*/2,*/2,*/2)(/2,*/2,*/2,*/2)(,*,*,*pnpnpppppnmpnmmpnmmnmmhyyKKKKKfxyyyKfxhyKhyKhyKhKfxhyKhyKhyKhKfxhyKhyKhyK)1,2,hpm(4)对比于单个微分方程的龙格库塔迭代形式,可以看出整个求解的过程完全一样,只不过在每步算斜率的时候需要一次性的解算完m(方程的个数)个,即是要把12,,,myyy的斜率一次性算完,才能继续往下递推运算。在求解常微分方程组初值问题的情况下,可将常微分方程组写成向量的形式,这样更加便于理解,下面用图形来展示整个求解过程:1,11,1,11,21,31,42,12,2,12,22,32,4,1,,1,2,3,42*2*6nnnnmnmnmmmmyyKKKKyyKKKKhyyKKKK2K1K3K4K1nYnYnxnx起始运算更新递推nYnx1*/2nYKh/2nxh2*/2nYKh/2nxh3*nYKhnxh图1龙格库塔法的求解过程沿着箭头的方向依次解出各个向量,即可依次递推下去,1K下面的,nnYx表示1K为点(,)nnxY处的斜率,2,3,4KKK处情形类似。4算例4.1问题描述利用四阶龙格库塔法求解初值问题(0)1(00.5)()/(0)2dyxyzydxxdzxyzzdx取步长为0.001h。4.2问题分析为了和第3节的数学模型对应,我们令1yy,2yz,则上面的问题就变为和前面的模型一样的形式:11212122(0)1(00.5)()/(0)2dyxyyydxxdyxyyydx4.3C程序代码#includestdio.h#includemath.h#defineM2//维数,方程组中方程的个数//算斜率的右端函数voidRightSlopeFun(double*pRightK,//算出来的右端斜率项[out]doubleiX,//计算点的微分自变量值double*iY//计算点的函数初始值){pRightK[0]=iX*iY[0]-iY[1];pRightK[1]=(iX+iY[0])/iY[1];}//龙格库塔法解算程序doubleLgktSoulution(double*pOY,//返回函数值[out]doubleiX,//积分自变量输入值double*iY,//初始值doubleh,//单步步长intCount=1//解算步数,默认形参为1,调用时不给此//参数赋值,则只解算一步){doubleK1[M];//第一个斜率doubleK2[M];//第二个斜率doubleK3[M];//第三个斜率doubleK4[M];//第四个斜率doubletempY[M];//保存Y的中间值的临时空间inti;//计数器doubletempX;//临时保存x的空间tempX=iX;//载入初始的x值for(i=0;iM;i++){tempY[i]=iY[i];//载入初始的函数值pOY[i]=iY[i];}while(Count0){RightSlopeFun(K1,tempX,tempY);//解算斜率K1tempX+=h/2;for(i=0;iM;i++){pOY[i]=tempY[i]+K1[i]*h/2;}RightSlopeFun(K2,tempX,pOY);//解算斜率K2for(i=0;iM;i++){pOY[i]=tempY[i]+K2[i]*h/2;}RightSlopeFun(K3,tempX,pOY);//解算斜率K3tempX+=h/2;for(i=0;iM;i++){pOY[i]=tempY[i]+K3[i]*h;}RightSlopeFun(K4,tempX,pOY);//解算斜率K4for(i=0;iM;i++){//得到函数值pOY[i]=tempY[i]+h*(K1[i]+2*K2[i]+2*K3[i]+K4[i])/6;//推算了一步的函数值,此处可以对该数据进行相应的操作}//递推数据更新Count--;if(Count=0){break;}for(i=0;iM;i++){tempY[i]=pOY[i];}}returntempX;}voidmain(){FILE*fp=fopen(d:\\lgktData.txt,a);doubleiy[M];doubleix;inti;iy[0]=1;iy[1]=2;ix=0;for(i=0;i500;i++){ix=LgktSoulution(iy,ix,iy,0.001);fprintf(fp,%-8.3f%-8.3f%-8.3f\n,ix,iy[0],iy[1]);}fclose(fp);}4.4结果分析在运行完毕以上的C程序后,在D盘的根目录下就会生成名为lgktData.txt的文件,这个文件中就保存了龙格库塔数值解法的数据,我们利用这个数据在MATLAB中绘图,在MATLAB的命令窗口或者M文件中输入如下代码clearclc[x,y1,y2]=textread('d:\\lgktData.txt','%.3f%.3f%.3f');plot(x,y1,'r',x,y2,'g');便可得到如下的图形:00.050.10.150.20.250.30.350.40.450.5-0.500.511.522.5从以上运用的四阶龙格库塔法求解常微分方程组的程序中,我们可以看出,只需要根据实际需要求解的模型,设定好方程组的个数M,将计算斜率的函数RightSlopeFun实现即可,求解函数LgktSoulution的内容完全是固定不变的,除非你要使用其他形式龙格库塔迭代形式;用龙格库塔法求解单个微分方程和求解微分方程组的思路和计算流程完全一样,只是在问题规模上有差异。5小结本文将单个常微分方程初值问题的龙格库塔求解方法和常微分方程组初值问题的龙格库塔法求解,在模型建立、迭代形式上进行了对应得阐述,只是为了便于从简单到复杂的理解,实质上这二者在程序实现的形式上是统一的。至此,利用龙格库塔法求解常微分方程组的处初值问题介绍完毕,对于程序进行适当的调整便可实现对不同微分方程组的求解,以及采用不同的龙格库塔迭代形式进行求解。