【C/C++】龙格库塔+亚当姆斯求解数值微分初值问题

 1 /*
 2     解数值微分初值问题: 
 3     龙格-库塔法求前k个初值 + 亚当姆斯法 
 4 */
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 
 8 double f(double x,double y){
 9     //y(0) = 1 
10     return (y - 2*x/y);
11 }
12 void getRungeResult(double *Runge_k,double x0,double y0,double h,int N){
13     //求解N个初值,保存在Runge_k[1 to N]中
14     double K1,K2,K3,K4;
15     double x1,y1;
16     for(int i = 1;i<=N;i++){
17         x1 = x0+h;
18         K1 = f(x0,y0);
19         K2 = f(x0+h/2,y0+h/2*K1);
20         K3 = f(x0+h/2,y0+h/2*K2);
21         K4 = f(x1,y0+K4);
22         y1 = y0 + h/6*(K1+2*K2+2*K3+K4);
23         Runge_k[i] = y1;
24         x0 = x1;
25         y0 = y1;
26     }
27     return;
28 }
29 
30 //亚当姆斯多步法 
31 void Adams(double *Runge_k,double *predict,double x0,double y0,double h,int N){
32     Runge_k[0] = y0;
33     //(0)龙格库塔法求前4个初值 
34     getRungeResult(Runge_k,x0,y0,h,3);
35     double y1,y2,y3,dy0,dy1,dy2,dy3;
36     y1 = Runge_k[1];
37     y2 = Runge_k[2];
38     y3 = Runge_k[3];
39     dy0 = f(x0,y0);
40     dy1 = f(x0+h,y1);
41     dy2 = f(x0+2*h,y2);
42     dy3 = f(x0+3*h,y3);
43     double x3 = x0+3*h;
44     double x4,y4,yp,dyp,dy4;
45     for(int i = 4;i<=N;i++){
46         x4 = x3+h;
47         //(1)预测 
48         yp = y3 + h/24*(55*dy3-59*dy2+37*dy1-9*dy0);
49         predict[i] = yp;//保存预测值 
50         //预测要用dyp 
51         dyp = f(x4,yp);
52         //(2)校正 
53         y4 = y3 + h/24*(9*dyp + 19*dy3 -5*dy2+dy1);
54         //存起来
55         Runge_k[i] = y4;
56         //求下一次需要用到导
57         dy4 = f(x4,y4);
58         //为下一次循环做准备 
59         x3 = x4;
60         y3 = y4;
61         dy0 = dy1;
62         dy1 = dy2;
63         dy2 = dy3;
64         dy3 = dy4;
65     }
66     return;
67 } 
68 
69 
70 /*假设这里保证四阶精度*/
71 int main(){
72     /*说明:x0,y0是初值,h是小区间长度,N是要求的个数*/
73     double x0,y0,h;
74     int N;
75     cout<<"输入初值x0,y0,小区间h,需要的初值个数N:";
76     cin>>x0>>y0>>h>>N;
77     //保存Runge求的4个初始值,龙格法求3个就可以;之后也用这个保存最终的Adams结果 
78     double Runge_k[100];
79     //保存预测值,方便以后比较 
80     double predict[100];
81     memset(predict,0,sizeof(predict));
82     memset(Runge_k,0,sizeof(Runge_k));
83     Adams(Runge_k,predict,x0,y0,h,N);
84     cout<<endl;
85     printf("预测值:"); 
86     for(int i = 0;i<=N;i++){
87         if(i<4){
88             printf("%.6lf ",0);
89         }else{
90             printf("%.6lf ",predict[i]);
91         }
92     }
93     cout<<endl;
94     printf("校正值:");
95     for(int i = 0;i<=N;i++){
96         printf("%.6lf ",Runge_k[i]);
97     }
98     
99 }

 

posted @ 2018-06-12 10:58  pigcv  阅读(765)  评论(0编辑  收藏  举报