void CVodeInt::initialize(double t0, FuncEval& func) { m_neq = func.neq(); m_t0 = t0; if (m_y) { N_VFree(nv(m_y)); // free solution vector if already allocated } m_y = reinterpret_cast<void*>(N_VNew(m_neq, 0)); // allocate solution vector // check abs tolerance array size if (m_itol == 1 && m_nabs < m_neq) throw CVodeErr("not enough absolute tolerance values specified."); func.getInitialConditions(m_t0, m_neq, N_VDATA(nv(m_y))); // set options m_iopt[MXSTEP] = m_maxsteps; m_iopt[MAXORD] = m_maxord; m_ropt[HMAX] = m_hmax; if (m_cvode_mem) CVodeFree(m_cvode_mem); // pass a pointer to func in m_data m_data = (void*)&func; if (m_itol) { m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, nv(m_abstol), m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } else { m_cvode_mem = CVodeMalloc(m_neq, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, &m_abstols, m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } if (!m_cvode_mem) throw CVodeErr("CVodeMalloc failed."); if (m_type == DENSE + NOJAC) { CVDense(m_cvode_mem, NULL, NULL); } else if (m_type == DENSE + JAC) { CVDense(m_cvode_mem, cvode_jac, NULL); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0, NULL, NULL, NULL); } else { throw CVodeErr("unsupported option"); } }
void ode_solver_init(ode_solver* solver, const double t0, double* y0, int lenY, double* p, int lenP ){ int i,flag; /* Get parameters */ if (p != 0){ if (lenP != solver->odeModel->P) { fprintf(stderr,"ode_solver_init: lenP must be equal %d, the number of parameters in the ode model.\n",solver->odeModel->P); return ; } for(i = 0; i < solver->odeModel->P; i++) solver->params[i] = p[i]; } /* Get initial conditions */ if(y0 != 0){ if( lenY != solver->odeModel->N ){ fprintf(stderr,"ode_solver_init: lenY must be equal %d, the number of variables in the ode model.\n",solver->odeModel->N); return ; } NV_DATA_S(solver->y) = y0; } /* initialise */ flag = CVodeInit(solver->cvode_mem, solver->odeModel->vf_eval, t0, solver->y); flag = CVodeSetUserData(solver->cvode_mem, solver->params); flag = CVDense(solver->cvode_mem, solver->odeModel->N); flag = CVDlsSetDenseJacFn(solver->cvode_mem, solver->odeModel->vf_jac); flag = CVodeSStolerances(solver->cvode_mem, ODE_SOLVER_REL_ERR, ODE_SOLVER_ABS_ERR); flag = CVodeSetMaxNumSteps(solver->cvode_mem, ODE_SOLVER_MX_STEPS); }
void CVodeInt::reinitialize(double t0, FuncEval& func) { m_t0 = t0; func.getInitialConditions(m_t0, m_neq, N_VDATA(nv(m_y))); // set options m_iopt[MXSTEP] = m_maxsteps; m_iopt[MAXORD] = m_maxord; m_ropt[HMAX] = m_hmax; //if (m_cvode_mem) CVodeFree(m_cvode_mem); // pass a pointer to func in m_data m_data = (void*)&func; int result; if (m_itol) { result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, nv(m_abstol), m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } else { result = CVReInit(m_cvode_mem, cvode_rhs, m_t0, nv(m_y), m_method, m_iter, m_itol, &m_reltol, &m_abstols, m_data, NULL, TRUE, m_iopt, DATA_PTR(m_ropt), NULL); } if (result != 0) throw CVodeErr("CVReInit failed."); if (m_type == DENSE + NOJAC) { CVDense(m_cvode_mem, NULL, NULL); } else if (m_type == DENSE + JAC) { CVDense(m_cvode_mem, cvode_jac, NULL); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, NONE, MODIFIED_GS, 0, 0.0, NULL, NULL, NULL); } else { throw CVodeErr("unsupported option"); } }
static int PrepareNextRun(void *cvode_mem, int lmm, int miter, long int mu, long int ml) { int flag = CV_SUCCESS; printf("\n\n-------------------------------------------------------------"); printf("\n\nLinear Multistep Method : "); if (lmm == CV_ADAMS) { printf("ADAMS\n"); } else { printf("BDF\n"); } printf("Iteration : "); if (miter == FUNC) { printf("FUNCTIONAL\n"); } else { printf("NEWTON\n"); printf("Linear Solver : "); switch(miter) { case DENSE_USER : printf("Dense, User-Supplied Jacobian\n"); flag = CVDense(cvode_mem, P1_NEQ); check_flag(&flag, "CVDense", 1); if(flag != CV_SUCCESS) break; flag = CVDenseSetJacFn(cvode_mem, Jac1, NULL); check_flag(&flag, "CVDenseSetJacFn", 1); break; case DENSE_DQ : printf("Dense, Difference Quotient Jacobian\n"); flag = CVDenseSetJacFn(cvode_mem, NULL, NULL); check_flag(&flag, "CVDenseSetJacFn", 1); break; case DIAG : printf("Diagonal Jacobian\n"); flag = CVDiag(cvode_mem); check_flag(&flag, "CVDiag", 1); break; case BAND_USER : printf("Band, User-Supplied Jacobian\n"); flag = CVBand(cvode_mem, P2_NEQ, mu, ml); check_flag(&flag, "CVBand", 1); if(flag != CV_SUCCESS) break; flag = CVBandSetJacFn(cvode_mem, Jac2, NULL); check_flag(&flag, "CVBandSetJacFn", 1); break; case BAND_DQ : printf("Band, Difference Quotient Jacobian\n"); flag = CVBandSetJacFn(cvode_mem, NULL, NULL); check_flag(&flag, "CVBandSetJacFn", 1); break; } } return(flag); }
void FCV_DENSE(long int *neq, int *ier) { /* neq is the problem size */ *ier = CVDense(CV_cvodemem, *neq); CV_ls = 1; }
int CVDenseB(void *cvadj_mem, long int nB) { CVadjMem ca_mem; void *cvode_mem; int flag; if (cvadj_mem == NULL) return(CV_ADJMEM_NULL); ca_mem = (CVadjMem) cvadj_mem; cvode_mem = (void *) ca_mem->cvb_mem; flag = CVDense(cvode_mem, nB); return(flag); }
void CVodesIntegrator::applyOptions() { if (m_type == DENSE + NOJAC) { sd_size_t N = static_cast<sd_size_t>(m_neq); #if SUNDIALS_USE_LAPACK CVLapackDense(m_cvode_mem, N); #else CVDense(m_cvode_mem, N); #endif } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, PREC_NONE, 0); } else if (m_type == BAND + NOJAC) { sd_size_t N = static_cast<sd_size_t>(m_neq); long int nu = m_mupper; long int nl = m_mlower; #if SUNDIALS_USE_LAPACK CVLapackBand(m_cvode_mem, N, nu, nl); #else CVBand(m_cvode_mem, N, nu, nl); #endif } else { throw CanteraError("CVodesIntegrator::applyOptions", "unsupported option"); } if (m_maxord > 0) { CVodeSetMaxOrd(m_cvode_mem, m_maxord); } if (m_maxsteps > 0) { CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); } if (m_hmax > 0) { CVodeSetMaxStep(m_cvode_mem, m_hmax); } if (m_hmin > 0) { CVodeSetMinStep(m_cvode_mem, m_hmin); } if (m_maxErrTestFails > 0) { CVodeSetMaxErrTestFails(m_cvode_mem, m_maxErrTestFails); } }
cvode_mem *SOLVER(cvode, init, TARGET, SIMENGINE_STORAGE, solver_props *props){ cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem)); unsigned int modelid; // Only need to create this buffer in the first memory space as we are using this only for scratch // and outside of the CVODE solver to compute the last outputs mem[0].k1 = (CDATAFORMAT*)malloc(props->statesize*props->num_models*sizeof(CDATAFORMAT)); for(modelid=0; modelid<props->num_models; modelid++){ // Set the modelid on a per memory structure basis mem[modelid].modelid = modelid; // Store solver properties mem[modelid].props = props; // Create intial value vector // This is done to avoid having the change the internal indexing within the flows and for the output_buffer mem[modelid].y0 = N_VMake_Serial(props->statesize, &(props->model_states[modelid*props->statesize])); // Create data structure for solver mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON); // Initialize CVODE if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, ((N_Vector)(mem[modelid].y0))) != CV_SUCCESS){ fprintf(stderr, "Couldn't initialize CVODE"); } // Set solver tolerances if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){ fprintf(stderr, "Could not set CVODE tolerances"); } // Set linear solver if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){ fprintf(stderr, "Could not set CVODE linear solver"); } // Set user data to contain pointer to memory structure for use in model_flows if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){ fprintf(stderr, "CVODE failed to initialize user data"); } } return mem; }
int main(int narg, char **args) { realtype reltol, t, tout; N_Vector state, abstol; void *cvode_mem; int flag, flagr; int rootsfound[NRF]; int rootdir[] = {1,}; FILE *pout; if(!(pout = fopen("results/iaf_v.dat", "w"))){ fprintf(stderr, "Cannot open file results/iaf_v.dat. Are you trying to write to a non-existent directory? Exiting...\n"); exit(1); } state = abstol = NULL; cvode_mem = NULL; state = N_VNew_Serial(NEQ); if (check_flag((void *)state, "N_VNew_Serial", 0)) return(1); abstol = N_VNew_Serial(NEQ); if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1); realtype reset = -0.07; realtype C = 3.2e-12; realtype thresh = -0.055; realtype gleak = 2e-10; realtype eleak = -0.053; realtype p[] = {reset, C, thresh, gleak, eleak, }; realtype v = reset; NV_Ith_S(state, 0) = reset; reltol = RTOL; NV_Ith_S(abstol,0) = ATOL0; /* Allocations and initializations */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeInit(cvode_mem, dstate_dt, T0, state); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSetUserData(cvode_mem, p); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); flag = CVodeRootInit(cvode_mem, NRF, root_functions); if (check_flag(&flag, "CVodeRootInit", 1)) return(1); CVodeSetRootDirection(cvode_mem, rootdir); if (check_flag(&flag, "CVodeSetRootDirection", 1)) return(1); flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); printf(" \n Integrating iaf \n\n"); printf("#t v, \n"); PrintOutput(pout, t, state); tout = DT; while(1) { flag = CVode(cvode_mem, tout, state, &t, CV_NORMAL); if(flag == CV_ROOT_RETURN) { /* Event detected */ flagr = CVodeGetRootInfo(cvode_mem, rootsfound); if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1); PrintRootInfo(t, state, rootsfound); if(rootsfound[0]){ //condition_0 v = NV_Ith_S(state, 0); NV_Ith_S(state, 0) = reset; } /* Restart integration with event-corrected state */ flag = CVodeSetUserData(cvode_mem, p); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); CVodeReInit(cvode_mem, t, state); //PrintRootInfo(t, state, rootsfound); } else { PrintOutput(pout, t, state); if(check_flag(&flag, "CVode", 1)) break; if(flag == CV_SUCCESS) { tout += DT; } if (t >= T1) break; } } PrintFinalStats(cvode_mem); N_VDestroy_Serial(state); N_VDestroy_Serial(abstol); CVodeFree(&cvode_mem); fclose(pout); return(0); }
int main() { realtype t, tout; N_Vector y; void *cvode_mem; int flag, flagr, iout; int rootsfound[2]; y = NULL; cvode_mem = NULL; /* Create serial vector of length NEQ for I.C. */ y = N_VNew_Serial(NEQ); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); /* Initialize y */ Ith(y,1) = Y1; Ith(y,2) = Y2; Ith(y,3) = Y3; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in y'=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)) return(1); /* Use private function to compute error weights */ flag = CVodeWFtolerances(cvode_mem, ewt); if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1); /* Call CVodeRootInit to specify the root function g with 2 components */ flag = CVodeRootInit(cvode_mem, 2, g); if (check_flag(&flag, "CVodeRootInit", 1)) return(1); /* Call CVDense to specify the CVDENSE dense linear solver */ flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); /* Set the Jacobian routine to Jac (user-supplied) */ flag = CVDlsSetDenseJacFn(cvode_mem, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); /* In loop, call CVode, print results, and test for error. Break out of loop when NOUT preset output times have been reached. */ printf(" \n3-species kinetics problem\n\n"); iout = 0; tout = T1; while(1) { flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL); PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3)); if (flag == CV_ROOT_RETURN) { flagr = CVodeGetRootInfo(cvode_mem, rootsfound); check_flag(&flagr, "CVodeGetRootInfo", 1); PrintRootInfo(rootsfound[0],rootsfound[1]); } if (check_flag(&flag, "CVode", 1)) break; if (flag == CV_SUCCESS) { iout++; tout *= TMULT; } if (iout == NOUT) break; } /* Print some final statistics */ PrintFinalStats(cvode_mem); /* Free y vector */ N_VDestroy_Serial(y); /* Free integrator memory */ CVodeFree(&cvode_mem); return(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); }
int cvode_init(solver_props *props){ assert(props->statesize > 0); cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem)); unsigned int modelid; props->mem = mem; for(modelid=0; modelid<props->num_models; modelid++){ // Set location to store the value of the next states mem[modelid].next_states = &(props->next_states[modelid*props->statesize]); mem[modelid].props = props; // Set the modelid on a per memory structure basis mem[modelid].modelid = modelid; // Create intial value vector // This is done to avoid having the change the internal indexing within the flows and for the output_buffer mem[modelid].y0 = N_VMake_Serial(props->statesize, mem[modelid].next_states); // Create data structure for solver // mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON); mem[modelid].cvmem = CVodeCreate(props->cvode.lmm, props->cvode.iter); // Initialize CVODE if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, mem[modelid].y0) != CV_SUCCESS){ PRINTF( "Couldn't initialize CVODE"); } // Set CVODE error handler if(CVodeSetErrHandlerFn(mem[modelid].cvmem, cvode_err_handler, mem)){ PRINTF( "Couldn't set CVODE error handler"); } // Set solver tolerances if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){ PRINTF( "Could not set CVODE tolerances"); } // Set maximum order if(CVodeSetMaxOrd(mem[modelid].cvmem, props->cvode.max_order) != CV_SUCCESS) { PRINTF( "Could not set CVODE maximum order"); } // Set linear solver switch (props->cvode.solv) { case CVODE_DENSE: if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){ PRINTF( "Could not set CVODE DENSE linear solver"); } break; case CVODE_DIAG: if(CVDiag(mem[modelid].cvmem) != CV_SUCCESS){ PRINTF( "Could not set CVODE DIAG linear solver"); } break; case CVODE_BAND: if(CVBand(mem[modelid].cvmem, mem[modelid].props->statesize, mem[modelid].props->cvode.upperhalfbw, mem[modelid].props->cvode.lowerhalfbw) != CV_SUCCESS){ PRINTF( "Could not set CVODE BAND linear solver"); } break; default: PRINTF( "No valid CVODE solver passed"); } // Set user data to contain pointer to memory structure for use in model_flows if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){ PRINTF( "CVODE failed to initialize user data"); } } return 0; }
int CVDenseB(void *cvode_mem, int which, long int nB) { CVodeMem cv_mem; CVadjMem ca_mem; CVodeBMem cvB_mem; void *cvodeB_mem; CVDlsMemB cvdlsB_mem; int flag; /* Check if cvode_mem exists */ if (cvode_mem == NULL) { cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDENSE", "CVDenseB", MSGD_CVMEM_NULL); return(CVDLS_MEM_NULL); } cv_mem = (CVodeMem) cvode_mem; /* Was ASA initialized? */ if (cv_mem->cv_adjMallocDone == FALSE) { cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDENSE", "CVDenseB", MSGD_NO_ADJ); return(CVDLS_NO_ADJ); } ca_mem = cv_mem->cv_adj_mem; /* Check which */ if ( which >= ca_mem->ca_nbckpbs ) { cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDENSE", "CVDenseB", MSGD_BAD_WHICH); return(CVDLS_ILL_INPUT); } /* Find the CVodeBMem entry in the linked list corresponding to which */ cvB_mem = ca_mem->cvB_mem; while (cvB_mem != NULL) { if ( which == cvB_mem->cv_index ) break; cvB_mem = cvB_mem->cv_next; } cvodeB_mem = (void *) (cvB_mem->cv_mem); /* Get memory for CVDlsMemRecB */ cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB)); if (cvdlsB_mem == NULL) { cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDenseB", MSGD_MEM_FAIL); return(CVDLS_MEM_FAIL); } /* set matrix type */ cvdlsB_mem->d_typeB = SUNDIALS_DENSE; /* initialize Jacobian function */ cvdlsB_mem->d_djacB = NULL; /* attach lmemB and lfreeB */ cvB_mem->cv_lmem = cvdlsB_mem; cvB_mem->cv_lfree = cvDenseFreeB; flag = CVDense(cvodeB_mem, nB); if (flag != CVDLS_SUCCESS) { free(cvdlsB_mem); cvdlsB_mem = NULL; } return(flag); }
/* * Functions to use CVODES * */ struct Integrator* CreateIntegrator(struct Simulation* sim, class ExecutableModel* em) { if (!(sim && em)) { ERROR("CreateIntegrator","Invalid arguments when creating integrator"); return((struct Integrator*)NULL); } int flag,mlmm,miter; struct Integrator* integrator = (struct Integrator*)malloc(sizeof(struct Integrator)); integrator->y = NULL; integrator->cvode_mem = NULL; integrator->simulation = simulationClone(sim); // FIXME: really need to handle this properly, but for now simply grabbing a handle. integrator->em = em; /* Check for errors in the simulation */ if (simulationGetATolLength(integrator->simulation) < 1) { ERROR("CreateIntegrator","Absolute tolerance(s) not set\n"); DestroyIntegrator(&integrator); return(NULL); } /* Would be good if we didn't require the specification of the tabulation step size, but for now it is required so we should check that it has a sensible value */ if (!simulationIsBvarTabStepSet(integrator->simulation)) { ERROR("CreateIntegrator","Tabulation step size must be set\n"); DestroyIntegrator(&integrator); return(NULL); } /* start and end also needs to be set */ if (!simulationIsBvarStartSet(integrator->simulation)) { ERROR("CreateIntegrator","Bound variable interval start must be set\n"); DestroyIntegrator(&integrator); return(NULL); } if (!simulationIsBvarEndSet(integrator->simulation)) { ERROR("CreateIntegrator","Bound variable interval end must be set\n"); DestroyIntegrator(&integrator); return(NULL); } /* Create serial vector of length NR for I.C. */ integrator->y = N_VNew_Serial(em->nRates); if (check_flag((void *)(integrator->y),"N_VNew_Serial",0)) { DestroyIntegrator(&integrator); return(NULL); } /* Initialize y */ realtype* yD = NV_DATA_S(integrator->y); int i; for (i=0;i<(em->nRates);i++) yD[i] = (realtype)(em->states[i]); /* adjust parameters accordingly */ switch (simulationGetMultistepMethod(integrator->simulation)) { case ADAMS: { mlmm = CV_ADAMS; break; } case BDF: { mlmm = CV_BDF; break; } default: { ERROR("CreateIntegrator","Invalid multistep method choice\n"); DestroyIntegrator(&integrator); return(NULL); } } switch (simulationGetIterationMethod(integrator->simulation)) { case FUNCTIONAL: { miter = CV_FUNCTIONAL; break; } case NEWTON: { miter = CV_NEWTON; break; } default: { ERROR("CreateIntegrator","Invalid iteration method choice\n"); DestroyIntegrator(&integrator); return(NULL); } } /* Call CVodeCreate to create the solver memory: A pointer to the integrator problem memory is returned and stored in cvode_mem. */ integrator->cvode_mem = CVodeCreate(mlmm,miter); if (check_flag((void *)(integrator->cvode_mem),"CVodeCreate",0)) { DestroyIntegrator(&integrator); return(NULL); } /* Call CVodeMalloc to initialize the integrator memory: cvode_mem is the pointer to the integrator memory returned by CVodeCreate f is the user's right hand side function in y'=f(t,y) tStart is the initial time y is the initial dependent variable vector CV_SS specifies scalar relative and absolute tolerances reltol the scalar relative tolerance &abstol is the absolute tolerance vector */ flag = CVodeInit(integrator->cvode_mem,f, simulationGetBvarStart(integrator->simulation),integrator->y); if (check_flag(&flag,"CVodeMalloc",1)) { DestroyIntegrator(&integrator); return(NULL); } double* atol = simulationGetATol(integrator->simulation); if (simulationGetATolLength(integrator->simulation) == 1) { flag = CVodeSStolerances(integrator->cvode_mem,simulationGetRTol(integrator->simulation),atol[0]); if (check_flag(&flag,"CVodeSStolerances",1)) { DestroyIntegrator(&integrator); return(NULL); } } else { ERROR("CreateIntegrator", "array abstol not supported yet."); DestroyIntegrator(&integrator); return(NULL); } free(atol); /* if using Newton iteration need a linear solver */ if (simulationGetIterationMethod(integrator->simulation) == NEWTON) { switch (simulationGetLinearSolver(integrator->simulation)) { case DENSE: { /* Call CVDense to specify the CVDENSE dense linear solver */ flag = CVDense(integrator->cvode_mem,em->nRates); if (check_flag(&flag,"CVDense",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case BAND: { /* Call CVBand to specify the CVBAND linear solver */ long int upperBW = em->nRates - 1; /* FIXME: This probably doesn't make */ long int lowerBW = em->nRates - 1; /* any sense, but should do until I */ /* fix it */ flag = CVBand(integrator->cvode_mem,em->nRates,upperBW,lowerBW); if (check_flag(&flag,"CVBand",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case DIAG: { /* Call CVDiag to specify the CVDIAG linear solver */ flag = CVDiag(integrator->cvode_mem); if (check_flag(&flag,"CVDiag",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case SPGMR: { /* Call CVSpgmr to specify the linear solver CVSPGMR with no preconditioning and the maximum Krylov dimension maxl */ flag = CVSpgmr(integrator->cvode_mem,PREC_NONE,0); if(check_flag(&flag,"CVSpgmr",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case SPBCG: { /* Call CVSpbcg to specify the linear solver CVSPBCG with no preconditioning and the maximum Krylov dimension maxl */ flag = CVSpbcg(integrator->cvode_mem,PREC_NONE,0); if(check_flag(&flag,"CVSpbcg",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; case SPTFQMR: { /* Call CVSptfqmr to specify the linear solver CVSPTFQMR with no preconditioning and the maximum Krylov dimension maxl */ flag = CVSptfqmr(integrator->cvode_mem,PREC_NONE,0); if(check_flag(&flag,"CVSptfqmr",1)) { DestroyIntegrator(&integrator); return(NULL); } } break; default: { ERROR("CreateIntegrator", "Must specify a valid linear solver when using " "Newton iteration\n"); DestroyIntegrator(&integrator); return(NULL); } } } /* Pass through the executable model to f */ // FIXME: really need to handle this properly, but for now simply grabbing a handle. flag = CVodeSetUserData(integrator->cvode_mem,(void*)(em)); if (check_flag(&flag,"CVodeSetUserData",1)) { DestroyIntegrator(&integrator); return(NULL); } /* Set the maximum time step size if it looks valid */ double mxD = simulationGetBvarMaxStep(integrator->simulation); double tbD = simulationGetBvarTabStep(integrator->simulation); double maxStep; if (simulationIsBvarMaxStepSet(integrator->simulation)) { flag = CVodeSetMaxStep(integrator->cvode_mem, (realtype)mxD); maxStep = mxD; if (check_flag(&flag,"CVodeSetMaxStep (max)",1)) { DestroyIntegrator(&integrator); return(NULL); } } else { flag = CVodeSetMaxStep(integrator->cvode_mem, (realtype)tbD); maxStep = tbD; if (check_flag(&flag,"CVodeSetMaxStep (tab)",1)) { DestroyIntegrator(&integrator); return(NULL); } } simulationSetBvarMaxStep(integrator->simulation,maxStep); simulationSetBvarMaxStep(sim,maxStep); /* try and make a sensible guess at the maximal number of steps to get to tout to take into account case where we simply want to integrate over a large time period in small steps (why?) */ double tout = simulationGetBvarStart(integrator->simulation)+ simulationGetBvarTabStep(integrator->simulation); if (simulationIsBvarEndSet(integrator->simulation)) { double end = simulationGetBvarEnd(integrator->simulation); if (tout > end) tout = end; } long int maxsteps = (long int)ceil(tout/maxStep) * 100; if (maxsteps < 500) maxsteps = 500; /* default value */ flag = CVodeSetMaxNumSteps(integrator->cvode_mem,maxsteps); if (check_flag(&flag,"CVodeSetMaxNumSteps",1)) { DestroyIntegrator(&integrator); return(NULL); } return(integrator); }
int dynamixMain (int argc, char * argv[]) { //// DECLARING VARIABLES // Struct of parameters PARAMETERS p; // CVode variables void * cvode_mem = NULL; // pointer to block of CVode memory N_Vector y, yout; // arrays of populations // arrays for energetic parameters realtype ** V = NULL; // pointer to k-c coupling constants realtype * Vbridge = NULL; // pointer to array of bridge coupling constants. // first element [0] is Vkb1, last [Nb] is VcbN realtype * Vnobridge = NULL; // coupling constant when there is no bridge //// Setting defaults for parameters to be read from input //// done setting defaults int flag; realtype * k_pops = NULL; // pointers to arrays of populations realtype * l_pops = NULL; realtype * c_pops = NULL; realtype * b_pops = NULL; realtype * ydata = NULL; // pointer to ydata (contains all populations) realtype * wavefunction = NULL; // (initial) wavefunction realtype * dm = NULL; // density matrix realtype * dmt = NULL; // density matrix in time realtype * wfnt = NULL; // density matrix in time realtype * k_energies = NULL; // pointers to arrays of energies realtype * c_energies = NULL; realtype * b_energies = NULL; realtype * l_energies = NULL; realtype t0 = 0.0; // initial time realtype t = 0; realtype tret = 0; // time returned by the solver time_t startRun; // time at start of log time_t endRun; // time at end of log struct tm * currentTime = NULL; // time structure for localtime #ifdef DEBUG FILE * realImaginary; // file containing real and imaginary parts of the wavefunction #endif FILE * log; // log file with run times realtype * tkprob = NULL; // total probability in k, l, c, b states at each timestep realtype * tlprob = NULL; realtype * tcprob = NULL; realtype * tbprob = NULL; double ** allprob = NULL; // populations in all states at all times realtype * times = NULL; realtype * qd_est = NULL; realtype * qd_est_diag = NULL; std::string inputFile = "ins/parameters.in"; // name of input file std::string cEnergiesInput = "ins/c_energies.in"; std::string cPopsInput = "ins/c_pops.in"; std::string bEnergiesInput = "ins/b_energies.in"; std::string VNoBridgeInput = "ins/Vnobridge.in"; std::string VBridgeInput = "ins/Vbridge.in"; std::map<const std::string, bool> outs; // map of output file names to bool // default output directory p.outputDir = "outs/"; double summ = 0; // sum variable // ---- process command line flags ---- // opterr = 0; int c; std::string insDir; /* process command line options */ while ((c = getopt(argc, argv, "i:o:")) != -1) { switch (c) { case 'i': // check that it ends in a slash std::cerr << "[dynamix]: assigning input directory" << std::endl; insDir = optarg; if (strcmp(&(insDir.at(insDir.length() - 1)), "/")) { std::cerr << "ERROR: option -i requires argument (" << insDir << ") to have a trailing slash (/)." << std::endl; return 1; } else { // ---- assign input files ---- // inputFile = insDir + "parameters.in"; cEnergiesInput = insDir + "c_energies.in"; cPopsInput = insDir + "c_pops.in"; bEnergiesInput = insDir + "b_energies.in"; VNoBridgeInput = insDir + "Vnobridge.in"; VBridgeInput = insDir + "Vbridge.in"; } break; case 'o': std::cerr << "[dynamix]: assigning output directory" << std::endl; p.outputDir = optarg; break; case '?': if (optopt == 'i') { fprintf(stderr, "Option -%c requires a directory argument.\n", optopt); } else if (isprint(optopt)) { fprintf(stderr, "Unknown option -%c.\n", optopt); } else { fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); } return 1; default: continue; } } optind = 1; // reset global variable counter for the next time this is run std::cerr << "[dynamix]: ARGUMENTS" << std::endl; for (int ii = 0; ii < argc; ii++) { std::cerr << "[dynamix]: " << argv[ii] << std::endl; } //// ASSIGN PARAMETERS FROM INPUT FILE // ---- TODO create output directory if it does not exist ---- // flag = mkdir(p.outputDir.c_str(), 0755); std::cerr << "Looking for inputs in all the " << inputFile << " places" << std::endl; assignParams(inputFile.c_str(), &p); // Decide which output files to make #ifdef DEBUG std::cout << "Assigning outputs as specified in " << inputFile << "\n"; #endif assignOutputs(inputFile.c_str(), outs, &p); #ifdef DEBUG // print out which outputs will be made for (std::map<const std::string, bool>::iterator it = outs.begin(); it != outs.end(); it++) { std::cout << "Output file: " << it->first << " will be created.\n"; } #endif // OPEN LOG FILE; PUT IN START TIME // if (isOutput(outs, "log.out")) { log = fopen("log.out", "w"); // note that this file is closed at the end of the program } time(&startRun); currentTime = localtime(&startRun); if (isOutput(outs, "log.out")) { fprintf(log, "Run started at %s\n", asctime(currentTime)); } if (isOutput(outs, "log.out")) { // make a note about the laser intensity. fprintf(log,"The laser intensity is %.5e W/cm^2.\n\n",pow(p.pumpAmpl,2)*3.5094452e16); } //// READ DATA FROM INPUTS p.Nc = numberOfValuesInFile(cEnergiesInput.c_str()); p.Nb = numberOfValuesInFile(bEnergiesInput.c_str()); k_pops = new realtype [p.Nk]; c_pops = new realtype [p.Nc]; b_pops = new realtype [p.Nb]; l_pops = new realtype [p.Nl]; k_energies = new realtype [p.Nk]; c_energies = new realtype [p.Nc]; b_energies = new realtype [p.Nb]; l_energies = new realtype [p.Nl]; if (numberOfValuesInFile(cPopsInput.c_str()) != p.Nc) { fprintf(stderr, "ERROR [Inputs]: c_pops and c_energies not the same length.\n"); return -1; } readArrayFromFile(c_energies, cEnergiesInput.c_str(), p.Nc); if (p.bridge_on) { if (p.bridge_on && (p.Nb < 1)) { std::cerr << "\nERROR: bridge_on but no bridge states. The file b_energies.in is probably empty.\n"; return -1; } p.Vbridge.resize(p.Nb+1); readArrayFromFile(b_energies, bEnergiesInput.c_str(), p.Nb); readVectorFromFile(p.Vbridge, VBridgeInput.c_str(), p.Nb + 1); #ifdef DEBUG std::cout << "COUPLINGS:"; for (int ii = 0; ii < p.Nb+1; ii++) { std::cout << " " << p.Vbridge[ii]; } std::cout << std::endl; #endif } else { p.Nb = 0; p.Vnobridge.resize(1); readVectorFromFile(p.Vnobridge, VNoBridgeInput.c_str(), 1); } #ifdef DEBUG std::cout << "\nDone reading things from inputs.\n"; #endif //// PREPROCESS DATA FROM INPUTS // check torsion parameters, set up torsion spline if (p.torsion) { #ifdef DEBUG std::cout << "Torsion is on." << std::endl; #endif // error checking if (p.torsionSite > p.Nb) { std::cerr << "ERROR: torsion site (" << p.torsionSite << ") is larger than number of bridge sites (" << p.Nb << ")." << std::endl; exit(-1); } else if (p.torsionSite < 0) { std::cerr << "ERROR: torsion site is less than zero." << std::endl; exit(-1); } if (!fileExists(p.torsionFile)) { std::cerr << "ERROR: torsion file " << p.torsionFile << " does not exist." << std::endl; } // create spline p.torsionV = new Spline(p.torsionFile.c_str()); if (p.torsionV->getFirstX() != 0.0) { std::cerr << "ERROR: time in " << p.torsionFile << " should start at 0.0." << std::endl; exit(-1); } if (p.torsionV->getLastX() < p.tout) { std::cerr << "ERROR: time in " << p.torsionFile << " should be >= tout." << std::endl; exit(-1); } } // set number of processors for OpenMP //omp_set_num_threads(p.nproc); mkl_set_num_threads(p.nproc); p.NEQ = p.Nk+p.Nc+p.Nb+p.Nl; // total number of equations set p.NEQ2 = p.NEQ*p.NEQ; // number of elements in DM #ifdef DEBUG std::cout << "\nTotal number of states: " << p.NEQ << std::endl; std::cout << p.Nk << " bulk, " << p.Nc << " QD, " << p.Nb << " bridge, " << p.Nl << " bulk VB.\n"; #endif tkprob = new realtype [p.numOutputSteps+1]; // total population on k, b, c at each timestep tcprob = new realtype [p.numOutputSteps+1]; tbprob = new realtype [p.numOutputSteps+1]; tlprob = new realtype [p.numOutputSteps+1]; allprob = new double * [p.numOutputSteps+1]; for (int ii = 0; ii <= p.numOutputSteps; ii++) { allprob[ii] = new double [p.NEQ]; } // assign times. p.times.resize(p.numOutputSteps+1); for (int ii = 0; ii <= p.numOutputSteps; ii++) { p.times[ii] = float(ii)/p.numOutputSteps*p.tout; } qd_est = new realtype [p.numOutputSteps+1]; qd_est_diag = new realtype [p.numOutputSteps+1]; p.Ik = 0; // set index start positions for each type of state p.Ic = p.Nk; p.Ib = p.Ic+p.Nc; p.Il = p.Ib+p.Nb; // assign bulk conduction and valence band energies // for RTA, bulk and valence bands have parabolic energies if (p.rta) { buildParabolicBand(k_energies, p.Nk, p.kBandEdge, CONDUCTION, &p); buildParabolicBand(l_energies, p.Nl, p.lBandTop, VALENCE, &p); } else { buildContinuum(k_energies, p.Nk, p.kBandEdge, p.kBandTop); buildContinuum(l_energies, p.Nl, p.kBandEdge - p.valenceBand - p.bulk_gap, p.kBandEdge - p.bulk_gap); } // calculate band width p.kBandWidth = k_energies[p.Nk - 1] - k_energies[0]; //// BUILD INITIAL WAVEFUNCTION // bridge states (empty to start) initializeArray(b_pops, p.Nb, 0.0); // coefficients in bulk and other states depend on input conditions in bulk if (!p.rta) { #ifdef DEBUG std::cout << "\ninitializing k_pops\n"; #endif if (p.bulk_constant) { initializeArray(k_pops, p.Nk, 0.0); #ifdef DEBUG std::cout << "\ninitializing k_pops with constant probability in range of states\n"; #endif initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0); initializeArray(l_pops, p.Nl, 0.0); // populate l states (all 0 to start off) initializeArray(c_pops, p.Nc, 0.0); // QD states empty to start } else if (p.bulk_Gauss) { buildKPopsGaussian(k_pops, k_energies, p.kBandEdge, p.bulkGaussSigma, p.bulkGaussMu, p.Nk); // populate k states with FDD initializeArray(l_pops, p.Nl, 0.0); // populate l states (all 0 to start off) initializeArray(c_pops, p.Nc, 0.0); // QD states empty to start } else if (p.qd_pops) { readArrayFromFile(c_pops, cPopsInput.c_str(), p.Nc); // QD populations from file initializeArray(l_pops, p.Nl, 0.0); // populate l states (all 0 to start off) initializeArray(k_pops, p.Nk, 0.0); // populate k states (all zero to start off) } else { initializeArray(k_pops, p.Nk, 0.0); // populate k states (all zero to start off) initializeArray(l_pops, p.Nl, 1.0); // populate l states (all populated to start off) initializeArray(c_pops, p.Nc, 0.0); // QD states empty to start } #ifdef DEBUG std::cout << "\nThis is k_pops:\n"; for (int ii = 0; ii < p.Nk; ii++) { std::cout << k_pops[ii] << std::endl; } std::cout << "\n"; #endif } // with RTA, use different set of switches else { // bulk valence band if (p.VBPopFlag == POP_EMPTY) { #ifdef DEBUG std::cout << "Initializing empty valence band" << std::endl; #endif initializeArray(l_pops, p.Nl, 0.0); } else if (p.VBPopFlag == POP_FULL) { #ifdef DEBUG std::cout << "Initializing full valence band" << std::endl; #endif initializeArray(l_pops, p.Nl, 1.0); } else { std::cerr << "ERROR: unrecognized VBPopFlag " << p.VBPopFlag << std::endl; } // bulk conduction band if (p.CBPopFlag == POP_EMPTY) { #ifdef DEBUG std::cout << "Initializing empty conduction band" << std::endl; #endif initializeArray(k_pops, p.Nk, 0.0); } else if (p.CBPopFlag == POP_FULL) { #ifdef DEBUG std::cout << "Initializing full conduction band" << std::endl; #endif initializeArray(k_pops, p.Nk, 1.0); } else if (p.CBPopFlag == POP_CONSTANT) { #ifdef DEBUG std::cout << "Initializing constant distribution in conduction band" << std::endl; #endif initializeArray(k_pops, p.Nk, 0.0); initializeArray(k_pops, p.Nk, 1e-1); // FIXME initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0); } else if (p.CBPopFlag == POP_GAUSSIAN) { #ifdef DEBUG std::cout << "Initializing Gaussian in conduction band" << std::endl; #endif buildKPopsGaussian(k_pops, k_energies, p.kBandEdge, p.bulkGaussSigma, p.bulkGaussMu, p.Nk); } else { std::cerr << "ERROR: unrecognized CBPopFlag " << p.CBPopFlag << std::endl; } //// QD if (p.QDPopFlag == POP_EMPTY) { initializeArray(c_pops, p.Nc, 0.0); } else if (p.QDPopFlag == POP_FULL) { initializeArray(c_pops, p.Nc, 1.0); } else { std::cerr << "ERROR: unrecognized QDPopFlag " << p.QDPopFlag << std::endl; } } // create empty wavefunction wavefunction = new realtype [2*p.NEQ]; initializeArray(wavefunction, 2*p.NEQ, 0.0); // assign real parts of wavefunction coefficients (imaginary are zero) for (int ii = 0; ii < p.Nk; ii++) { wavefunction[p.Ik + ii] = k_pops[ii]; } for (int ii = 0; ii < p.Nc; ii++) { wavefunction[p.Ic + ii] = c_pops[ii]; } for (int ii = 0; ii < p.Nb; ii++) { wavefunction[p.Ib + ii] = b_pops[ii]; } for (int ii = 0; ii < p.Nl; ii++) { wavefunction[p.Il + ii] = l_pops[ii]; } if (isOutput(outs, "psi_start.out")) { outputWavefunction(wavefunction, p.NEQ); } // Give all coefficients a random phase if (p.random_phase) { float phi; // set the seed if (p.random_seed == -1) { srand(time(NULL)); } else { srand(p.random_seed); } for (int ii = 0; ii < p.NEQ; ii++) { phi = 2*3.1415926535*(float)rand()/(float)RAND_MAX; wavefunction[ii] = wavefunction[ii]*cos(phi); wavefunction[ii + p.NEQ] = wavefunction[ii + p.NEQ]*sin(phi); } } #ifdef DEBUG // print out details of wavefunction coefficients std::cout << std::endl; for (int ii = 0; ii < p.Nk; ii++) { std::cout << "starting wavefunction: Re[k(" << ii << ")] = " << wavefunction[p.Ik + ii] << std::endl; } for (int ii = 0; ii < p.Nc; ii++) { std::cout << "starting wavefunction: Re[c(" << ii << ")] = " << wavefunction[p.Ic + ii] << std::endl; } for (int ii = 0; ii < p.Nb; ii++) { std::cout << "starting wavefunction: Re[b(" << ii << ")] = " << wavefunction[p.Ib + ii] << std::endl; } for (int ii = 0; ii < p.Nl; ii++) { std::cout << "starting wavefunction: Re[l(" << ii << ")] = " << wavefunction[p.Il + ii] << std::endl; } for (int ii = 0; ii < p.Nk; ii++) { std::cout << "starting wavefunction: Im[k(" << ii << ")] = " << wavefunction[p.Ik + ii + p.NEQ] << std::endl; } for (int ii = 0; ii < p.Nc; ii++) { std::cout << "starting wavefunction: Im[c(" << ii << ")] = " << wavefunction[p.Ic + ii + p.NEQ] << std::endl; } for (int ii = 0; ii < p.Nb; ii++) { std::cout << "starting wavefunction: Im[b(" << ii << ")] = " << wavefunction[p.Ib + ii + p.NEQ] << std::endl; } for (int ii = 0; ii < p.Nl; ii++) { std::cout << "starting wavefunction: Im[l(" << ii << ")] = " << wavefunction[p.Il + ii + p.NEQ] << std::endl; } std::cout << std::endl; summ = 0; for (int ii = 0; ii < 2*p.NEQ; ii++) { summ += pow(wavefunction[ii],2); } std::cout << "\nTotal population is " << summ << "\n\n"; #endif //// ASSEMBLE ARRAY OF ENERGIES // TODO TODO p.energies.resize(p.NEQ); for (int ii = 0; ii < p.Nk; ii++) { p.energies[p.Ik + ii] = k_energies[ii]; } for (int ii = 0; ii < p.Nc; ii++) { p.energies[p.Ic + ii] = c_energies[ii]; } for (int ii = 0; ii < p.Nb; ii++) { p.energies[p.Ib + ii] = b_energies[ii]; } for (int ii = 0; ii < p.Nl; ii++) { p.energies[p.Il + ii] = l_energies[ii]; } #ifdef DEBUG for (int ii = 0; ii < p.NEQ; ii++) { std::cout << "p.energies[" << ii << "] is " << p.energies[ii] << "\n"; } #endif //// ASSIGN COUPLING CONSTANTS V = new realtype * [p.NEQ]; for (int ii = 0; ii < p.NEQ; ii++) { V[ii] = new realtype [p.NEQ]; } buildCoupling(V, &p, outs); if (isOutput(outs, "log.out")) { // make a note in the log about system timescales double tau = 0; // fundamental system timescale if (p.Nk == 1) { fprintf(log, "\nThe timescale (tau) is undefined (Nk == 1).\n"); } else { if (p.bridge_on) { if (p.scale_bubr) { tau = 1.0/(2*p.Vbridge[0]*M_PI); } else { tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vbridge[0],2)*M_PI); } } else { if (p.scale_buqd) { tau = 1.0/(2*p.Vnobridge[0]*M_PI); } else { tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vnobridge[0],2)*M_PI); } } fprintf(log, "\nThe timescale (tau) is %.9e a.u.\n", tau); } } //// CREATE DENSITY MATRIX if (! p.wavefunction) { // Create the initial density matrix dm = new realtype [2*p.NEQ2]; initializeArray(dm, 2*p.NEQ2, 0.0); #pragma omp parallel for for (int ii = 0; ii < p.NEQ; ii++) { // diagonal part dm[p.NEQ*ii + ii] = pow(wavefunction[ii],2) + pow(wavefunction[ii + p.NEQ],2); if (p.coherent) { // off-diagonal part for (int jj = 0; jj < ii; jj++) { // real part of \rho_{ii,jj} dm[p.NEQ*ii + jj] = wavefunction[ii]*wavefunction[jj] + wavefunction[ii+p.NEQ]*wavefunction[jj+p.NEQ]; // imaginary part of \rho_{ii,jj} dm[p.NEQ*ii + jj + p.NEQ2] = wavefunction[ii]*wavefunction[jj+p.NEQ] - wavefunction[jj]*wavefunction[ii+p.NEQ]; // real part of \rho_{jj,ii} dm[p.NEQ*jj + ii] = dm[p.NEQ*ii + jj]; // imaginary part of \rho_{jj,ii} dm[p.NEQ*jj + ii + p.NEQ2] = -1*dm[p.NEQ*ii + jj + p.NEQ*p.NEQ]; } } } // Create the array to store the density matrix in time dmt = new realtype [2*p.NEQ2*(p.numOutputSteps+1)]; initializeArray(dmt, 2*p.NEQ2*(p.numOutputSteps+1), 0.0); #ifdef DEBUG2 // print out density matrix std::cout << "\nDensity matrix without normalization:\n\n"; for (int ii = 0; ii < p.NEQ; ii++) { for (int jj = 0; jj < p.NEQ; jj++) { fprintf(stdout, "(%+.1e,%+.1e) ", dm[p.NEQ*ii + jj], dm[p.NEQ*ii + jj + p.NEQ2]); } fprintf(stdout, "\n"); } #endif // Normalize the DM so that populations add up to 1. // No normalization if RTA is on. if (!p.rta) { summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { // assume here that diagonal elements are all real summ += dm[p.NEQ*ii + ii]; } if ( summ == 0.0 ) { std::cerr << "\nFATAL ERROR [populations]: total population is 0!\n"; return -1; } if (summ != 1.0) { // the variable 'summ' is now a multiplicative normalization factor summ = 1.0/summ; for (int ii = 0; ii < 2*p.NEQ2; ii++) { dm[ii] *= summ; } } #ifdef DEBUG std::cout << "\nThe normalization factor for the density matrix is " << summ << "\n\n"; #endif } // Error checking for total population; recount population first summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { summ += dm[p.NEQ*ii + ii]; } if ( fabs(summ-1.0) > 1e-12 && (!p.rta)) { std::cerr << "\nWARNING [populations]: After normalization, total population is not 1, it is " << summ << "!\n"; } #ifdef DEBUG std::cout << "\nAfter normalization, the sum of the populations in the density matrix is " << summ << "\n\n"; #endif // Add initial DM to parameters. p.startDM.resize(2*p.NEQ2); memcpy(&(p.startDM[0]), &(dm[0]), 2*p.NEQ2*sizeof(double)); } // wavefunction else { // Create the array to store the wavefunction in time wfnt = new realtype [2*p.NEQ*(p.numOutputSteps+1)]; initializeArray(wfnt, 2*p.NEQ*(p.numOutputSteps+1), 0.0); // normalize summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2); } #ifdef DEBUG std::cout << "Before normalization, the total population is " << summ << std::endl; #endif summ = 1.0/sqrt(summ); for (int ii = 0; ii < 2*p.NEQ; ii++) { wavefunction[ii] *= summ; } // check total population summ = 0.0; for (int ii = 0; ii < p.NEQ; ii++) { summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2); } #ifdef DEBUG std::cout << "After normalization, the total population is " << summ << std::endl; #endif if (fabs(summ - 1.0) > 1e-12) { std::cerr << "WARNING: wavefunction not normalized! Total density is " << summ << std::endl; } // Add initial wavefunction to parameters. p.startWfn.resize(2*p.NEQ); memcpy(&(p.startWfn[0]), &(wavefunction[0]), 2*p.NEQ*sizeof(double)); } //// BUILD HAMILTONIAN // //TODO TODO #ifdef DEBUG fprintf(stderr, "Building Hamiltonian.\n"); #endif realtype * H = NULL; H = new realtype [p.NEQ2]; for (int ii = 0; ii < p.NEQ2; ii++) { H[ii] = 0.0; } buildHamiltonian(H, p.energies, V, &p); // add Hamiltonian to p p.H.resize(p.NEQ2); for (int ii = 0; ii < p.NEQ2; ii++) { p.H[ii] = H[ii]; } // create sparse version of H p.H_sp.resize(p.NEQ2); p.H_cols.resize(p.NEQ2); p.H_rowind.resize(p.NEQ2 + 1); int job [6] = {0, 0, 0, 2, p.NEQ2, 1}; int info = 0; mkl_ddnscsr(&job[0], &(p.NEQ), &(p.NEQ), &(p.H)[0], &(p.NEQ), &(p.H_sp)[0], &(p.H_cols)[0], &(p.H_rowind)[0], &info); //// SET UP CVODE VARIABLES #ifdef DEBUG std::cout << "\nCreating N_Vectors.\n"; if (p.wavefunction) { std::cout << "\nProblem size is " << 2*p.NEQ << " elements.\n"; } else { std::cout << "\nProblem size is " << 2*p.NEQ2 << " elements.\n"; } #endif // Creates N_Vector y with initial populations which will be used by CVode// if (p.wavefunction) { y = N_VMake_Serial(2*p.NEQ, wavefunction); } else { y = N_VMake_Serial(2*p.NEQ2, dm); } // put in t = 0 information if (! p.wavefunction) { updateDM(y, dmt, 0, &p); } else { updateWfn(y, wfnt, 0, &p); } // the vector yout has the same dimensions as y yout = N_VClone(y); #ifdef DEBUG realImaginary = fopen("real_imaginary.out", "w"); #endif // Make plot files makePlots(outs, &p); // only do propagation if not just making plots if (! p.justPlots) { // Make outputs independent of time propagation computeGeneralOutputs(outs, &p); // create CVode object // this is a stiff problem, I guess? #ifdef DEBUG std::cout << "\nCreating cvode_mem object.\n"; #endif cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); flag = CVodeSetUserData(cvode_mem, (void *) &p); #ifdef DEBUG std::cout << "\nInitializing CVode solver.\n"; #endif // initialize CVode solver // if (p.wavefunction) { //flag = CVodeInit(cvode_mem, &RHS_WFN, t0, y); flag = CVodeInit(cvode_mem, &RHS_WFN_SPARSE, t0, y); } else { if (p.kinetic) { flag = CVodeInit(cvode_mem, &RHS_DM_RELAX, t0, y); } else if (p.rta) { flag = CVodeInit(cvode_mem, &RHS_DM_RTA, t0, y); //flag = CVodeInit(cvode_mem, &RHS_DM_RTA_BLAS, t0, y); } else if (p.dephasing) { flag = CVodeInit(cvode_mem, &RHS_DM_dephasing, t0, y); } else { //flag = CVodeInit(cvode_mem, &RHS_DM, t0, y); flag = CVodeInit(cvode_mem, &RHS_DM_BLAS, t0, y); } } #ifdef DEBUG std::cout << "\nSpecifying integration tolerances.\n"; #endif // specify integration tolerances // flag = CVodeSStolerances(cvode_mem, p.reltol, p.abstol); #ifdef DEBUG std::cout << "\nAttaching linear solver module.\n"; #endif // attach linear solver module // if (p.wavefunction) { flag = CVDense(cvode_mem, 2*p.NEQ); } else { // Diagonal approximation to the Jacobian saves memory for large systems flag = CVDiag(cvode_mem); } //// CVODE TIME PROPAGATION #ifdef DEBUG std::cout << "\nAdvancing the solution in time.\n"; #endif for (int ii = 1; ii <= p.numsteps; ii++) { t = (p.tout*((double) ii)/((double) p.numsteps)); flag = CVode(cvode_mem, t, yout, &tret, 1); #ifdef DEBUGf std::cout << std::endl << "CVode flag at step " << ii << ": " << flag << std::endl; #endif if ((ii % (p.numsteps/p.numOutputSteps) == 0) || (ii == p.numsteps)) { // show progress in stdout if (p.progressStdout) { fprintf(stdout, "\r%-.2lf percent done", ((double)ii/((double)p.numsteps))*100); fflush(stdout); } // show progress in a file if (p.progressFile) { std::ofstream progressFile("progress.tmp"); progressFile << ((double)ii/((double)p.numsteps))*100 << " percent done." << std::endl; progressFile.close(); } if (p.wavefunction) { updateWfn(yout, wfnt, ii*p.numOutputSteps/p.numsteps, &p); } else { updateDM(yout, dmt, ii*p.numOutputSteps/p.numsteps, &p); } } } #ifdef DEBUG fclose(realImaginary); #endif //// MAKE FINAL OUTPUTS // finalize log file // time(&endRun); currentTime = localtime(&endRun); if (isOutput(outs, "log.out")) { fprintf(log, "Final status of 'flag' variable: %d\n\n", flag); fprintf(log, "Run ended at %s\n", asctime(currentTime)); fprintf(log, "Run took %.3g seconds.\n", difftime(endRun, startRun)); fclose(log); // note that the log file is opened after variable declaration } if (p.progressStdout) { printf("\nRun took %.3g seconds.\n", difftime(endRun, startRun)); } // Compute density outputs. #ifdef DEBUG std::cout << "Computing outputs..." << std::endl; #endif if (p.wavefunction) { computeWfnOutput(wfnt, outs, &p); } else { computeDMOutput(dmt, outs, &p); } #ifdef DEBUG std::cout << "done computing outputs" << std::endl; #endif // do analytical propagation if (p.analytical && (! p.bridge_on)) { computeAnalyticOutputs(outs, &p); } } //// CLEAN UP #ifdef DEBUG fprintf(stdout, "Deallocating N_Vectors.\n"); #endif // deallocate memory for N_Vectors // N_VDestroy_Serial(y); N_VDestroy_Serial(yout); #ifdef DEBUG fprintf(stdout, "Freeing CVode memory.\n"); #endif // free solver memory // CVodeFree(&cvode_mem); #ifdef DEBUG fprintf(stdout, "Freeing memory in main.\n"); #endif // delete all these guys delete [] tkprob; delete [] tlprob; delete [] tcprob; delete [] tbprob; for (int ii = 0; ii <= p.numOutputSteps; ii++) { delete [] allprob[ii]; } delete [] allprob; delete [] k_pops; delete [] c_pops; delete [] b_pops; delete [] l_pops; if (p.bridge_on) { delete [] Vbridge; } else { delete [] Vnobridge; } delete [] k_energies; delete [] c_energies; delete [] b_energies; delete [] l_energies; delete [] wavefunction; delete [] H; for (int ii = 0; ii < p.NEQ; ii++) { delete [] V[ii]; } delete [] V; if (p.wavefunction) { delete [] wfnt; } else { delete [] dm; delete [] dmt; } delete [] times; delete [] qd_est; delete [] qd_est_diag; std::cout << "whoo" << std::endl; return 0; }
void CVodesIntegrator::initialize(double t0, FuncEval& func) { m_neq = func.neq(); m_t0 = t0; if (m_y) { N_VDestroy_Serial(nv(m_y)); // free solution vector if already allocated } m_y = reinterpret_cast<void*>(N_VNew_Serial(m_neq)); // allocate solution vector for (int i=0; i<m_neq; i++) { NV_Ith_S(nv(m_y), i) = 0.0; } // check abs tolerance array size if (m_itol == CV_SV && m_nabs < m_neq) throw CVodesErr("not enough absolute tolerance values specified."); func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y))); if (m_cvode_mem) CVodeFree(&m_cvode_mem); /* * Specify the method and the iteration type: * Cantera Defaults: * CV_BDF - Use BDF methods * CV_NEWTON - use newton's method */ m_cvode_mem = CVodeCreate(m_method, m_iter); if (!m_cvode_mem) throw CVodesErr("CVodeCreate failed."); int flag = 0; #if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23) if (m_itol == CV_SV) { // vector atol flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, nv(m_abstol)); } else { // scalar atol flag = CVodeMalloc(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, &m_abstols); } if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeMalloc input argument."); } else throw CVodesErr("CVodeMalloc failed."); } #elif defined(SUNDIALS_VERSION_24) flag = CVodeInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y)); if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeInit input argument."); } else { throw CVodesErr("CVodeInit failed."); } } if (m_itol == CV_SV) { flag = CVodeSVtolerances(m_cvode_mem, m_reltol, nv(m_abstol)); } else { flag = CVodeSStolerances(m_cvode_mem, m_reltol, m_abstols); } if (flag != CV_SUCCESS) { if (flag == CV_MEM_FAIL) { throw CVodesErr("Memory allocation failed."); } else if (flag == CV_ILL_INPUT) { throw CVodesErr("Illegal value for CVodeInit input argument."); } else { throw CVodesErr("CVodeInit failed."); } } #else printf("unknown sundials verson\n"); exit(-1); #endif if (m_type == DENSE + NOJAC) { long int N = m_neq; CVDense(m_cvode_mem, N); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, PREC_NONE, 0); } else if (m_type == BAND + NOJAC) { long int N = m_neq; long int nu = m_mupper; long int nl = m_mlower; CVBand(m_cvode_mem, N, nu, nl); } else { throw CVodesErr("unsupported option"); } // pass a pointer to func in m_data m_fdata = new FuncData(&func, func.nparams()); //m_data = (void*)&func; #if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23) flag = CVodeSetFdata(m_cvode_mem, (void*)m_fdata); if (flag != CV_SUCCESS) { throw CVodesErr("CVodeSetFdata failed."); } #elif defined(SUNDIALS_VERSION_24) flag = CVodeSetUserData(m_cvode_mem, (void*)m_fdata); if (flag != CV_SUCCESS) { throw CVodesErr("CVodeSetUserData failed."); } #endif if (func.nparams() > 0) { sensInit(t0, func); flag = CVodeSetSensParams(m_cvode_mem, DATA_PTR(m_fdata->m_pars), NULL, NULL); } // set options if (m_maxord > 0) flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord); if (m_maxsteps > 0) flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); if (m_hmax > 0) flag = CVodeSetMaxStep(m_cvode_mem, m_hmax); }
int main(int narg, char **args) { realtype reltol, t, tout; N_Vector state, abstol; void *cvode_mem; int flag, flagr; int rootsfound[NRF]; int rootdir[] = {1,1,1,}; FILE *pout; pout = stdout; state = abstol = NULL; cvode_mem = NULL; state = N_VNew_Serial(NEQ); if (check_flag((void *)state, "N_VNew_Serial", 0)) return(1); abstol = N_VNew_Serial(NEQ); if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1); realtype a = 0.02; realtype b = 0.2; realtype c = -50; realtype d = 2; realtype I = 0; realtype v0 = -70; realtype p[] = {a, b, c, d, I, v0, }; realtype v = v0; realtype u = b * v0; NV_Ith_S(state, 0) = v0; NV_Ith_S(state, 1) = b * v0; reltol = RTOL; NV_Ith_S(abstol,0) = ATOL0; NV_Ith_S(abstol,1) = ATOL1; /* Allocations and initializations */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeInit(cvode_mem, dstate_dt, T0, state); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSetUserData(cvode_mem, p); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); flag = CVodeRootInit(cvode_mem, NRF, root_functions); if (check_flag(&flag, "CVodeRootInit", 1)) return(1); CVodeSetRootDirection(cvode_mem, rootdir); if (check_flag(&flag, "CVodeSetRootDirection", 1)) return(1); flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); printf(" \n Integrating izhikevich_burster \n\n"); printf("#t v, u, \n"); PrintOutput(pout, t, state); tout = DT; while(1) { flag = CVode(cvode_mem, tout, state, &t, CV_NORMAL); if(flag == CV_ROOT_RETURN) { /* Event detected */ flagr = CVodeGetRootInfo(cvode_mem, rootsfound); if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1); PrintRootInfo(t, state, rootsfound); if(rootsfound[0]){ //spike v = NV_Ith_S(state, 0); u = NV_Ith_S(state, 1); NV_Ith_S(state, 0) = c; NV_Ith_S(state, 1) = u + d; } if(rootsfound[1]){ //start_inj I = 5; p[0] = a; p[1] = b; p[2] = c; p[3] = d; p[4] = I; p[5] = v0; } if(rootsfound[2]){ //end_inj I = 0; p[0] = a; p[1] = b; p[2] = c; p[3] = d; p[4] = I; p[5] = v0; } /* Restart integration with event-corrected state */ flag = CVodeSetUserData(cvode_mem, p); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); CVodeReInit(cvode_mem, t, state); //PrintRootInfo(t, state, rootsfound); } else { PrintOutput(pout, t, state); if(check_flag(&flag, "CVode", 1)) break; if(flag == CV_SUCCESS) { tout += DT; } if (t >= T1) break; } } PrintFinalStats(cvode_mem); N_VDestroy_Serial(state); N_VDestroy_Serial(abstol); CVodeFree(&cvode_mem); fclose(pout); return(0); }
int jmi_ode_cvode_new(jmi_ode_cvode_t** integrator_ptr, jmi_ode_solver_t* solver) { jmi_ode_cvode_t* integrator; jmi_ode_problem_t* problem = solver -> ode_problem; int flag = 0; void* cvode_mem; jmi_real_t* y; jmi_real_t* atol_nv; int i; integrator = (jmi_ode_cvode_t*)calloc(1,sizeof(jmi_ode_cvode_t)); if(!integrator){ jmi_log_node(problem->log, logError, "Error", "Failed to allocate the internal CVODE struct."); return -1; } /* DEFAULT VALUES NEEDS TO BE IMPROVED*/ integrator->lmm = CV_BDF; integrator->iter = CV_NEWTON; /* integrator->rtol = 1e-4; */ integrator->rtol = solver->rel_tol; if (problem->n_real_x > 0) { integrator->atol = N_VNew_Serial(problem->n_real_x); } else { integrator->atol = N_VNew_Serial(1); } atol_nv = NV_DATA_S(integrator->atol); if (problem->n_real_x > 0) { for (i = 0; i < problem->n_real_x; i++) { atol_nv[i] = 0.01*integrator->rtol*problem->nominal[i]; } }else{ atol_nv[0] = 0.01*integrator->rtol*1.0; } cvode_mem = CVodeCreate(integrator->lmm,integrator->iter); if(!cvode_mem){ jmi_log_node(problem->log, logError, "Error", "Failed to allocate the CVODE struct."); return -1; } /* Get the default values for the time and states */ if (problem->n_real_x > 0) { integrator->y_work = N_VNew_Serial(problem->n_real_x); y = NV_DATA_S(integrator->y_work); memcpy (y, problem->states, problem->n_real_x*sizeof(jmi_real_t)); }else{ integrator->y_work = N_VNew_Serial(1); y = NV_DATA_S(integrator->y_work); y[0] = 0.0; } flag = CVodeInit(cvode_mem, cv_rhs, problem->time, integrator->y_work); if(flag != 0) { jmi_log_node(problem->log, logError, "Error", "Failed to initialize CVODE. Returned with <error_flag: %d>", flag); return -1; } flag = CVodeSVtolerances(cvode_mem, integrator->rtol, integrator->atol); if(flag!=0){ jmi_log_node(problem->log, logError, "Error", "Failed to specify the tolerances. Returned with <error_flag: %d>", flag); return -1; } if (problem->n_real_x > 0) { flag = CVDense(cvode_mem, problem->n_real_x); }else{ flag = CVDense(cvode_mem, 1); } if(flag!=0){ jmi_log_node(problem->log, logError, "Error", "Failed to specify the linear solver. Returned with <error_flag: %d>", flag); return -1; } flag = CVodeSetUserData(cvode_mem, (void*)solver); if(flag!=0){ jmi_log_node(problem->log, logError, "Error", "Failed to specify the user data. Returned with <error_flag: %d>", flag); return -1; } if (problem->n_sw > 0){ flag = CVodeRootInit(cvode_mem, problem->n_sw, cv_root); if(flag!=0){ jmi_log_node(problem->log, logError, "Error", "Failed to specify the event indicator function. Returned with <error_flag: %d>", flag); return -1; } } flag = CVodeSetErrHandlerFn(cvode_mem, cv_err, (void*)solver); if(flag!=0){ jmi_log_node(problem->log, logError, "Error", "Failed to specify the error handling function. Returned with <error_flag: %d>", flag); return -1; } integrator->cvode_mem = cvode_mem; *integrator_ptr = integrator; return 0; }
/* Main Function */ int main(int argc, char *argv[]) { char *filename = "shalehills"; /* Input file name prefix */ char *StateFile; /* Output file name string */ char *FluxFile; char *ETISFile; char *QFile; Model_Data mData; /* Model Data */ Control_Data cData; /* Solver Control Data */ N_Vector CV_Y; /* State Variables Vector */ M_Env machEnv; /* Machine Environments */ realtype ropt[OPT_SIZE]; /* Optional real type and integer type */ long int iopt[OPT_SIZE]; /* vecter for Message Passing to solver */ void *cvode_mem; /* Model Data Pointer */ int flag; /* flag to test return value */ FILE *res_state_file; /* Output file for States */ FILE *res_flux_file; /* Output file for Flux */ FILE *res_etis_file; /* Output file for ET and IS */ FILE *res_q_file; int N; /* Problem size */ int i; /* loop index */ realtype t; /* simulation time */ realtype NextPtr, StepSize; /* stress period & step size */ clock_t start, end_r, end_s; /* system clock at points */ realtype cputime_r, cputime_s; /* for duration in realtype */ /* allocate memory for model data structure */ mData = (Model_Data)malloc(sizeof *mData); start = clock(); /* get user specified file name in command line */ if(argc >= 2) { filename = (char *)malloc(strlen(argv[1])*sizeof(char)); strcpy(filename, argv[1]); } printf("\nBelt up! PIHM 1.0 is starting ... \n"); /* read in 7 input files with "filename" as prefix */ read_alloc(filename, mData, &cData); /* problem size */ N = 3*mData->NumEle + mData->NumRiv; /* initial machine environment variable */ machEnv = M_EnvInit_Serial(N); /* initial state variable depending on machine*/ CV_Y = N_VNew(N, machEnv); /* initialize mode data structure */ initialize(filename, mData, &cData, CV_Y); if(cData.Debug == 1) {PrintModelData(mData);} end_r = clock(); cputime_r = (end_r - start)/(realtype)CLOCKS_PER_SEC; printf("\nSolving ODE system ... \n"); /* initial control parameter for CVODE solver. Otherwise the default value by C could cause problems. */ for(i=0; i<OPT_SIZE; i++) { ropt[i] = 0.0; iopt[i] = 0; } /* set user specified control parameter */ ropt[H0] = cData.InitStep; ropt[HMAX] = cData.MaxStep; /* allocate memory for solver */ cvode_mem = CVodeMalloc(N, f, cData.StartTime, CV_Y, BDF, NEWTON, SS, &cData.reltol, &cData.abstol, mData, NULL, TRUE, iopt, ropt, machEnv); if(cvode_mem == NULL) {printf("CVodeMalloc failed. \n"); return(1);} if(cData.Solver == 1) { /* using dense direct solver */ flag = CVDense(cvode_mem, NULL, NULL); if(flag != SUCCESS) {printf("CVDense failed. \n"); return(1);} } else if(cData.Solver == 2) { /* using iterative solver */ flag = CVSpgmr(cvode_mem, NONE, cData.GSType, cData.MaxK, cData.delt, NULL, NULL, mData, NULL, NULL); if (flag != SUCCESS) {printf("CVSpgmr failed."); return(1);} } /*allocate and copy to get output file name */ StateFile = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(StateFile, filename); FluxFile = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(FluxFile, filename); ETISFile = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ETISFile, filename); QFile = (char *)malloc((strlen(filename)+2)*sizeof(char)); strcpy(QFile, filename); /* open output file */ if (cData.res_out == 1) {res_state_file = fopen(strcat(StateFile, ".res"), "w");} if (cData.flux_out == 1) {res_flux_file = fopen(strcat(FluxFile, ".flux"), "w");} if (cData.etis_out == 1) {res_etis_file = fopen(strcat(ETISFile, ".etis"), "w");} if (cData.q_out == 1) {res_q_file = fopen(strcat(QFile, ".q"), "w");} /* print header of output file */ if (cData.res_out == 1) {FPrintYheader(res_state_file, mData);} if (cData.etis_out == 1) {FPrintETISheader(res_etis_file, mData);} if (cData.q_out == 1) {FPrintETISheader(res_q_file, mData);} printf("\n"); /* set start time */ t = cData.StartTime; /* start solver in loops */ for(i=0; i<cData.NumSteps; i++) { /* prompt information in non-verbose mode */ if (cData.Verbose != 1) { printf(" Running: %-4.1f%% ... ", (100*(i+1)/((realtype) cData.NumSteps))); fflush(stdout); } /* inner loops to next output points with ET step size control */ while(t < cData.Tout[i+1]) { if (t + cData.ETStep >= cData.Tout[i+1]) { NextPtr = cData.Tout[i+1]; } else { NextPtr = t + cData.ETStep; } StepSize = NextPtr - t; /* calculate Interception Storage */ calIS(t, StepSize, mData); /* solving ODE system */ flag = CVode(cvode_mem, NextPtr, CV_Y, &t, NORMAL); /* calculate ET and adjust states variables*/ calET(t, StepSize, CV_Y, mData); } if(cData.Verbose == 1) {PrintVerbose(i, t, iopt, ropt);} /* uncomment it if user need it verbose mode */ /* if(cData.Verbose == 1) {PrintY(mData, CV_Y, t);} */ /* print out results to files at every output time */ if (cData.res_out == 1) {FPrintY(mData, CV_Y, t, res_state_file);} if (cData.flux_out == 1) {FPrintFlux(mData, t, res_flux_file);} if (cData.etis_out == 1) {FPrintETIS(mData, t, res_etis_file);} if (cData.q_out == 1) {FPrintQ(mData, t, res_q_file);} if (cData.Verbose != 1) {printf("\r");} if(flag != SUCCESS) {printf("CVode failed, flag = %d. \n", flag); return(flag);} /* clear buffer */ fflush(stdout); } /* free memory */ /* N_VFree(CV_Y); CVodeFree(cvode_mem); M_EnvFree_Serial(machEnv); */ /* capture time */ end_s = clock(); cputime_s = (end_s - end_r)/(realtype)CLOCKS_PER_SEC; /* print out simulation statistics */ PrintFarewell(cData, iopt, ropt, cputime_r, cputime_s); if (cData.res_out == 1) {FPrintFarewell(cData, res_state_file, iopt, ropt, cputime_r, cputime_s);} /* close output files */ if (cData.res_out == 1) {fclose(res_state_file);} if (cData.flux_out == 1) {fclose(res_flux_file);} if (cData.etis_out == 1) {fclose(res_etis_file);} if (cData.q_out == 1) {fclose(res_q_file);} free(mData); return 0; }
void Cvode::initialize() { _properties = dynamic_cast<ISystemProperties*>(_system); _continuous_system = dynamic_cast<IContinuous*>(_system); _event_system = dynamic_cast<IEvent*>(_system); _mixed_system = dynamic_cast<IMixedSystem*>(_system); _time_system = dynamic_cast<ITime*>(_system); IGlobalSettings* global_settings = dynamic_cast<ISolverSettings*>(_cvodesettings)->getGlobalSettings(); // Kennzeichnung, dass initialize()() (vor der Integration) aufgerufen wurde _idid = 5000; _tLastEvent = 0.0; _event_n = 0; SolverDefaultImplementation::initialize(); _dimSys = _continuous_system->getDimContinuousStates(); _dimZeroFunc = _event_system->getDimZeroFunc(); if (_dimSys == 0) _dimSys = 1; // introduce dummy state if (_dimSys <= 0) { _idid = -1; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } else { // Allocate state vectors, stages and temporary arrays if (_z) delete[] _z; if (_zInit) delete[] _zInit; if (_zWrite) delete[] _zWrite; if (_zeroSign) delete[] _zeroSign; if (_absTol) delete[] _absTol; if(_delta) delete [] _delta; if(_deltaInv) delete [] _deltaInv; if(_ysave) delete [] _ysave; _z = new double[_dimSys]; _zInit = new double[_dimSys]; _zWrite = new double[_dimSys]; _zeroSign = new int[_dimZeroFunc]; _absTol = new double[_dimSys]; _delta =new double[_dimSys]; _deltaInv =new double[_dimSys]; _ysave =new double[_dimSys]; memset(_z, 0, _dimSys * sizeof(double)); memset(_zInit, 0, _dimSys * sizeof(double)); memset(_ysave, 0, _dimSys * sizeof(double)); // Counter initialisieren _outStps = 0; if (_cvodesettings->getDenseOutput()) { // Ausgabeschrittweite _hOut = global_settings->gethOutput(); } // Allocate memory for the solver _cvodeMem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void*) _cvodeMem, "CVodeCreate", 0)) { _idid = -5; throw ModelicaSimulationError(SOLVER,/*_idid,_tCurrent,*/"Cvode::initialize()"); } // // Make Cvode ready for integration // // Set initial values for CVODE _continuous_system->evaluateAll(IContinuous::CONTINUOUS); _continuous_system->getContinuousStates(_zInit); memcpy(_z, _zInit, _dimSys * sizeof(double)); // Get nominal values _absTol[0] = 1.0; // in case of dummy state _continuous_system->getNominalStates(_absTol); for (int i = 0; i < _dimSys; i++) _absTol[i] *= dynamic_cast<ISolverSettings*>(_cvodesettings)->getATol(); _CV_y0 = N_VMake_Serial(_dimSys, _zInit); _CV_y = N_VMake_Serial(_dimSys, _z); _CV_yWrite = N_VMake_Serial(_dimSys, _zWrite); _CV_absTol = N_VMake_Serial(_dimSys, _absTol); if (check_flag((void*) _CV_y0, "N_VMake_Serial", 0)) { _idid = -5; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } // Initialize Cvode (Initial values are required) _idid = CVodeInit(_cvodeMem, CV_fCallback, _tCurrent, _CV_y0); if (_idid < 0) { _idid = -5; throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); } // Set Tolerances _idid = CVodeSVtolerances(_cvodeMem, dynamic_cast<ISolverSettings*>(_cvodesettings)->getRTol(), _CV_absTol); // RTOL and ATOL if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); // Set the pointer to user-defined data _idid = CVodeSetUserData(_cvodeMem, _data); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); _idid = CVodeSetInitStep(_cvodeMem, 1e-6); // INITIAL STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); _idid = CVodeSetMaxOrd(_cvodeMem, 5); // Max Order if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = CVodeSetMaxConvFails(_cvodeMem, 100); // Maximale Fehler im Konvergenztest if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = CVodeSetStabLimDet(_cvodeMem, TRUE); // Stability Detection if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVoder::initialize()"); _idid = CVodeSetMinStep(_cvodeMem, dynamic_cast<ISolverSettings*>(_cvodesettings)->getLowerLimit()); // MINIMUM STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxStep(_cvodeMem, global_settings->getEndTime() / 10.0); // MAXIMUM STEPSIZE if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxNonlinIters(_cvodeMem, 5); // Max number of iterations if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxErrTestFails(_cvodeMem, 100); if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); _idid = CVodeSetMaxNumSteps(_cvodeMem, 1e3); // Max Number of steps if (_idid < 0) throw ModelicaSimulationError(SOLVER,/*_idid,_tCurrent,*/"Cvode::initialize()"); // Initialize linear solver #ifdef USE_SUNDIALS_LAPACK _idid = CVLapackDense(_cvodeMem, _dimSys); #else _idid = CVDense(_cvodeMem, _dimSys); #endif if (_idid < 0) throw ModelicaSimulationError(SOLVER,"Cvode::initialize()"); // Use own jacobian matrix // Check if Colored Jacobians are worth to use #if SUNDIALS_MAJOR_VERSION >= 2 || (SUNDIALS_MAJOR_VERSION == 2 && SUNDIALS_MINOR_VERSION >= 4) _maxColors = _system->getAMaxColors(); if(_maxColors < _dimSys && _continuous_system->getDimContinuousStates() > 0) { // _idid = CVDlsSetDenseJacFn(_cvodeMem, &CV_JCallback); // initializeColoredJac(); } #endif if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::initialize()"); if (_dimZeroFunc) { _idid = CVodeRootInit(_cvodeMem, _dimZeroFunc, &CV_ZerofCallback); memset(_zeroSign, 0, _dimZeroFunc * sizeof(int)); _idid = CVodeSetRootDirection(_cvodeMem, _zeroSign); if (_idid < 0) throw ModelicaSimulationError(SOLVER,/*_idid,_tCurrent,*/"CVode::initialize()"); memset(_zeroSign, -1, _dimZeroFunc * sizeof(int)); memset(_zeroVal, -1, _dimZeroFunc * sizeof(int)); } _cvode_initialized = true; LOGGER_WRITE("Cvode: initialized",LC_SOLV,LL_DEBUG); } }
/* ** ======== ** main MEX ** ======== */ void mexFunction( int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[] ) { /* variables */ double * return_status; double * species_out; double * observables_out; double * parameters; double * species_init; double * timepoints; size_t n_timepoints; size_t i; size_t j; /* intermediate data vectors */ N_Vector expressions; N_Vector observables; N_Vector ratelaws; /* array to hold pointers to data vectors */ N_Vector temp_data[3]; /* CVODE specific variables */ realtype reltol; realtype abstol; realtype time; N_Vector species; void * cvode_mem; int flag; /* check number of input/output arguments */ if (nlhs != 3) { mexErrMsgTxt("syntax: [err_flag, species_out, obsv_out] = network_mex( timepoints, species_init, params )"); } if (nrhs != 3) { mexErrMsgTxt("syntax: [err_flag, species_out, obsv_out] = network_mex( timepoints, species_init, params )"); } /* make sure timepoints has correct dimensions */ if ( (mxGetM(prhs[0]) < 2) || (mxGetN(prhs[0]) != 1) ) { mexErrMsgTxt("TIMEPOINTS must be a column vector with 2 or more elements."); } /* make sure species_init has correct dimensions */ if ( (mxGetM(prhs[1]) != 1) || (mxGetN(prhs[1]) != __N_SPECIES__) ) { mexErrMsgTxt("SPECIES_INIT must be a row vector with 7 elements."); } /* make sure params has correct dimensions */ if ( (mxGetM(prhs[2]) != 1) || (mxGetN(prhs[2]) != __N_PARAMETERS__) ) { mexErrMsgTxt("PARAMS must be a column vector with 4 elements."); } /* get pointers to input arrays */ timepoints = mxGetPr(prhs[0]); species_init = mxGetPr(prhs[1]); parameters = mxGetPr(prhs[2]); /* get number of timepoints */ n_timepoints = mxGetM(prhs[0]); /* Create an mxArray for output trajectories */ plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL ); plhs[1] = mxCreateDoubleMatrix(n_timepoints, __N_SPECIES__, mxREAL); plhs[2] = mxCreateDoubleMatrix(n_timepoints, __N_OBSERVABLES__, mxREAL); /* get pointers to output arrays */ return_status = mxGetPr(plhs[0]); species_out = mxGetPr(plhs[1]); observables_out = mxGetPr(plhs[2]); /* initialize intermediate data vectors */ expressions = NULL; expressions = N_VNew_Serial(__N_EXPRESSIONS__); if (check_flag((void *)expressions, "N_VNew_Serial", 0)) { return_status[0] = 1; return; } observables = NULL; observables = N_VNew_Serial(__N_OBSERVABLES__); if (check_flag((void *)observables, "N_VNew_Serial", 0)) { N_VDestroy_Serial(expressions); return_status[0] = 1; return; } ratelaws = NULL; ratelaws = N_VNew_Serial(__N_RATELAWS__); if (check_flag((void *)ratelaws, "N_VNew_Serial", 0)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); return_status[0] = 1; return; } /* set up pointers to intermediate data vectors */ temp_data[0] = expressions; temp_data[1] = observables; temp_data[2] = ratelaws; /* calculate expressions (expressions are constant, so only do this once!) */ calc_expressions( expressions, parameters ); /* SOLVE model equations! */ species = NULL; cvode_mem = NULL; /* Set the scalar relative tolerance */ reltol = 1e-06; abstol = 1e-06; /* Create serial vector for Species */ species = N_VNew_Serial(__N_SPECIES__); if (check_flag((void *)species, "N_VNew_Serial", 0)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); return_status[0] = 1; return; } for ( i = 0; i < __N_SPECIES__; i++ ) { NV_Ith_S(species,i) = species_init[i]; } /* write initial species populations into species_out */ for ( i = 0; i < __N_SPECIES__; i++ ) { species_out[i*n_timepoints] = species_init[i]; } /* write initial observables populations into species_out */ calc_observables( observables, species, expressions ); for ( i = 0; i < __N_OBSERVABLES__; i++ ) { observables_out[i*n_timepoints] = NV_Ith_S(observables,i); } /* Call CVodeCreate to create the solver memory: * CV_ADAMS or CV_BDF is the linear multistep method * CV_FUNCTIONAL or CV_NEWTON is the nonlinear solver iteration * A pointer to the integrator problem memory is returned and stored in cvode_mem. */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } /* Call CVodeInit to initialize the integrator memory: * cvode_mem is the pointer to the integrator memory returned by CVodeCreate * rhs_func is the user's right hand side function in y'=f(t,y) * T0 is the initial time * y is the initial dependent variable vector */ flag = CVodeInit(cvode_mem, calc_species_deriv, timepoints[0], species); if (check_flag(&flag, "CVodeInit", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } /* Set scalar relative and absolute tolerances */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } /* pass params to rhs_func */ flag = CVodeSetUserData(cvode_mem, &temp_data); if (check_flag(&flag, "CVodeSetFdata", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } /* select linear solver */ flag = CVDense(cvode_mem, __N_SPECIES__); if (check_flag(&flag, "CVDense", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } flag = CVodeSetMaxNumSteps(cvode_mem, 2000); if (check_flag(&flag, "CVodeSetMaxNumSteps", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } flag = CVodeSetMaxErrTestFails(cvode_mem, 7); if (check_flag(&flag, "CVodeSetMaxErrTestFails", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } flag = CVodeSetMaxConvFails(cvode_mem, 10); if (check_flag(&flag, "CVodeSetMaxConvFails", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } flag = CVodeSetMaxStep(cvode_mem, 0.0); if (check_flag(&flag, "CVodeSetMaxStep", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } /* integrate to each timepoint */ for ( i=1; i < n_timepoints; i++ ) { flag = CVode(cvode_mem, timepoints[i], species, &time, CV_NORMAL); if (check_flag(&flag, "CVode", 1)) { N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); CVodeFree(&cvode_mem); return_status[0] = 1; return; } /* copy species output from nvector to matlab array */ for ( j = 0; j < __N_SPECIES__; j++ ) { species_out[j*n_timepoints + i] = NV_Ith_S(species,j); } /* copy observables output from nvector to matlab array */ calc_observables( observables, species, expressions ); for ( j = 0; j < __N_OBSERVABLES__; j++ ) { observables_out[j*n_timepoints + i] = NV_Ith_S(observables,j); } } /* Free vectors */ N_VDestroy_Serial(expressions); N_VDestroy_Serial(observables); N_VDestroy_Serial(ratelaws); N_VDestroy_Serial(species); /* Free integrator memory */ CVodeFree(&cvode_mem); return; }
void SundialsCvode::initialize() { int flag = 0; if (_initialized) { // Starting over with a new IC, but the same ODE flag = CVodeReInit(sundialsMem, t0, y.forSundials()); if (check_flag(&flag, "CVodeReInit", 1)) { throw DebugException("SundialsCvode::reInitialize: error in CVodeReInit"); } CVodeSetMaxNumSteps(sundialsMem, maxNumSteps); CVodeSetMinStep(sundialsMem, minStep); return; } // On the first call to initialize, need to allocate and set up // the Sundials solver, set tolerances and link the ODE functions sundialsMem = CVodeCreate(linearMultistepMethod, nonlinearSolverMethod); if (check_flag((void *)sundialsMem, "CVodeCreate", 0)) { throw DebugException("SundialsCvode::initialize: error in CVodeCreate"); } flag = CVodeInit(sundialsMem, f, t0, y.forSundials()); if (check_flag(&flag, "CVodeMalloc", 1)) { throw DebugException("SundialsCvode::initialize: error in CVodeMalloc"); } CVodeSVtolerances(sundialsMem, reltol, abstol.forSundials()); CVodeSetUserData(sundialsMem, theODE); CVodeSetMaxNumSteps(sundialsMem, maxNumSteps); CVodeSetMinStep(sundialsMem, minStep); if (findRoots) { rootsFound.resize(nRoots); // Call CVodeRootInit to specify the root function g with nRoots components flag = CVodeRootInit(sundialsMem, nRoots, g); if (check_flag(&flag, "CVodeRootInit", 1)) { throw DebugException("SundialsCvode::initialize: error in CVodeRootInit"); } } if (bandwidth_upper == -1 && bandwidth_lower == -1) { // Call CVDense to specify the CVDENSE dense linear solver flag = CVDense(sundialsMem, nEq); if (check_flag(&flag, "CVDense", 1)) { throw DebugException("SundialsCvode::initialize: error in CVDense"); } // Set the Jacobian routine to denseJac (user-supplied) flag = CVDlsSetDenseJacFn(sundialsMem, denseJac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) { throw DebugException("SundialsCvode::initialize: error in CVDlsSetDenseJacFn"); } } else { // Call CVDense to specify the CVBAND Banded linear solver flag = CVBand(sundialsMem, nEq, bandwidth_upper, bandwidth_lower); if (check_flag(&flag, "CVBand", 1)) { throw DebugException("SundialsCvode::initialize: error in CVBand"); } // Set the Jacobian routine to bandJac (user-supplied) flag = CVDlsSetBandJacFn(sundialsMem, bandJac); if (check_flag(&flag, "CVDlsSetBandJacFn", 1)) { throw DebugException("SundialsCvode::initialize: error in CVDlsSetBandJacFn"); } } _initialized = true; }
int main(int argc, char *argv[]) { void *cvode_mem; UserData data; realtype t, tout; N_Vector y; int iout, flag; realtype pbar[NS]; int is; N_Vector *yS; booleantype sensi, err_con; int sensi_meth; cvode_mem = NULL; data = NULL; y = NULL; yS = NULL; /* Process arguments */ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con); /* User data structure */ data = (UserData) malloc(sizeof *data); if (check_flag((void *)data, "malloc", 2)) return(1); data->p[0] = RCONST(0.04); data->p[1] = RCONST(1.0e4); data->p[2] = RCONST(3.0e7); /* Initial conditions */ y = N_VNew_Serial(NEQ); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); Ith(y,1) = Y1; Ith(y,2) = Y2; Ith(y,3) = Y3; /* Create CVODES object */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Allocate space for CVODES */ flag = CVodeMalloc(cvode_mem, f, T0, y, CV_WF, 0.0, NULL); if (check_flag(&flag, "CVodeMalloc", 1)) return(1); /* Use private function to compute error weights */ flag = CVodeSetEwtFn(cvode_mem, ewt, NULL); if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1); /* Attach user data */ flag = CVodeSetFdata(cvode_mem, data); if (check_flag(&flag, "CVodeSetFdata", 1)) return(1); /* Attach linear solver */ flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); flag = CVDenseSetJacFn(cvode_mem, Jac, data); if (check_flag(&flag, "CVDenseSetJacFn", 1)) return(1); printf("\n3-species chemical kinetics problem\n"); /* Sensitivity-related settings */ if (sensi) { pbar[0] = data->p[0]; pbar[1] = data->p[1]; pbar[2] = data->p[2]; yS = N_VNewVectorArray_Serial(NS, NEQ); if (check_flag((void *)yS, "N_VNewVectorArray_Serial", 0)) return(1); for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]); flag = CVodeSensMalloc(cvode_mem, NS, sensi_meth, yS); if(check_flag(&flag, "CVodeSensMalloc", 1)) return(1); flag = CVodeSetSensRhs1Fn(cvode_mem, fS); if (check_flag(&flag, "CVodeSetSensRhs1Fn", 1)) return(1); flag = CVodeSetSensErrCon(cvode_mem, err_con); if (check_flag(&flag, "CVodeSetSensFdata", 1)) return(1); flag = CVodeSetSensFdata(cvode_mem, data); if (check_flag(&flag, "CVodeSetSensFdata", 1)) return(1); flag = CVodeSetSensParams(cvode_mem, NULL, pbar, NULL); if (check_flag(&flag, "CVodeSetSensParams", 1)) return(1); printf("Sensitivity: YES "); if(sensi_meth == CV_SIMULTANEOUS) printf("( SIMULTANEOUS +"); else if(sensi_meth == CV_STAGGERED) printf("( STAGGERED +"); else printf("( STAGGERED1 +"); if(err_con) printf(" FULL ERROR CONTROL )"); else printf(" PARTIAL ERROR CONTROL )"); } else { printf("Sensitivity: NO "); } /* In loop over output points, call CVode, print results, test for error */ printf("\n\n"); printf("==================================================="); printf("============================\n"); printf(" T Q H NST y1"); printf(" y2 y3 \n"); printf("==================================================="); printf("============================\n"); for (iout=1, tout=T1; iout <= NOUT; iout++, tout *= TMULT) { flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL); if (check_flag(&flag, "CVode", 1)) break; PrintOutput(cvode_mem, t, y); if (sensi) { flag = CVodeGetSens(cvode_mem, t, yS); if (check_flag(&flag, "CVodeGetSens", 1)) break; PrintOutputS(yS); } printf("-------------------------------------------------"); printf("------------------------------\n"); } /* Print final statistics */ PrintFinalStats(cvode_mem, sensi); /* Free memory */ N_VDestroy_Serial(y); /* Free y vector */ if (sensi) { N_VDestroyVectorArray_Serial(yS, NS); /* Free yS vector */ } free(data); /* Free user data */ CVodeFree(cvode_mem); /* Free CVODES memory */ return(0); }
int main(int narg, char **args) { realtype reltol, t, tout; N_Vector state, abstol; void *cvode_mem; int flag, flagr; FILE *pout; if(!(pout = fopen("Locke2008_Circadian_Clock.dat", "w"))){ fprintf(stderr, "Cannot open file Locke2008_Circadian_Clock.dat. Are you trying to write to a non-existent directory? Exiting...\n"); exit(1); } state = abstol = NULL; cvode_mem = NULL; state = N_VNew_Serial(NEQ); if (check_flag((void *)state, "N_VNew_Serial", 0)) return(1); abstol = N_VNew_Serial(NEQ); if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1); realtype Kc = 4.8283; realtype v_4 = 1.0841; realtype v_6 = 4.6645; realtype vc = 6.7924; realtype v_1 = 6.8355; realtype v_2 = 8.4297; realtype K = 1.0; realtype v_8 = 3.5216; realtype L = 0.0; realtype n = 5.6645; realtype k3 = 0.1177; realtype K2 = 0.291; realtype K1 = 2.7266; realtype k7 = 0.2282; realtype K6 = 9.9849; realtype k5 = 0.3352; realtype K4 = 8.1343; realtype K8 = 7.4519; realtype init_X1 = 4.25; realtype tscale = 1.0; realtype init_Z1 = 2.25; realtype init_Z2 = 0.0; realtype init_V1 = 2.5; realtype init_V2 = 0.0; realtype init_X2 = 0.0; realtype compartment = 1.0; realtype init_Y1 = 3.25; realtype init_Y2 = 0.0; realtype p[] = {Kc, v_4, v_6, vc, v_1, v_2, K, v_8, L, n, k3, K2, K1, k7, K6, k5, K4, K8, init_X1, tscale, init_Z1, init_Z2, init_V1, init_V2, init_X2, compartment, init_Y1, init_Y2, }; realtype X1 = init_X1; realtype X2 = init_X2; realtype V1 = init_V1; realtype V2 = init_V2; realtype Y1 = init_Y1; realtype Y2 = init_Y2; realtype Z1 = init_Z1; realtype Z2 = init_Z2; NV_Ith_S(state, 0) = init_Y2; NV_Ith_S(state, 1) = init_V1; NV_Ith_S(state, 2) = init_Y1; NV_Ith_S(state, 3) = init_V2; NV_Ith_S(state, 4) = init_X2; NV_Ith_S(state, 5) = init_X1; NV_Ith_S(state, 6) = init_Z1; NV_Ith_S(state, 7) = init_Z2; reltol = RTOL; NV_Ith_S(abstol,0) = ATOL0; NV_Ith_S(abstol,1) = ATOL1; NV_Ith_S(abstol,2) = ATOL2; NV_Ith_S(abstol,3) = ATOL3; NV_Ith_S(abstol,4) = ATOL4; NV_Ith_S(abstol,5) = ATOL5; NV_Ith_S(abstol,6) = ATOL6; NV_Ith_S(abstol,7) = ATOL7; /* Allocations and initializations */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeInit(cvode_mem, dstate_dt, T0, state); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSetUserData(cvode_mem, p); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); printf(" \n Integrating Locke2008_Circadian_Clock_0 \n\n"); printf("#t Y2, V1, Y1, V2, X2, X1, Z1, Z2, \n"); PrintOutput(pout, t, state); tout = DT; while(1) { flag = CVode(cvode_mem, tout, state, &t, CV_NORMAL); { PrintOutput(pout, t, state); if(check_flag(&flag, "CVode", 1)) break; if(flag == CV_SUCCESS) { tout += DT; } if (t >= T1) break; } } PrintFinalStats(cvode_mem); N_VDestroy_Serial(state); N_VDestroy_Serial(abstol); CVodeFree(&cvode_mem); fclose(pout); return(0); }
int run_rate_state_sim(std::vector<std::vector<realtype> > &results, RSParams ¶ms) { realtype long_term_reltol, event_reltol, t, tout, tbase=0; N_Vector y, long_term_abstol, event_abstol; unsigned int i, n; int flag, err_code; void *long_term_cvode, *event_cvode, *current_cvode; // Create serial vector of length NEQ for I.C. and abstol y = N_VNew_Serial(params.num_eqs()*params.num_blocks()); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); long_term_abstol = N_VNew_Serial(params.num_eqs()*params.num_blocks()); if (check_flag((void *)long_term_abstol, "N_VNew_Serial", 0)) return(1); event_abstol = N_VNew_Serial(params.num_eqs()*params.num_blocks()); if (check_flag((void *)event_abstol, "N_VNew_Serial", 0)) return(1); // Initialize y for (i=0;i<params.num_blocks();++i) { NV_Ith_S(y,i*params.num_eqs()+EQ_X) = params.init_val(i, EQ_X); NV_Ith_S(y,i*params.num_eqs()+EQ_V) = params.init_val(i, EQ_V); NV_Ith_S(y,i*params.num_eqs()+EQ_H) = params.init_val(i, EQ_H); } /* Initialize interactions */ /*interaction = new realtype[NBLOCKS*NBLOCKS]; double int_level = 1e-2; double dropoff = 1.1; for (i=0;i<NBLOCKS;++i) { for (n=0;n<NBLOCKS;++n) { interaction[i*NBLOCKS+n] = (i==n?(1.0-int_level):int_level); } }*/ /* Set the scalar relative tolerance */ long_term_reltol = RCONST(1.0e-12); event_reltol = RCONST(1.0e-12); /* Set the vector absolute tolerance */ for (i=0;i<params.num_blocks();++i) { Xth(long_term_abstol,i) = RCONST(1.0e-12); Vth(long_term_abstol,i) = RCONST(1.0e-12); Hth(long_term_abstol,i) = RCONST(1.0e-12); Xth(event_abstol,i) = RCONST(1.0e-12); Vth(event_abstol,i) = RCONST(1.0e-12); Hth(event_abstol,i) = RCONST(1.0e-12); } /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ long_term_cvode = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)long_term_cvode, "CVodeCreate", 0)) return(1); event_cvode = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)event_cvode, "CVodeCreate", 0)) return(1); // Turn off error messages //CVodeSetErrFile(long_term_cvode, NULL); //CVodeSetErrFile(event_cvode, NULL); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in y'=f(t,y), the inital time T0, and * the initial dependent variable vector y. */ flag = CVodeInit(long_term_cvode, func, T0, y); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeInit(event_cvode, func, T0, y); if (check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSVtolerances to specify the scalar relative tolerance * and vector absolute tolerances */ flag = CVodeSVtolerances(long_term_cvode, long_term_reltol, long_term_abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); flag = CVodeSVtolerances(event_cvode, event_reltol, event_abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); /* Set the root finding function */ //flag = CVodeRootInit(long_term_cvode, params.num_blocks(), vel_switch_finder); //flag = CVodeRootInit(event_cvode, params.num_blocks(), vel_switch_finder); //if (check_flag(&flag, "CVodeRootInit", 1)) return(1); /* Call CVDense to specify the CVDENSE dense linear solver */ //flag = CVSpbcg(cvode_mem, PREC_NONE, 0); //if (check_flag(&flag, "CVSpbcg", 1)) return(1); //flag = CVSpgmr(cvode_mem, PREC_NONE, 0); //if (check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVDense(long_term_cvode, params.num_eqs()*params.num_blocks()); if (check_flag(&flag, "CVDense", 1)) return(1); flag = CVDense(event_cvode, params.num_eqs()*params.num_blocks()); if (check_flag(&flag, "CVDense", 1)) return(1); flag = CVodeSetUserData(long_term_cvode, ¶ms); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSetUserData(event_cvode, ¶ms); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); CVodeSetMaxNumSteps(long_term_cvode, 100000); CVodeSetMaxNumSteps(event_cvode, 100000); /* Set the Jacobian routine to Jac (user-supplied) */ flag = CVDlsSetDenseJacFn(long_term_cvode, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); flag = CVDlsSetDenseJacFn(event_cvode, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); /* In loop, call CVode, print results, and test for error. Break out of loop when NOUT preset output times have been reached. */ tout = T0+params.time_step(); err_code = 0; int mode = 0; int num_res_vals = params.num_eqs()*params.num_blocks(); while(t+tbase < params.end_time()) { switch (mode) { case 0: current_cvode = long_term_cvode; break; case 1: current_cvode = event_cvode; break; } flag = CVode(current_cvode, tout, y, &t, CV_NORMAL); record_results(results, y, t, tbase, num_res_vals); if (check_flag(&flag, "CVode", 1)) { err_code = flag; break; } if (flag == CV_ROOT_RETURN) { int flagr; int rootsfound[params.num_blocks()]; flagr = CVodeGetRootInfo(current_cvode, rootsfound); if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1); //mode = !mode; //std::cerr << rootsfound[0] << std::endl; } if (flag == CV_SUCCESS) tout += params.time_step(); if (t > 10) { t -= 10; tout -= 10; Xth(y,0) -= 10; tbase += 10; CVodeReInit(current_cvode, t, y); } } std::cerr << err_code << " X:" << Xth(y,0) << " V:" << Vth(y,0) << " H:" << Hth(y,0) << " F:" << F(0,Vth(y,0),Hth(y,0),params) << " dV:" << (Xth(y,0)-t-params.param(0, K_PARAM)*F(0,Vth(y,0),Hth(y,0),params))/params.param(0, R_PARAM) << " dH:" << -Hth(y,0)*Vth(y,0)*log(Hth(y,0)*Vth(y,0)) << std::endl; /* Print some final statistics */ //PrintFinalStats(cvode_mem); /* Free y and abstol vectors */ N_VDestroy_Serial(y); N_VDestroy_Serial(long_term_abstol); N_VDestroy_Serial(event_abstol); /* Free integrator memory */ CVodeFree(&long_term_cvode); return err_code; }
static int simulate_nmr_pulse(struct bloch_sim *bs) { N_Vector M = NULL; M = N_VNew_Serial(3 * bs->num_cells); if (check_flag((void *)M, "N_VNew_Serial", 0)) return(1); int i; /* Set initial (t=0) magnetization conditions */ for(i=0; i < bs->num_cells; ++i) { X(M,i) = 0.0; Y(M,i) = 0.0; Z(M,i) = bs->cell_frequencies[i] / bs->w_avg; } realtype reltol = RCONST(1.0e-14); realtype abstol = RCONST(1.0e-14); void *cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); int flag; //TODO: check if flag should be pointer; flag = CVodeInit(cvode_mem, bloch_equations, 0.0, M); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeSetUserData(cvode_mem, bs); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVDense(cvode_mem, 3 * bs->num_cells); if (check_flag(&flag, "CVDense", 1)) return(1); flag = CVDlsSetDenseJacFn(cvode_mem, bloch_jacobian); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); /////////////////////////// // PI/2 PULSE SIMULATION // /////////////////////////// bs->rf_on = 1; flag = CVodeSetStopTime(cvode_mem, bs->pi2_duration); if (check_flag(&flag, "CVodeSetStopTime", 1)) return 1; realtype time_reached; flag = CVode(cvode_mem, bs->pi2_duration, M, &time_reached, CV_NORMAL); if (flag != CV_SUCCESS) { printf("ERROR: Failed to simulate Pi/2 pulse\n"); } // {{{ PI2 PULSE DEBUG STATEMENTS if (DEBUG) { printf("\n"); printf("#####################################\n"); printf("### PI/2 PULSE SIMULATION DETAILS ###\n"); printf("#####################################\n"); printf("\n"); printf("TIME REACHED: %.15e\n", time_reached); printf("TIME REACHED - PI2_DURATION: %.15e\n", time_reached - bs->pi2_duration); printf("\n"); printf("MAGNETIZATION AT END OF PI/2 PULSE:\n"); for (i = 0; i<bs->num_cells; ++i) { printf("CELL %d: %.4e, %.4e, %.4e\n", i, X(M,i), Y(M,i), Z(M,i)); } } // }}} //////////////////// // FID SIMULATION // //////////////////// bs->rf_on = 0; if (DEBUG) { printf("##############################\n"); printf("### FID SIMULATION DETAILS ###\n"); printf("##############################\n"); } flag = CVodeReInit(cvode_mem, 0.0, M); if (check_flag(&flag, "CVodeReInit", 1)) return(1); time_reached = 0.0; flag = CVodeSetStopTime(cvode_mem, bs->fid_duration); if (check_flag(&flag, "CVodeSetStopTime", 1)) return 1; flag = CVodeRootInit(cvode_mem, 1, bloch_root); if (check_flag(&flag, "CVodeRootInit", 1)) return 1; realtype time_desired, M_FID_X; while (time_reached < bs->fid_duration) { time_desired = time_reached + bs->fid_sampling_interval; flag = CVode(cvode_mem, time_desired, M, &time_reached, CV_NORMAL); if (flag == CV_ROOT_RETURN) { bs->zero_crossings[bs->num_zero_crossings] = time_reached; M_FID_X = 0.0; for (i=0; i < bs->num_cells; i++) { M_FID_X += X(M,i) * cos(bs->w_avg * time_reached); M_FID_X += Y(M,i) * sin(bs->w_avg * time_reached); } bs->envelope[bs->num_zero_crossings] = M_FID_X / bs->num_cells; bs->num_zero_crossings++; } } bs->zero_crossings = (realtype*) realloc(bs->zero_crossings, sizeof(realtype) * bs->num_zero_crossings); bs->envelope = (realtype*) realloc(bs->envelope, sizeof(realtype) * bs->num_zero_crossings); if (!bs->zero_crossings || !bs->envelope) { printf("ERROR: reallocating zero crossing and/or envelope array memory failed!\n"); exit(1); } N_VDestroy_Serial(M); CVodeFree(&cvode_mem); return 0; }
void CvodeSolver::initialize(const double &pVoiStart, const int &pRatesStatesCount, double *pConstants, double *pRates, double *pStates, double *pAlgebraic, ComputeRatesFunction pComputeRates) { if (!mSolver) { // Retrieve some of the CVODE properties double maximumStep = MaximumStepDefaultValue; int maximumNumberOfSteps = MaximumNumberOfStepsDefaultValue; QString integrationMethod = IntegrationMethodDefaultValue; QString iterationType = IterationTypeDefaultValue; QString linearSolver = LinearSolverDefaultValue; QString preconditioner = PreconditionerDefaultValue; int upperHalfBandwidth = UpperHalfBandwidthDefaultValue; int lowerHalfBandwidth = LowerHalfBandwidthDefaultValue; double relativeTolerance = RelativeToleranceDefaultValue; double absoluteTolerance = AbsoluteToleranceDefaultValue; if (mProperties.contains(MaximumStepId)) { maximumStep = mProperties.value(MaximumStepId).toDouble(); } else { emit error(QObject::tr("the 'maximum step' property value could not be retrieved")); return; } if (mProperties.contains(MaximumNumberOfStepsId)) { maximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsId).toInt(); } else { emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved")); return; } if (mProperties.contains(IntegrationMethodId)) { integrationMethod = mProperties.value(IntegrationMethodId).toString(); } else { emit error(QObject::tr("the 'integration method' property value could not be retrieved")); return; } if (mProperties.contains(IterationTypeId)) { iterationType = mProperties.value(IterationTypeId).toString(); if (!iterationType.compare(NewtonIteration)) { // We are dealing with a Newton iteration, so retrieve and check // its linear solver if (mProperties.contains(LinearSolverId)) { linearSolver = mProperties.value(LinearSolverId).toString(); bool needUpperAndLowerHalfBandwidths = false; if ( !linearSolver.compare(DenseLinearSolver) || !linearSolver.compare(DiagonalLinearSolver)) { // We are dealing with a dense/diagonal linear solver, // so nothing more to do } else if (!linearSolver.compare(BandedLinearSolver)) { // We are dealing with a banded linear solver, so we // need both an upper and a lower half bandwidth needUpperAndLowerHalfBandwidths = true; } else { // We are dealing with a GMRES/Bi-CGStab/TFQMR linear // solver, so retrieve and check its preconditioner if (mProperties.contains(PreconditionerId)) { preconditioner = mProperties.value(PreconditionerId).toString(); } else { emit error(QObject::tr("the 'preconditioner' property value could not be retrieved")); return; } if (!preconditioner.compare(BandedPreconditioner)) { // We are dealing with a banded preconditioner, so // we need both an upper and a lower half bandwidth needUpperAndLowerHalfBandwidths = true; } } if (needUpperAndLowerHalfBandwidths) { if (mProperties.contains(UpperHalfBandwidthId)) { upperHalfBandwidth = mProperties.value(UpperHalfBandwidthId).toInt(); if ( (upperHalfBandwidth < 0) || (upperHalfBandwidth >= pRatesStatesCount)) { emit error(QObject::tr("the 'upper half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1)); return; } } else { emit error(QObject::tr("the 'upper half-bandwidth' property value could not be retrieved")); return; } if (mProperties.contains(LowerHalfBandwidthId)) { lowerHalfBandwidth = mProperties.value(LowerHalfBandwidthId).toInt(); if ( (lowerHalfBandwidth < 0) || (lowerHalfBandwidth >= pRatesStatesCount)) { emit error(QObject::tr("the 'lower half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1)); return; } } else { emit error(QObject::tr("the 'lower half-bandwidth' property value could not be retrieved")); return; } } } else { emit error(QObject::tr("the 'linear solver' property value could not be retrieved")); return; } } } else { emit error(QObject::tr("the 'iteration type' property value could not be retrieved")); return; } if (mProperties.contains(RelativeToleranceId)) { relativeTolerance = mProperties.value(RelativeToleranceId).toDouble(); if (relativeTolerance < 0) { emit error(QObject::tr("the 'relative tolerance' property must have a value greater than or equal to 0")); return; } } else { emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved")); return; } if (mProperties.contains(AbsoluteToleranceId)) { absoluteTolerance = mProperties.value(AbsoluteToleranceId).toDouble(); if (absoluteTolerance < 0) { emit error(QObject::tr("the 'absolute tolerance' property must have a value greater than or equal to 0")); return; } } else { emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved")); return; } if (mProperties.contains(InterpolateSolutionId)) { mInterpolateSolution = mProperties.value(InterpolateSolutionId).toBool(); } else { emit error(QObject::tr("the 'interpolate solution' property value could not be retrieved")); return; } // Initialise the ODE solver itself OpenCOR::Solver::OdeSolver::initialize(pVoiStart, pRatesStatesCount, pConstants, pRates, pStates, pAlgebraic, pComputeRates); // Create the states vector mStatesVector = N_VMake_Serial(pRatesStatesCount, pStates); // Create the CVODE solver bool newtonIteration = !iterationType.compare(NewtonIteration); mSolver = CVodeCreate(!integrationMethod.compare(BdfMethod)?CV_BDF:CV_ADAMS, newtonIteration?CV_NEWTON:CV_FUNCTIONAL); // Use our own error handler CVodeSetErrHandlerFn(mSolver, errorHandler, this); // Initialise the CVODE solver CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector); // Set some user data mUserData = new CvodeSolverUserData(pConstants, pAlgebraic, pComputeRates); CVodeSetUserData(mSolver, mUserData); // Set the maximum step CVodeSetMaxStep(mSolver, maximumStep); // Set the maximum number of steps CVodeSetMaxNumSteps(mSolver, maximumNumberOfSteps); // Set the linear solver, if needed if (newtonIteration) { if (!linearSolver.compare(DenseLinearSolver)) { CVDense(mSolver, pRatesStatesCount); } else if (!linearSolver.compare(BandedLinearSolver)) { CVBand(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth); } else if (!linearSolver.compare(DiagonalLinearSolver)) { CVDiag(mSolver); } else { // We are dealing with a GMRES/Bi-CGStab/TFQMR linear solver if (!preconditioner.compare(BandedPreconditioner)) { if (!linearSolver.compare(GmresLinearSolver)) CVSpgmr(mSolver, PREC_LEFT, 0); else if (!linearSolver.compare(BiCgStabLinearSolver)) CVSpbcg(mSolver, PREC_LEFT, 0); else CVSptfqmr(mSolver, PREC_LEFT, 0); CVBandPrecInit(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth); } else { if (!linearSolver.compare(GmresLinearSolver)) CVSpgmr(mSolver, PREC_NONE, 0); else if (!linearSolver.compare(BiCgStabLinearSolver)) CVSpbcg(mSolver, PREC_NONE, 0); else CVSptfqmr(mSolver, PREC_NONE, 0); } } } // Set the relative and absolute tolerances CVodeSStolerances(mSolver, relativeTolerance, absoluteTolerance); } else { // Reinitialise the CVODE object CVodeReInit(mSolver, pVoiStart, mStatesVector); } }
int do_integrate(float t_start, float t_stop, int n_points) { realtype reltol, t; N_Vector y, abstol; void *cvode_mem; int flag, flagr, iout; y = abstol = NULL; cvode_mem = NULL; /* Create serial vector of length NEQ for I.C. and abstol */ y = N_VNew_Serial(NEQ); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); abstol = N_VNew_Serial(NEQ); if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1); //Setup the initial state values: setup_initial_states(y); setup_tolerances(abstol); /* Set the scalar relative tolerance */ reltol = RTOL; /* Call CVodeCreate to create the solver memory and specify the * Backward Differentiation Formula and the use of a Newton iteration */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in y'=f(t,y), the inital time T0, and * the initial dependent variable vector y. */ flag = CVodeInit(cvode_mem, f, t_start, y); if (check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSVtolerances to specify the scalar relative tolerance * and vector absolute tolerances */ flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1); /* Call CVDense to specify the CVDENSE dense linear solver */ flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); /* Set the Jacobian routine to Jac (user-supplied) */ flag = CVDlsSetDenseJacFn(cvode_mem, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); /* In loop, call CVode, print results, and test for error.*/ printf(" \n3-species kinetics problem\n\n"); iout = 0; int i=0; for(i=1;i< n_points; i++) { float t_next = t_start + (t_stop-t_start)/n_points * i; printf("Advancing to: %f", t_next); flag = CVode(cvode_mem, t_next, y, &t, CV_NORMAL); loop_function(t,y); PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3)); //printf("MH: %d %f",iout,t_next); if (check_flag(&flag, "CVode", 1)) break; assert(flag==CV_SUCCESS); } /* Print some final statistics */ PrintFinalStats(cvode_mem); /* Free y and abstol vectors */ N_VDestroy_Serial(y); N_VDestroy_Serial(abstol); /* Free integrator memory */ CVodeFree(&cvode_mem); return(0); }
void CVodesIntegrator::reinitialize(double t0, FuncEval& func) { m_t0 = t0; //try { func.getInitialConditions(m_t0, m_neq, NV_DATA_S(nv(m_y))); //} //catch (CanteraError) { //showErrors(); //error("Teminating execution"); //} int result, flag; #if defined(SUNDIALS_VERSION_22) || defined(SUNDIALS_VERSION_23) if (m_itol == CV_SV) { result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, nv(m_abstol)); } else { result = CVodeReInit(m_cvode_mem, cvodes_rhs, m_t0, nv(m_y), m_itol, m_reltol, &m_abstols); } if (result != CV_SUCCESS) { throw CVodesErr("CVodeReInit failed. result = "+int2str(result)); } #elif defined(SUNDIALS_VERSION_24) result = CVodeReInit(m_cvode_mem, m_t0, nv(m_y)); if (result != CV_SUCCESS) { throw CVodesErr("CVodeReInit failed. result = "+int2str(result)); } #endif if (m_type == DENSE + NOJAC) { long int N = m_neq; CVDense(m_cvode_mem, N); } else if (m_type == DIAG) { CVDiag(m_cvode_mem); } else if (m_type == BAND + NOJAC) { long int N = m_neq; long int nu = m_mupper; long int nl = m_mlower; CVBand(m_cvode_mem, N, nu, nl); } else if (m_type == GMRES) { CVSpgmr(m_cvode_mem, PREC_NONE, 0); } else { throw CVodesErr("unsupported option"); } // set options if (m_maxord > 0) flag = CVodeSetMaxOrd(m_cvode_mem, m_maxord); if (m_maxsteps > 0) flag = CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); if (m_hmax > 0) flag = CVodeSetMaxStep(m_cvode_mem, m_hmax); }
int main(int argc, char *argv[]) { UserData data; void *cvode_mem; realtype reltolQ, abstolQ; N_Vector y, q; int steps; int indexB; realtype reltolB, abstolB, abstolQB; N_Vector yB, qB; realtype time; int flag, ncheck; long int nst, nstB; CVadjCheckPointRec *ckpnt; data = NULL; cvode_mem = NULL; ckpnt = NULL; y = yB = qB = NULL; /* Print problem description */ printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n"); printf("-------------------------------------------------\n\n"); printf("ODE: dy1/dt = -p1*y1 + p2*y2*y3\n"); printf(" dy2/dt = p1*y1 - p2*y2*y3 - p3*(y2)^2\n"); printf(" dy3/dt = p3*(y2)^2\n\n"); printf("Find dG/dp for\n"); printf(" G = int_t0^tB0 g(t,p,y) dt\n"); printf(" g(t,p,y) = y3\n\n\n"); /* User data structure */ data = (UserData) malloc(sizeof *data); if (check_flag((void *)data, "malloc", 2)) return(1); data->p[0] = RCONST(0.04); data->p[1] = RCONST(1.0e4); data->p[2] = RCONST(3.0e7); /* Initialize y */ y = N_VNew_Serial(NEQ); if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1); Ith(y,1) = RCONST(1.0); Ith(y,2) = ZERO; Ith(y,3) = ZERO; /* Initialize q */ q = N_VNew_Serial(1); if (check_flag((void *)q, "N_VNew_Serial", 0)) return(1); Ith(q,1) = ZERO; /* Set the scalar realtive and absolute tolerances reltolQ and abstolQ */ reltolQ = RTOL; abstolQ = ATOLq; /* Create and allocate CVODES memory for forward run */ printf("Create and allocate CVODES memory for forward runs\n"); cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeInit(cvode_mem, f, T0, y); if (check_flag(&flag, "CVodeInit", 1)) return(1); flag = CVodeWFtolerances(cvode_mem, ewt); if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1); flag = CVodeSetUserData(cvode_mem, data); if (check_flag(&flag, "CVodeSetUserData", 1)) return(1); flag = CVDense(cvode_mem, NEQ); if (check_flag(&flag, "CVDense", 1)) return(1); flag = CVDlsSetDenseJacFn(cvode_mem, Jac); if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1); flag = CVodeQuadInit(cvode_mem, fQ, q); if (check_flag(&flag, "CVodeQuadInit", 1)) return(1); flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ); if (check_flag(&flag, "CVodeQuadSStolerances", 1)) return(1); flag = CVodeSetQuadErrCon(cvode_mem, TRUE); if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1); /* Allocate global memory */ steps = STEPS; flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE); /* flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL); */ if (check_flag(&flag, "CVodeAdjInit", 1)) return(1); /* Perform forward run */ printf("Forward integration ... "); flag = CVodeF(cvode_mem, TOUT, y, &time, CV_NORMAL, &ncheck); if (check_flag(&flag, "CVodeF", 1)) return(1); flag = CVodeGetNumSteps(cvode_mem, &nst); if (check_flag(&flag, "CVodeGetNumSteps", 1)) return(1); printf("done ( nst = %ld )\n",nst); flag = CVodeGetQuad(cvode_mem, &time, q); if (check_flag(&flag, "CVodeGetQuad", 1)) return(1); printf("--------------------------------------------------------\n"); #if defined(SUNDIALS_EXTENDED_PRECISION) printf("G: %12.4Le \n",Ith(q,1)); #elif defined(SUNDIALS_DOUBLE_PRECISION) printf("G: %12.4le \n",Ith(q,1)); #else printf("G: %12.4e \n",Ith(q,1)); #endif printf("--------------------------------------------------------\n\n"); /* Test check point linked list (uncomment next block to print check point information) */ /* { int i; printf("\nList of Check Points (ncheck = %d)\n\n", ncheck); ckpnt = (CVadjCheckPointRec *) malloc ( (ncheck+1)*sizeof(CVadjCheckPointRec)); CVodeGetAdjCheckPointsInfo(cvode_mem, ckpnt); for (i=0;i<=ncheck;i++) { printf("Address: %p\n",ckpnt[i].my_addr); printf("Next: %p\n",ckpnt[i].next_addr); printf("Time interval: %le %le\n",ckpnt[i].t0, ckpnt[i].t1); printf("Step number: %ld\n",ckpnt[i].nstep); printf("Order: %d\n",ckpnt[i].order); printf("Step size: %le\n",ckpnt[i].step); printf("\n"); } } */ /* Initialize yB */ yB = N_VNew_Serial(NEQ); if (check_flag((void *)yB, "N_VNew_Serial", 0)) return(1); Ith(yB,1) = ZERO; Ith(yB,2) = ZERO; Ith(yB,3) = ZERO; /* Initialize qB */ qB = N_VNew_Serial(NP); if (check_flag((void *)qB, "N_VNew", 0)) return(1); Ith(qB,1) = ZERO; Ith(qB,2) = ZERO; Ith(qB,3) = ZERO; /* Set the scalar relative tolerance reltolB */ reltolB = RTOL; /* Set the scalar absolute tolerance abstolB */ abstolB = ATOLl; /* Set the scalar absolute tolerance abstolQB */ abstolQB = ATOLq; /* Create and allocate CVODES memory for backward run */ printf("Create and allocate CVODES memory for backward run\n"); flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB); if (check_flag(&flag, "CVodeCreateB", 1)) return(1); flag = CVodeInitB(cvode_mem, indexB, fB, TB1, yB); if (check_flag(&flag, "CVodeInitB", 1)) return(1); flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB); if (check_flag(&flag, "CVodeSStolerancesB", 1)) return(1); flag = CVodeSetUserDataB(cvode_mem, indexB, data); if (check_flag(&flag, "CVodeSetUserDataB", 1)) return(1); flag = CVDenseB(cvode_mem, indexB, NEQ); if (check_flag(&flag, "CVDenseB", 1)) return(1); flag = CVDlsSetDenseJacFnB(cvode_mem, indexB, JacB); if (check_flag(&flag, "CVDlsSetDenseJacFnB", 1)) return(1); flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB); if (check_flag(&flag, "CVodeQuadInitB", 1)) return(1); flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolB, abstolQB); if (check_flag(&flag, "CVodeQuadSStolerancesB", 1)) return(1); flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE); if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1); /* Backward Integration */ printf("Backward integration ... "); flag = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_flag(&flag, "CVodeB", 1)) return(1); CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB); printf("done ( nst = %ld )\n", nstB); flag = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_flag(&flag, "CVodeGetB", 1)) return(1); flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB); if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1); PrintOutput(TB1, yB, qB); /* Reinitialize backward phase (new tB0) */ Ith(yB,1) = ZERO; Ith(yB,2) = ZERO; Ith(yB,3) = ZERO; Ith(qB,1) = ZERO; Ith(qB,2) = ZERO; Ith(qB,3) = ZERO; printf("Re-initialize CVODES memory for backward run\n"); flag = CVodeReInitB(cvode_mem, indexB, TB2, yB); if (check_flag(&flag, "CVodeReInitB", 1)) return(1); flag = CVodeQuadReInitB(cvode_mem, indexB, qB); if (check_flag(&flag, "CVodeQuadReInitB", 1)) return(1); printf("Backward integration ... "); flag = CVodeB(cvode_mem, T0, CV_NORMAL); if (check_flag(&flag, "CVodeB", 1)) return(1); CVodeGetNumSteps(CVodeGetAdjCVodeBmem(cvode_mem, indexB), &nstB); printf("done ( nst = %ld )\n", nstB); flag = CVodeGetB(cvode_mem, indexB, &time, yB); if (check_flag(&flag, "CVodeGetB", 1)) return(1); flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB); if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1); PrintOutput(TB2, yB, qB); /* Free memory */ printf("Free memory\n\n"); CVodeFree(&cvode_mem); N_VDestroy_Serial(y); N_VDestroy_Serial(q); N_VDestroy_Serial(yB); N_VDestroy_Serial(qB); if (ckpnt != NULL) free(ckpnt); free(data); return(0); }