コード例 #1
0
ファイル: evolve.c プロジェクト: BrianGladman/gsl
/* Evolution framework method.
 *
 * Uses an adaptive step control object
 */
int
gsl_odeiv2_evolve_apply (gsl_odeiv2_evolve * e,
                         gsl_odeiv2_control * con,
                         gsl_odeiv2_step * step,
                         const gsl_odeiv2_system * dydt,
                         double *t, double t1, double *h, double y[])
{
  const double t0 = *t;
  double h0 = *h;
  int step_status;
  int final_step = 0;
  double dt = t1 - t0;          /* remaining time, possibly less than h */

  if (e->dimension != step->dimension)
    {
      GSL_ERROR ("step dimension must match evolution size", GSL_EINVAL);
    }

  if ((dt < 0.0 && h0 > 0.0) || (dt > 0.0 && h0 < 0.0))
    {
      GSL_ERROR ("step direction must match interval direction", GSL_EINVAL);
    }

  /* Save y in case of failure in a step */

  DBL_MEMCPY (e->y0, y, e->dimension);

  /* Calculate initial dydt once or reuse previous value if the method
     can benefit. */

  if (step->type->can_use_dydt_in)
    {
      if (e->count == 0)
        {
          int status = GSL_ODEIV_FN_EVAL (dydt, t0, y, e->dydt_in);

          if (status)
            {
              return status;
            }
        }
      else
        {
          DBL_MEMCPY (e->dydt_in, e->dydt_out, e->dimension);
        }
    }

try_step:

  if ((dt >= 0.0 && h0 > dt) || (dt < 0.0 && h0 < dt))
    {
      h0 = dt;
      final_step = 1;
    }
  else
    {
      final_step = 0;
    }

  if (step->type->can_use_dydt_in)
    {
      step_status =
        gsl_odeiv2_step_apply (step, t0, h0, y, e->yerr, e->dydt_in,
                               e->dydt_out, dydt);
    }
  else
    {
      step_status =
        gsl_odeiv2_step_apply (step, t0, h0, y, e->yerr, NULL, e->dydt_out,
                               dydt);
    }

  /* Return if stepper indicates a pointer or user function failure */

  if (step_status == GSL_EFAULT || step_status == GSL_EBADFUNC)
    {
      return step_status;
    }

  /* Check for stepper internal failure */

  if (step_status != GSL_SUCCESS)
    {
      /* Stepper was unable to calculate step. Try decreasing step size. */

      double h_old = h0;

      h0 *= 0.5;

#ifdef DEBUG
      printf ("-- gsl_odeiv2_evolve_apply h0=%.5e\n", h0);
#endif

      /* Check that an actual decrease in h0 occured and the
         suggested h0 will change the time by at least 1 ulp */

      {
        double t_curr = GSL_COERCE_DBL (*t);
        double t_next = GSL_COERCE_DBL ((*t) + h0);

        if (fabs (h0) < fabs (h_old) && t_next != t_curr)
          {

            /* Step was decreased. Undo step, and try again with new h0. */

            DBL_MEMCPY (y, e->y0, dydt->dimension);
            e->failed_steps++;
            goto try_step;
          }
        else
          {
#ifdef DEBUG
            printf
              ("-- gsl_odeiv2_evolve_apply h0=%.5e, t0=%.5e, step_status=%d\n",
               h0, t0, step_status);
#endif
            *h = h0;            /* notify user of step-size which caused the failure */
            *t = t0;            /* restore original t value */
            return step_status;
          }
      }
    }

  e->count++;
  e->last_step = h0;

  if (final_step)
    {
      *t = t1;
    }
  else
    {
      *t = t0 + h0;
    }

  if (con != NULL)
    {
      /* Check error and attempt to adjust the step. */

      double h_old = h0;

      const int hadjust_status
        =
        gsl_odeiv2_control_hadjust (con, step, y, e->yerr, e->dydt_out, &h0);

      if (hadjust_status == GSL_ODEIV_HADJ_DEC)
        {
          /* Check that the reported status is correct (i.e. an actual
             decrease in h0 occured) and the suggested h0 will change
             the time by at least 1 ulp */

          double t_curr = GSL_COERCE_DBL (*t);
          double t_next = GSL_COERCE_DBL ((*t) + h0);

          if (fabs (h0) < fabs (h_old) && t_next != t_curr)
            {
              /* Step was decreased. Undo step, and try again with new h0. */

              DBL_MEMCPY (y, e->y0, dydt->dimension);
              e->failed_steps++;
              goto try_step;
            }
          else
            {
              /* Can not obtain required error tolerance, and can not
                 decrease step-size any further, so give up and return
                 GSL_FAILURE.
               */

              *h = h0;          /* notify user of step-size which caused the failure */
              return GSL_FAILURE;
            }
        }
    }

  /* Suggest step size for next time-step. Change of step size is not
     suggested in the final step, because that step can be very
     small compared to previous step, to reach t1. 
   */

  if (final_step == 0)
    {
      *h = h0;
    }

  return step_status;
}
コード例 #2
0
ファイル: evolve.c プロジェクト: BrianGladman/gsl
int
gsl_odeiv2_evolve_apply_fixed_step (gsl_odeiv2_evolve * e,
                                    gsl_odeiv2_control * con,
                                    gsl_odeiv2_step * step,
                                    const gsl_odeiv2_system * dydt,
                                    double *t, const double h, double y[])
{
  const double t0 = *t;
  int step_status;

  if (e->dimension != step->dimension)
    {
      GSL_ERROR ("step dimension must match evolution size", GSL_EINVAL);
    }

  /* Save y in case of failure in a step */

  DBL_MEMCPY (e->y0, y, e->dimension);

  /* Calculate initial dydt once if the method can benefit. */

  if (step->type->can_use_dydt_in)
    {
      int status = GSL_ODEIV_FN_EVAL (dydt, t0, y, e->dydt_in);

      if (status)
        {
          return status;
        }
    }

  if (step->type->can_use_dydt_in)
    {
      step_status =
        gsl_odeiv2_step_apply (step, t0, h, y, e->yerr, e->dydt_in,
                               e->dydt_out, dydt);
    }
  else
    {
      step_status =
        gsl_odeiv2_step_apply (step, t0, h, y, e->yerr, NULL, e->dydt_out,
                               dydt);
    }

  /* Return the stepper return value in case of an error */

  if (step_status != GSL_SUCCESS)
    {
      return step_status;
    }

  if (con != NULL)
    {
      /* Calculate error level. Fail if error level exceeds desired
         error level. */

      double htemp = h;

      const int hadjust_status
        = gsl_odeiv2_control_hadjust (con, step, y, e->yerr,
                                      e->dydt_out, &htemp);

      if (hadjust_status == GSL_ODEIV_HADJ_DEC)
        {
          DBL_MEMCPY (y, e->y0, dydt->dimension);
          e->failed_steps++;
          return GSL_FAILURE;
        }
    }

  /* Step is accepted, update status */

  e->count++;
  e->last_step = h;
  *t = t0 + h;

  return GSL_SUCCESS;
}
コード例 #3
0
ファイル: zombie-attack.c プロジェクト: Daniel-M/ODE-Seminar
int main(int argc, char **argv){
  

  /* Here on ask for initial values on each concentration IN THIS STAGE ON DEFINES INITIAL CONDITIONS
     Note that we have 5 conditions, setting 0.0 for the initial complex concentration */
  
  double y[3]={1,40,4};

  
  double p1=askvalue("a1?",-1e6,1e6),p2=askvalue("b1?",-1e6,1e6),p3=askvalue("d1?",-1e6,1e6),p4=askvalue("b2?",-1e6,1e6);
  double p5=askvalue("d2?",-1e6,1e6),p6=askvalue("a2?",-1e6,1e6),p7=askvalue("b3?",-1e6,1e6),p8=askvalue("d36?",-1e6,1e6);  // Rate constans, one can use an "askvalue" for demand them to the user
  
  /* Here one defines the parameters as an array of 4 elements
     this array is passed to the routine of solution */
  
  double parametros[8]={p1,p2,p3,p4,p5,p6,p7,p8}; 
  
  double t=0.0,tf;
  double yerr[3];
  double stepp;
  
  //FILE *resultados; // Deleted only one file results
  //opendatafile(&resultados,"resultados.txt","w");
  
  /* added file separation for each complex */
  
  /* here one creates the pointer to write to a file */
  
  FILE *filedataca;
  FILE *filedatamg;
  FILE *filedatacaparv;

  
  /* using opendatafile routine in "commonroutines.c" as a file handler */
  
  
  /* Opening files to write and putting some information on each */
  
  opendatafile(&filedataca,"results-zombie.txt","w"); //open the file for write
  fprintf(filedataca,"### Time\tZombie\n");
  
  opendatafile(&filedatamg,"results-sano.txt","w"); //open the file for write
  fprintf(filedatamg,"### Time\tSano\n");
  
  opendatafile(&filedatacaparv,"results-inmune.txt","w"); //open the file for write
  fprintf(filedatacaparv,"### Time\tInmune\n");
  
    
  fprintf(filedataca,"%E %E\n",t,y[0]);
  fprintf(filedatamg,"%E %E\n",t,y[1]);
  fprintf(filedatacaparv,"%E %E\n",t,y[2]);

  
  /***************************************************************/
  /* Now one defines the stuff that GSL Needs to solve the system */
  /***************************************************************/
  
  /* Here one creates the step method one can change where says "gsl_odeiv2_step_rk8pd" by
     
     * gsl_odeiv2_step_rk2  - Runge Kutta (2,3) Method
     * gsl_odeiv2_step_rk4  - 4th Order Runge Kutta Method (The Classical)
     * gsl_odeiv2_step_rkf45 - Runge-Kutta-Fehlberg (4,5) Method (General Purpose, GSL Recommended)
     * gsl_odeiv2_step_rkck - Runge- Kutta Cash-Karp (4,5) Method
     * gsl_odeiv2_step_rk8pd - Runge- Kutta Prince-Dormand (8,9) Method (defined here by default) */
     
  const gsl_odeiv2_step_type *Type=gsl_odeiv2_step_rkf45;
  
  
  /* Here one says to GSL that must create memory for 5 ODES (note the five) 
   * this must be changed when one changes the number of equations */

  gsl_odeiv2_step *Step=gsl_odeiv2_step_alloc(Type,3);
  
 /* Here one defines the system of ODEs as Sys and then calls the created system "reactions"
  * The NULL it's because we haven't defined a jacobian matrix, one uses the jacobian when
    the method demands but for the methods listed above one don't needs to define a jacobian
    so one puts NULL
  * then one puts 5 cuz we have 5 ODEs to integrate
  * the on puts &parameters on makes a "reference call" to the defined array of parameters to pass to the system
    remember that in "reactions" one uses them*/
 
  gsl_odeiv2_system Sys={reactions,NULL,3,&parametros};
  
  
  
  /*askvalue returns double, usage "askvalue(char mensaje[200], double xmin, double xmax)"*/
  stepp=askvalue("Paso de Integración",0,1);
  tf=askvalue("Tiempo de Integración",1e-6,1e6);
  
  printf("\n");
  
  while(t<tf){
  
     /* The function "gsl_odeiv2_step_apply(Step,t,stepp,y,yerr,dy/dt_in,dy/dt_out,&Sys)"
       applies the stepping function Step to the system of equations defined by Sys,
       using the step-size stepp to advance the system from time t and state y to time t+h.
       The new state of the system is stored in y on output, with an estimate of the absolute 
       error in each component stored in yerr. If the argument dydt_in is not null it should
       point an array containing the derivatives for the system at time t on input. This is
       optional as the derivatives will be computed internally if they are not provided, but
       allows the reuse of existing derivative information. On output the new derivatives of
       the system at time t+h will be stored in dydt_out if it is not null.
       
       * Note that both dy/dt_in and dy/dt_out are defined as null below*/
    
    
    
    int status=gsl_odeiv2_step_apply(Step,t,stepp,y,yerr,NULL,NULL,&Sys);
    

    
    //fprintf(resultados,"\n%.6E %.6E %.6E %.6E %.6E %.6E",t,y[0],y[1],y[2],y[3],y[4]); // Deleted, used in one file results
    
    
    fprintf(filedataca,"%E %E\n",t,y[0]);
    fprintf(filedatamg,"%E %E\n",t,y[1]);
    fprintf(filedatacaparv,"%E %E\n",t,y[2]);
  
    
    printf("%.6E %.6E %.6E %.6E\n",t,y[0],y[1],y[2]);
    
    t++;
    
  }
  
  fclose(filedataca);
  fclose(filedatamg);
  fclose(filedatacaparv);

   
  
  /* If GNU Plot it's intalled uncomment the lines below to create plots of the results on images */
   
  system("gnuplot -p -e \"set terminal png size 1640,1480;set output 'kinetic-all.png';plot 'results-zombie.txt' w lp,'results-sano.txt' w lp,'results-inmune.txt' w lp\"");
  system("gnuplot -p -e \"set terminal png size 1640,1480;set output 'kinetic-ca.png';plot 'results-zombie.txt' w lp\"");
  system("gnuplot -p -e \"set terminal png size 1640,1480;set output 'kinetic-mg.png';plot 'results-sano.txt' w lp\"");
  system("gnuplot -p -e \"set terminal png size 1640,1480;set output 'kinetic-parv.png';plot 'results-inmune.txt' w lp\"");
 
  
  exit(0);
} //End of Main Code