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); }
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); }
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); }