Exemplo n.º 1
0
int CVodeSetErrFileB(void *cvadj_mem, FILE *errfpB)
{
  CVadjMem ca_mem;
  void *cvode_mem;
  int flag;

  ca_mem = (CVadjMem) cvadj_mem;
  cvode_mem = (void *)ca_mem->cvb_mem;

  flag = CVodeSetErrFile(cvode_mem, errfpB);

  return(flag);
}
Exemplo n.º 2
0
int CVodeSetErrFileB(void *cvadj_mem, FILE *errfpB)
{
  CVadjMem ca_mem;
  void *cvode_mem;
  int flag;

  if (cvadj_mem == NULL) {
    CVProcessError(NULL, CV_ADJMEM_NULL, "CVODEA", "CVodeSetErrFileB", MSGAM_NULL_CAMEM);
    return(CV_ADJMEM_NULL);
  }
  ca_mem = (CVadjMem) cvadj_mem;
  cvode_mem = (void *)ca_mem->cvb_mem;

  flag = CVodeSetErrFile(cvode_mem, errfpB);

  return(flag);
}
Exemplo n.º 3
0
int calculate_abundances_(realtype *abundance, realtype *rate, realtype *density,
                          realtype *temperature, int *npart, int *nspec, int *nreac)
{
  int neq = *nspec-1; /* Number of ODEs in the system */
  realtype t0, t, tout; /* Initial, current and output times */
  realtype *data; /* Array pointer to access data stored in vectors*/
  N_Vector y; /* Vector of dependent variables that CVODE is to solve */
  User_Data user_data; /* Data to be passed to the solver routines */
  FILE *cvoderr; /* Log file for CVODE error messages */
  void *cvode_mem; /* Memory allocated to the CVODE solver */
  long int mxstep; /* Maximum number of internal steps */
  int flag, status, nfails; /* CVODE return flag, status and failure counter */

  /* Define the necessary external variables contained within the Fortran module CHEMISTRY_MODULE */
  extern realtype chemistry_module_mp_relative_abundance_tolerance_ ; /* Relative error tolerance */
  extern realtype chemistry_module_mp_absolute_abundance_tolerance_ ; /* Absolute error tolerance */

  /* Define the necessary external variables contained within the Fortran module GLOBAL_MODULE */
  extern realtype global_module_mp_start_time_; /* Start time for the chemical evolution (yr) */
  extern realtype global_module_mp_end_time_; /* End time for the chemical evolution (yr) */
  extern int global_module_mp_nelect_; /* Species index number for electron */

  realtype reltol = chemistry_module_mp_relative_abundance_tolerance_;
  realtype abstol = chemistry_module_mp_absolute_abundance_tolerance_;
  realtype start_time = global_module_mp_start_time_;
  realtype end_time = global_module_mp_end_time_;
  realtype seconds_in_year = RCONST(3.1556926e7); /* Convert from years to seconds */
  int nelect = global_module_mp_nelect_-1;

  double cpu_start, cpu_end; /* CPU times */
#ifdef OPENMP
  int nthread, thread; /* Number of threads and current thread number */
#endif

  int n, i;

  /* Open the error log files */
  stderr = fopen("main.log", "a");
  cvoderr = fopen("cvode.log", "a");

  /* Specify the maximum number of internal steps */
  mxstep = 10000000;

  /* Initialize the global status flag */
  status = 0;

#ifdef OPENMP
  cpu_start = omp_get_wtime();
#else
  cpu_start = clock();
#endif

#pragma omp parallel for default(none) schedule(dynamic) \
  shared(npart, nspec, nreac, nelect, nthread, abundance, rate, density, temperature) \
  shared(neq, start_time, end_time, reltol, abstol, mxstep, status, cvoderr, stderr) \
  shared(seconds_in_year) \
  private(i, t0, tout, t, y, data, user_data, cvode_mem, flag, nfails)
  for (n = 0; n < *npart; n++) {

    /* Store the number of threads being used */
#ifdef OPENMP
    if (n == 0) nthread = omp_get_num_threads();
#endif

    /* Reset the integration failure counter */
    nfails = 0;

    /* Specify the start and end time of the integration (in seconds) */
    t0 = start_time*seconds_in_year;
    tout = end_time*seconds_in_year;

    /* Create a serial vector of length NEQ to contain the abundances */
    y = NULL;
    y = N_VNew_Serial(neq);
    if (check_flag((void *)y, "N_VNew_Serial", 0)) status = 1;

    /* Initialize y from the abundance array */
    data = NV_DATA_S(y);
    for (i = 0; i < neq; i++) {
#ifdef LOG_ODES
      if (abundance[n*(*nspec)+i] > 0) data[i] = log(abundance[n*(*nspec)+i]);
      else data[i] = log(abstol*abstol);
#else
      data[i] = abundance[n*(*nspec)+i];
#endif
    }

    /* Create and allocate memory to user_data to contain the rates */
    user_data = NULL;
    user_data = (User_Data) malloc(sizeof *user_data);
    if(check_flag((void *)user_data, "malloc", 2)) status = 1;

    /* Initialize user_data with the array of reaction rate coefficients,
     * the total number density, gas temperature and electron abundance */
    user_data->rate = &rate[n*(*nreac)];
    user_data->n_H = density[n];
    user_data->T_g = temperature[n];
    user_data->x_e = abundance[n*(*nspec)+nelect];

    /* Call CVodeCreate to create the solver memory and specify the
     * use of Backward Differentiation Formula and Newton iteration */
    cvode_mem = NULL;
    cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
    if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) status = 1;

    /* Call CVodeSetErrFile to direct all error messages to the log file */
    flag = CVodeSetErrFile(cvode_mem, cvoderr);
    if (check_flag(&flag, "CVodeSetErrFile", 1)) status = 1;

    /* Call CVodeInit to initialize the integrator memory and specify the
     * right hand side function in ydot = f(t,y), the inital time t0, and
     * the initial dependent variable vector y */
    flag = CVodeInit(cvode_mem, f, t0, y);
    if (check_flag(&flag, "CVodeInit", 1)) status = 1;

    /* Call CVodeSStolerances to set the relative and absolute tolerances */
    flag = CVodeSStolerances(cvode_mem, reltol, abstol);
    if (check_flag(&flag, "CVodeSStolerances", 1)) status = 1;

    /* Call CVodeSetMaxNumSteps to set the maximum number of steps */
    flag = CVodeSetMaxNumSteps(cvode_mem, mxstep);
    if (check_flag(&flag, "CVodeSetMaxNumSteps", 1)) status = 1;

    /* Specify the user-defined data to be passed to the various routines */
    flag = CVodeSetUserData(cvode_mem, user_data);
    if (check_flag(&flag, "CVodeSetUserData", 1)) status = 1;

    /* Specify that the CVDense direct dense linear solver is to be used */
    flag = CVDense(cvode_mem, neq);
    if (check_flag(&flag, "CVDense", 1)) status = 1;

    /* Specify that a user-supplied Jacobian routine (Jac) is to be used */
    /* flag = CVDlsSetDenseJacFn(cvode_mem, Jac); */
    /* if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) status = 1; */

    tout = 1.0e-4*seconds_in_year;

    do { /* Call CVode, check the return status and loop until the end time is reached */

      flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);

#pragma omp critical (status)
      if (flag == 0) {
        if (nfails > 0) {
          fprintf(cvoderr, "Call to CVODE successful: particle = %d, t = %8.2le yr, # steps = %ld\n\n", n, t/seconds_in_year, mxstep);
        }
      }
      else {
        nfails++;
        if (flag == -1) {
          if (nfails < 5) {
            fprintf(cvoderr, "  Particle %d: Doubling mxstep and continuing the integration.\n\n", n);
            flag = CVodeSetMaxNumSteps(cvode_mem, mxstep);
            if (check_flag(&flag, "CVodeSetMaxNumSteps", 1)) status = 1;
	  }
          else {
            fprintf(stderr, " WARNING! CVODE solver failed: flag = %d\n", flag);
            fprintf(cvoderr, "ERROR! Fifth failure - aborting integration\n\n");
            fprintf(cvoderr, "-----------------------------------------------\n");
            fprintf(cvoderr, "CVODE Parameters:\n\n");
            fprintf(cvoderr, "Particle %d\n\n", n);
            fprintf(cvoderr, "Before:\n");
            fprintf(cvoderr, "flag   = %d\n", 0);
            fprintf(cvoderr, "t      = %8.2le yr\n", start_time);
            fprintf(cvoderr, "tout   = %8.2le yr\n", end_time);
            fprintf(cvoderr, "dt     = %8.2le yr\n\n", end_time-start_time);
            fprintf(cvoderr, "After:\n");
            fprintf(cvoderr, "flag   = %d\n", flag);
            fprintf(cvoderr, "t      = %8.2le yr\n", t/seconds_in_year);
            fprintf(cvoderr, "tout   = %8.2le yr\n", tout/seconds_in_year);
            fprintf(cvoderr, "dt     = %8.2le yr\n", (tout-t)/seconds_in_year);
            fprintf(cvoderr, "-----------------------------------------------\n\n");
            status = flag;
          }
        }
        else if (flag == -4) {
          if (nfails < 5) {
            fprintf(cvoderr, "  Particle %d: Attempting to continue the integration using the same parameters.\n\n", n);
          }
          else {
            fprintf(stderr, " WARNING! CVODE solver failed: flag = %d\n", flag);
            fprintf(cvoderr, "ERROR! Fifth failure - aborting integration\n\n");
            fprintf(cvoderr, "-----------------------------------------------\n");
            fprintf(cvoderr, "CVODE Parameters:\n\n");
            fprintf(cvoderr, "Particle %d\n\n", n);
            fprintf(cvoderr, "Before:\n");
            fprintf(cvoderr, "flag   = %d\n", 0);
            fprintf(cvoderr, "t      = %8.2le yr\n", start_time);
            fprintf(cvoderr, "tout   = %8.2le yr\n", end_time);
            fprintf(cvoderr, "dt     = %8.2le yr\n\n", end_time-start_time);
            fprintf(cvoderr, "After:\n");
            fprintf(cvoderr, "flag   = %d\n", flag);
            fprintf(cvoderr, "t      = %8.2le yr\n", t/seconds_in_year);
            fprintf(cvoderr, "tout   = %8.2le yr\n", tout/seconds_in_year);
            fprintf(cvoderr, "dt     = %8.2le yr\n", (tout-t)/seconds_in_year);
            fprintf(cvoderr, "-----------------------------------------------\n\n");
            status = flag;
          }
        }
        else {
          fprintf(stderr, " WARNING! CVODE solver failed: flag = %d\n", flag);
          fprintf(cvoderr, "ERROR! CVODE failed with the following parameters:\n\n");
          fprintf(cvoderr, "-----------------------------------------------\n");
          fprintf(cvoderr, "CVODE Parameters:\n\n");
          fprintf(cvoderr, "Particle %d\n\n", n);
          fprintf(cvoderr, "Before:\n");
          fprintf(cvoderr, "flag   = %d\n", 0);
          fprintf(cvoderr, "t      = %8.2le yr\n", start_time);
          fprintf(cvoderr, "tout   = %8.2le yr\n", end_time);
          fprintf(cvoderr, "dt     = %8.2le yr\n\n", end_time-start_time);
          fprintf(cvoderr, "After:\n");
          fprintf(cvoderr, "flag   = %d\n", flag);
          fprintf(cvoderr, "t      = %8.2le yr\n", t/seconds_in_year);
          fprintf(cvoderr, "tout   = %8.2le yr\n", tout/seconds_in_year);
          fprintf(cvoderr, "dt     = %8.2le yr\n", (tout-t)/seconds_in_year);
          fprintf(cvoderr, "-----------------------------------------------\n\n");
          status = flag;
          nfails = 5;
        }
      }

      tout = tout*10;
      if (tout > end_time*seconds_in_year) tout = end_time*seconds_in_year;

    } while (t < tout && nfails < 5);

    /* Store the output values in the abundance array */
    data = NV_DATA_S(y);
    for (i = 0; i < neq; i++) {
#ifdef LOG_ODES
      abundance[n*(*nspec)+i] = exp(data[i]);
#else
      abundance[n*(*nspec)+i] = data[i];
#endif
      if(abundance[n*(*nspec)+i] < abstol) abundance[n*(*nspec)+i] = 0;
    }
    abundance[n*(*nspec)+nelect] = user_data->x_e;

    /* Free y vector memory allocation */
    N_VDestroy_Serial(y);

    /* Free user_data memory allocation */
    free(user_data);

    /* Free integrator memory allocation */
    CVodeFree(&cvode_mem);

  } /* End of for-loop over particles */

#ifdef OPENMP
  cpu_end = omp_get_wtime();
#else
  cpu_end = clock();
#endif

  /* Close the error log files */
  fclose(cvoderr);
  fclose(stderr);

  if (status != 0) {
    fprintf(stdout, "\n ERROR! Calculation of abundances failed with status = %d\n\n", status);
#ifdef DEBUG
    fprintf(stdout, " Elapsed time = %0.3f seconds\n", cpu_end-cpu_start);
#ifdef OPENMP
    fprintf(stdout, " Threads used = %d (maximum %d)\n\n", nthread, omp_get_max_threads());
#endif
#endif
  }

  else {
#ifdef DEBUG
    fprintf(stdout, "  --> Elapsed time = %0.3f seconds\n", cpu_end-cpu_start);
#ifdef OPENMP
    fprintf(stdout, "  --> Threads used = %d (maximum %d)\n", nthread, omp_get_max_threads());
#endif
#endif
  }

  return(status);
}