牛顿法求初值的实现,用休眠王子在C中求解微分方程
下面的代码就像一个魔咒,用正确的初始值求解其中的微分方程组(代码中的fcn函数)。然而,任务的重点是用一些随机值替换初始值y_1(0)和y_2(0),并实现一些迭代方法以找到正确的初始值来求解方程。我已经知道如何检查该值是否正确,因为根据定义,ddopri 5的输出应该将y_2(1)和y_3(1)设为0。对于这个问题,我如何实现Newton-Raphson牛顿法求初值的实现,用休眠王子在C中求解微分方程,c,numerical-methods,newtons-method,runge-kutta,C,Numerical Methods,Newtons Method,Runge Kutta,下面的代码就像一个魔咒,用正确的初始值求解其中的微分方程组(代码中的fcn函数)。然而,任务的重点是用一些随机值替换初始值y_1(0)和y_2(0),并实现一些迭代方法以找到正确的初始值来求解方程。我已经知道如何检查该值是否正确,因为根据定义,ddopri 5的输出应该将y_2(1)和y_3(1)设为0。对于这个问题,我如何实现Newton-Raphson #include<stdio.h> #include<math.h> #include<stdbool.h&g
#include<stdio.h>
#include<math.h>
#include<stdbool.h>
double ddopri5(void fcn(double, double *, double *), double *y);
double alpha;
void fcn(double t, double *y, double *f);
double eps;
int main(void){
double y[4];
//eps = 1.e-9;
printf("Enter alpha:\n");
scanf("%lg", &alpha);
printf("Enter epsilon:\n");
scanf("%lg", &eps);
y[0]=1.0;//x1(0)
y[1]=-1.22565282791;//x2(0)
y[2]=-0.274772807644;//p1(0)
y[3]=0.0;//p2(0)
ddopri5(fcn, y);
}
void fcn(double t, double *y, double *f){
/* double h = 0.25;*/
f[0] = y[1];
f[1] = y[3] - sqrt(2)*y[0]*exp(-alpha*t);
f[2] = sqrt(2)*y[3]*exp(-alpha*t) + y[0];
f[3] = -y[2];
}
double ddopri5(void fcn(double, double *, double *), double *y){
double t, h, a, b, tw, chi;
double w[4], k1[4], k2[4], k3[4], k4[4], k5[4], k6[4], k7[4], err[4], dy[4];
int i;
double errabs;
int iteration;
iteration = 0;
//eps = 1.e-9;
h = 0.1;
a = 0.0;
b = 1;//3.1415926535;
t = a;
while(t < b -eps){
printf("%lg\n", eps);
fcn(t, y, k1);
tw = t+ (1.0/5.0)*h;
for(i = 0; i < 4; i++){
/*printf("k1[%i] = %.15lf \n", i, k1[i]);*/
w[i] = y[i] + h*(1.0/5.0)*k1[i];
}
fcn(tw, w, k2);
tw = t+ (3.0/10.0)*h;
for(i = 0; i < 4; i++){
/*printf("k2[%i] = %.15lf \n", i, k2[i]);*/
w[i] = y[i] + h*((3.0/40.0)*k1[i] + (9.0/40.0)*k2[i]);
}
fcn(tw, w, k3);
tw = t+ (4.0/5.0)*h;
for(i = 0; i < 4; i++){
/*printf("k3[%i] = %.15lf \n", i, k3[i]);*/
w[i] = y[i] + h*((44.0/45.0)*k1[i] - (56.0/15.0)*k2[i] + (32.0/9.0)*k3[i]);
}
fcn(tw, w, k4);
tw = t+ (8.0/9.0)*h;
for(i = 0; i < 4; i++){
/*printf("k4[%i] = %.15lf \n", i, k4[i]);*/
w[i] = y[i] + h*((19372.0/6561.0)*k1[i] - (25360.0/2187.0)*k2[i] + (64448.0/6561.0)*k3[i] - (212.0/729.0)*k4[i]);
}
fcn(tw, w, k5);
tw = t + h;
for(i = 0; i < 4; i++){
/*printf("k5[%i] = %.15lf \n", i, k5[i]);*/
w[i] = y[i] + h*((9017.0/3168.0)*k1[i] - (355.0/33.0)*k2[i] + (46732.0/5247.0)*k3[i] + (49.0/176.0)*k4[i] - (5103.0/18656.0)*k5[i]) ;
}
fcn(tw, w, k6);
tw = t + h;
for(i = 0; i < 4; i++){
/*printf("k6[%i] = %.15lf \n", i, k6[i]);*/
w[i] = y[i] + h*((35.0/384.0)*k1[i] + (500.0/1113.0)*k3[i] + (125.0/192.0)*k4[i] - (2187.0/6784.0)*k5[i] + (11.0/84.0)*k6[i]);
}
fcn(tw, w, k7);
errabs = 0;
for(i = 0; i < 4; i++){
/* printf("k7[%i] = %.15lf \n", i, k7[i]);*/
/* dy[i] = h*((71.0/57600.0)*k1[i] - (71.0/16695.0)*k3[i] + (71.0/1920.0)*k4[i] - (17253.0/339200.0)*k5[i] + (22.0/525.0)*k6[i]);*/
dy[i] = h*((35.0/384.0)*k1[i] + (500.0/1113.0)*k3[i] + (125.0/192.0)*k4[i] - (2187.0/6784.0)*k5[i] + (11.0/84.0)*k6[i]);
/*err[i] = h*((71.0/57600.0)*k1[i] + (71.0/16695.0)*k3[i] + (71.0/1920.0)*k4[i] - (17253.0/339200.0)*k5[i] + (22.0/525.0)*k6[i] - (1.0/40.0)*k7[i])*/;
err[i] = h*((71.0/57600.0)*k1[i] - (71.0/16695.0)*k3[i] + (71.0/1920.0)*k4[i] - (17253.0/339200.0)*k5[i] + (22.0/525.0)*k6[i] - (1.0/40.0)*k7[i]);
/*printf("err[%i] = %.15lf \n", i, err[i]);*/
errabs+=err[i]*err[i];
}
errabs = sqrt(errabs);
printf("errabs = %.15lf\n", errabs);
if( errabs < eps){
t+= h;
printf(" FROM IF \t t = %.25lf, \n h = %.25lf, \n errabs = %.25lf, \n iteration = %i . \n", t, h, errabs, iteration);
for(i = 0; i < 4; i++){
y[i]+=dy[i];
}
}
/*Avtomaticheskiy vibor shaga*/
chi=errabs/eps;
chi = pow(chi, (1.0/6.0));
if(chi > 10) chi = 10;
if(chi < 0.1) chi = 0.1;
h*= 0.95/chi;
if( t + h > b ) h = b - t;
/* for(i = 0; i < 4; i++){
printf("y[%i] = %.15lf \n", i, y[i]);
}*/
iteration++;
printf("t = %.25lf \t h = %.25lf\n", t, h);
/*if(iteration > 5) break;*/
printf("end \n");
for(i = 0; i < 4; i++){
printf("y[%i] = %.15lf \n", i, y[i]);
}
if(iteration > 30000) break;
}
/* for(i = 0; i < 4; i++){
printf("y[%i] = %.15lf\n", i, y[i]);
}*/
return 0;
}
#包括
#包括
#包括
双ddopri5(无效fcn(双精度,双精度*,双精度*),双精度*y);
双α;
无效fcn(双t,双y,双f);
双每股收益;
内部主(空){
双y[4];
//每股收益=1.e-9;
printf(“输入alpha:\n”);
扫描频率(“%lg”、&alpha);
printf(“输入ε:\n”);
scanf(“%lg”、&eps);
y[0]=1.0;//x1(0)
y[1]=-1.22565282791;//x2(0)
y[2]=-0.274772807644;//p1(0)
y[3]=0.0;//p2(0)
ddopri5(fcn,y);
}
空fcn(双t,双y,双f){
/*双h=0.25*/
f[0]=y[1];
f[1]=y[3]-sqrt(2)*y[0]*exp(-alpha*t);
f[2]=sqrt(2)*y[3]*exp(-alpha*t)+y[0];
f[3]=-y[2];
}
双ddopri5(无效fcn(双精度,双精度*,双精度*),双精度*y){
双t,h,a,b,tw,chi;
双w[4],k1[4],k2[4],k3[4],k4[4],k5[4],k6[4],k7[4],err[4],dy[4];
int i;
双勘误表;
整数迭代;
迭代=0;
//每股收益=1.e-9;
h=0.1;
a=0.0;
b=1;//3.1415926535;
t=a;
而(t10)chi=10;
如果(chi<0.1)chi=0.1;
h*=0.95/chi;
如果(t+h>b)h=b-t;
/*对于(i=0;i<4;i++){
printf(“y[%i]=%.15lf\n”,i,y[i]);
}*/
迭代++;
printf(“t=%.25lf\th=%.25lf\n”,t,h);
/*如果(迭代>5次)中断*/
printf(“end\n”);
对于(i=0;i<4;i++){
printf(“y[%i]=%.15lf\n”,i,y[i]);
}
如果(迭代次数>30000次)中断;
}
/*对于(i=0;i<4;i++){
printf(“y[%i]=%.15lf\n”,i,y[i]);
}*/
返回0;
}
试试这个:
Y0=initial_guess
while (true) {
F=ddopri(Y0);
Error=F-F_correct
if (Error small enough)
break;
J=jacobian(ddopri, Y0) // this is the matrix dF/dY0
Y0=Y0-J^(-1)*Error // here you have to solve a linear system
雅可比矩阵可以使用有限差分法得到,即每次上下碰撞Y的一个元素,计算F,取有限差分
明确地说,矩阵j的元素(i,j)是dF_i/dY0_jNR与成本函数的导数一起工作。所以你需要一个成本函数和它的导数。如果ddopri5是你的代价函数,那么你必须实现它对输入参数的导数。正如@Matthew所说,或者,你可以用有限差分近似你的导数。嘿,伙计们!我把它们放在哪里?你能给我大概的伪代码吗?为什么是2x2?我的方程组(fcn)有4x4维。如果这让人困惑,就忽略这一部分。我从答案中删除了这个。我的意思是,在你的问题中,你声明你不知道4个初始条件中的2个。因此,你的真实未知数是2,而不是4。顺便说一句,我看你对StackOverflow是新手。