Dormand Prince 方法的 Fortran 和 C 代码

问题描述

我正在编写代码来使用 Dormand Prince 方法求解微分方程组。我在堆栈溢出中找到了相同的 C 代码,并尝试为我的方程实现它。它起作用了,我得到了解决方案。但是,我需要通过 fortran 和 C 来解决它。当我将代码转换为 fortran 时,它只会给出无限次相同的结果。我是 Fortran 的初学者。请帮助我哪里出错了?`

    #include<stdio.h>
    #include<math.h>
    #include<stdbool.h>
    #include  <stdlib.h>

    #define N 3

    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[N];
    //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.0;//x2(0)
   y[2]=1.0;//p1(0)
   ddopri5(fcn,y);

   }


  void fcn(double t,double *f){
 /*  double h = 0.25;*/
        f[0] = y[1];
        f[1] =- y[2]*y[0];
        f[2] = t;
    }

  double ddopri5(void fcn(double,double *y){
  double t,h,a,b,tw,chi;
  double w[N],k1[N],k2[N],k3[N],k4[N],k5[N],k6[N],k7[N],err[N],dy[N];
  int i;
  double errabs;
  int iteration;
  iteration = 0;

  //eps = 1.e-9;
  h = 0.5;
  a = 0.0;
  b = 15.0;//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 < N; 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 < N; i++){
        /*printf("k2[%i] = %.15lf \n",k2[i]);*/
        w[i] = y[i] + h*((3.0/40.0)*k1[i] + (9.0/40.0)*k2[i]);  
    }

  fcn(tw,k3);
    tw = t+ (4.0/5.0)*h;
    for(i = 0; i < N; i++){
        /*printf("k3[%i] = %.15lf \n",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,k4);
    tw = t+ (8.0/9.0)*h;
    for(i = 0; i < N; i++){
        /*printf("k4[%i] = %.15lf \n",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,k5);
    tw = t + h;
    for(i = 0; i < N; i++){
        /*printf("k5[%i] = %.15lf \n",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,k6);

    tw = t + h;
    for(i = 0; i < N; i++){
        /*printf("k6[%i] = %.15lf \n",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,k7);


    errabs = 0;

    for(i = 0; i < N; i++){
    /*  printf("k7[%i] = %.15lf \n",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",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,errabs,iteration);*/
        for(i = 0; i < N; i++){
            y[i]+=dy[i];            
        }
    } 
    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 < N; i++){
        printf("y[%i] = %.15lf \n",y[i]);
    }*/

   iteration++;
  /*printf("t = %.25lf \t h = %.25lf\n",h);*/
  /*if(iteration > 5) break;*/
  /* printf("end \n");*/
    for(i = 0; i < N; i++){
        printf("%.15lf %.15lf %.15lf %.15lf\n",y[0],y[1],y[2]);
    }
   if(iteration > 30000) break;
    }
  /*  for(i = 0; i < N; i++){
    printf("y[%i] = %.15lf\n",y[i]);
     }*/

        return 0;
    }

转换后的Fortran版本如下

      PROGRAM GHO
         IMPLICIT NONE
         DOUBLE PRECISION::y(3),eps,f(3)
         y(1)=1.0
         y(2)=-1.22565282791
         y(3)=-0.274772807644
         eps=0.05
        call ddopri5( y)
     END PROGRAM

     SUbroUTINE fcn(t,f)
          IMPLICIT NONE
          DOUBLE PRECISION::y(3),f(3)
          f(1)=y(2)
          f(2)=-y(3)*y(1)
          f(3)=t
     END SUbroUTINE 



    SUbroUTINE ddopri5( y)
       IMPLICIT NONE
       external fcn
       DOUBLE PRECISION::t,chi,eps
       DOUBLE PRECISION:: w(3),k1(3),k2(3),k3(3),k4(3),k5(3),k6(3),k7(3),&
        yerr(3),dy(3),y(3)
        INTEGER :: i
        DOUBLE PRECISION::errabs
         INTEGER::iteration;
         iteration = 0
          h=0.5
          a=0.0
          b=15.0
          t=a
         do while(t.le.(b-eps))
            call fcn(t,k1)
            tw = t+ (1.0/5.0)*h
            print *,k1(1),k1(2),k1(3)
            do i=1,3
              w(i) = y(i)+ h*(1.0/5.0)*k1(i)
            enddo
            call fcn(tw,k2)
            tw = t+ (3.0/10.0)*h
            do i=1,3
              w(i) = y(i)+ h*((3.0/40.0)*k1(i)+ (9.0/40.0)*k2(i))
            enddo
            call fcn(tw,k3)
            tw = t+ (4.0/5.0)*h
            do i=1,3
              w(i) = (i)+ h*((44.0/45.0)*k1(i)- (56.0/15.0)*k2(i)+ (32.0/9.0)*k3(i))
            enddo
            call fcn(tw,k4)
            tw = t+ (8.0/9.0)*h
            do i=1,3
            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))   
          enddo
          call fcn(tw,k5)
          tw = t + h;
          do i=1,3
          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))    
           enddo
           call fcn(tw,k6)
            tw = t + h
           do i=1,3
             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))
          enddo
           call fcn(tw,k7)
           errabs = 0
           do i=1,3
           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))
           yerr(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))
           print *,yerr(1),yerr(2),yerr(3)
           errabs=errabs+MAXVAL((yerr(i)*yerr(i)))
           print *,errabs
          enddo
        errabs =sqrt(errabs)
        print *,errabs
        if( errabs<eps)then 
             t=t+h
            do i=1,3
               y(i)=y(i)+dy(i)
            enddo
        endif
        chi=errabs/eps
       chi =chi**(1.0/6.0)
       if(chi>10) chi = 10
       if(chi<0.1) chi = 0.1
       h=(0.95/chi)*h
       print *,h
       if( t + h > b ) h=b-t
       iteration=iteration+1
      write (*,*) t,y(1),y(2),y(3)
  
      enddo    
    END SUbroUTINE

请帮帮我。我被困在这里好几天了。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)