void CVodesIntegrator::setMaxSteps(int nmax) { m_maxsteps = nmax; if (m_cvode_mem) { CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps); } }
inline void cvodes_set_options(void* cvodes_mem, double rel_tol, double abs_tol, // NOLINTNEXTLINE(runtime/int) long int max_num_steps) { // forward CVode errors to noop error handler CVodeSetErrHandlerFn(cvodes_mem, cvodes_silent_err_handler, 0); // Initialize solver parameters cvodes_check_flag(CVodeSStolerances(cvodes_mem, rel_tol, abs_tol), "CVodeSStolerances"); cvodes_check_flag(CVodeSetMaxNumSteps(cvodes_mem, max_num_steps), "CVodeSetMaxNumSteps"); double init_step = 0; cvodes_check_flag(CVodeSetInitStep(cvodes_mem, init_step), "CVodeSetInitStep"); long int max_err_test_fails = 20; // NOLINT(runtime/int) cvodes_check_flag(CVodeSetMaxErrTestFails(cvodes_mem, max_err_test_fails), "CVodeSetMaxErrTestFails"); long int max_conv_fails = 50; // NOLINT(runtime/int) cvodes_check_flag(CVodeSetMaxConvFails(cvodes_mem, max_conv_fails), "CVodeSetMaxConvFails"); }
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 OpenSMOKE_CVODE_Sundials<T>::AnalyzeUserOptions() { /* TODO if (this->iSetMaximumNumberOfPrints_) iwork_[6] = this->maximumNumberOfPrints_; if (this->iSetMaximumOrder_) iwork_[8] = this->maximumOrder_; */ if (this->iSetMaximumNumberOfSteps_) { int flag = CVodeSetMaxNumSteps(cvode_mem_, this->maximumNumberOfSteps_); if (check_flag(&flag, std::string("CVodeSetMaxNumSteps"), 1)) exit(-1); } if (this->iSetMaximumStep_) { int flag = CVodeSetMaxStep(cvode_mem_, this->maximumStep_); if (check_flag(&flag, std::string("CVodeSetMaxStep"), 1)) exit(-1); } if (this->iSetMinimumStep_) { int flag = CVodeSetMinStep(cvode_mem_, this->minimumStep_); if (check_flag(&flag, std::string("CVodeSetMinStep"), 1)) exit(-1); } if (this->iSetFirstStep_) { int flag = CVodeSetInitStep(cvode_mem_, this->firstStep_); if (check_flag(&flag, std::string("CVodeSetInitStep"), 1)) exit(-1); } }
int CVodeSetMaxNumStepsB(void *cvadj_mem, long int mxstepsB) { CVadjMem ca_mem; void *cvode_mem; int flag; ca_mem = (CVadjMem) cvadj_mem; cvode_mem = (void *)ca_mem->cvb_mem; flag = CVodeSetMaxNumSteps(cvode_mem, mxstepsB); return(flag); }
int CVodeSetMaxNumStepsB(void *cvadj_mem, long int mxstepsB) { CVadjMem ca_mem; void *cvode_mem; int flag; if (cvadj_mem == NULL) { CVProcessError(NULL, CV_ADJMEM_NULL, "CVODEA", "CVodeSetMaxNumStepsB", MSGAM_NULL_CAMEM); return(CV_ADJMEM_NULL); } ca_mem = (CVadjMem) cvadj_mem; cvode_mem = (void *)ca_mem->cvb_mem; flag = CVodeSetMaxNumSteps(cvode_mem, mxstepsB); 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); } }
int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB) { CVodeMem cv_mem; CVadjMem ca_mem; CVodeBMem cvB_mem; void *cvodeB_mem; int flag; /* Check if cvode_mem exists */ if (cvode_mem == NULL) { cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_NO_MEM); return(CV_MEM_NULL); } cv_mem = (CVodeMem) cvode_mem; /* Was ASA initialized? */ if (cv_mem->cv_adjMallocDone == FALSE) { cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_NO_ADJ); return(CV_NO_ADJ); } ca_mem = cv_mem->cv_adj_mem; /* Check which */ if ( which >= nbckpbs ) { cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_BAD_WHICH); return(CV_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); flag = CVodeSetMaxNumSteps(cvodeB_mem, mxstepsB); return(flag); }
void FCV_SETIIN(char key_name[], long int *ival, int *ier) { if (!strncmp(key_name,"MAX_ORD",7)) *ier = CVodeSetMaxOrd(CV_cvodemem, (int) *ival); else if (!strncmp(key_name,"MAX_NSTEPS",10)) *ier = CVodeSetMaxNumSteps(CV_cvodemem, (long int) *ival); else if (!strncmp(key_name,"MAX_ERRFAIL",11)) *ier = CVodeSetMaxErrTestFails(CV_cvodemem, (int) *ival); else if (!strncmp(key_name,"MAX_NITERS",10)) *ier = CVodeSetMaxNonlinIters(CV_cvodemem, (int) *ival); else if (!strncmp(key_name,"MAX_CONVFAIL",12)) *ier = CVodeSetMaxConvFails(CV_cvodemem, (int) *ival); else if (!strncmp(key_name,"HNIL_WARNS",10)) *ier = CVodeSetMaxHnilWarns(CV_cvodemem, (int) *ival); else if (!strncmp(key_name,"STAB_LIM",8)) *ier = CVodeSetStabLimDet(CV_cvodemem, (booleantype) *ival); else { *ier = -99; fprintf(stderr, "FCVSETIIN: Unrecognized key.\n\n"); } }
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; }
/* * 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 main(int argc, char *argv[]) { void *cvode_mem; UserData data; realtype abstol, reltol, t, tout; N_Vector y; int iout, flag; realtype *pbar; int is, *plist; N_Vector *uS; booleantype sensi, err_con; int sensi_meth; pbar = NULL; plist = NULL; uS = NULL; y = NULL; data = NULL; cvode_mem = NULL; /* Process arguments */ ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con); /* Problem parameters */ data = AllocUserData(); if(check_flag((void *)data, "AllocUserData", 2)) return(1); InitUserData(data); /* Initial states */ y = N_VNew_Serial(NEQ); if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1); SetInitialProfiles(y, data->dx, data->dz); /* Tolerances */ abstol=ATOL; reltol=RTOL; /* Create CVODES object */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1); flag = CVodeSetFdata(cvode_mem, data); if(check_flag(&flag, "CVodeSetFdata", 1)) return(1); flag = CVodeSetMaxNumSteps(cvode_mem, 2000); if(check_flag(&flag, "CVodeSetMaxNumSteps", 1)) return(1); /* Allocate CVODES memory */ flag = CVodeMalloc(cvode_mem, f, T0, y, CV_SS, reltol, &abstol); if(check_flag(&flag, "CVodeMalloc", 1)) return(1); /* Attach CVSPGMR linear solver */ flag = CVSpgmr(cvode_mem, PREC_LEFT, 0); if(check_flag(&flag, "CVSpgmr", 1)) return(1); flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve, data); if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); printf("\n2-species diurnal advection-diffusion problem\n"); /* Forward sensitivity analysis */ if(sensi) { plist = (int *) malloc(NS * sizeof(int)); if(check_flag((void *)plist, "malloc", 2)) return(1); for(is=0; is<NS; is++) plist[is] = is; pbar = (realtype *) malloc(NS * sizeof(realtype)); if(check_flag((void *)pbar, "malloc", 2)) return(1); for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]]; uS = N_VCloneVectorArray_Serial(NS, y); if(check_flag((void *)uS, "N_VCloneVectorArray_Serial", 0)) return(1); for(is=0;is<NS;is++) N_VConst(ZERO,uS[is]); flag = CVodeSensMalloc(cvode_mem, NS, sensi_meth, uS); if(check_flag(&flag, "CVodeSensMalloc", 1)) return(1); flag = CVodeSetSensErrCon(cvode_mem, err_con); if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1); flag = CVodeSetSensRho(cvode_mem, ZERO); if(check_flag(&flag, "CVodeSetSensRho", 1)) return(1); flag = CVodeSetSensParams(cvode_mem, data->p, pbar, plist); 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("========================================================================\n"); printf(" T Q H NST Bottom left Top right \n"); printf("========================================================================\n"); for (iout=1, tout = TWOHR; iout <= NOUT; iout++, tout += TWOHR) { 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, uS); if(check_flag(&flag, "CVodeGetSens", 1)) break; PrintOutputS(uS); } printf("------------------------------------------------------------------------\n"); } /* Print final statistics */ PrintFinalStats(cvode_mem, sensi); /* Free memory */ N_VDestroy_Serial(y); if (sensi) { N_VDestroyVectorArray_Serial(uS, NS); free(pbar); free(plist); } FreeUserData(data); CVodeFree(&cvode_mem); return(0); }
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; }
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 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); }
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); }
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); }
/** \brief Call the ODE solver. * * \param neq The number of equations. * \param x_f A pointer to a vector of \c neq variables, giving the * initial state vector on entry and the final state vector on exit. * \param abstol_f A pointer to a vector of \c neq variables, giving * the absolute error tolerance for the corresponding state vector * component. * \param reltol_f The scalar relative tolerance. * \param t_initial_f The initial time (s). * \param t_final_f The final time (s). * \return A result code (0 is success). */ int condense_solver(int neq, double *x_f, double *abstol_f, double reltol_f, double t_initial_f, double t_final_f) { realtype reltol, t_initial, t_final, t, tout; N_Vector y, abstol; void *cvode_mem; CVodeMem cv_mem; int flag, i, pretype, maxl; realtype *y_data, *abstol_data; y = abstol = NULL; cvode_mem = NULL; y = N_VNew_Serial(neq); if (condense_check_flag((void *)y, "N_VNew_Serial", 0)) return PMC_CONDENSE_SOLVER_INIT_Y; abstol = N_VNew_Serial(neq); if (condense_check_flag((void *)abstol, "N_VNew_Serial", 0)) return PMC_CONDENSE_SOLVER_INIT_ABSTOL; y_data = NV_DATA_S(y); abstol_data = NV_DATA_S(abstol); for (i = 0; i < neq; i++) { y_data[i] = x_f[i]; abstol_data[i] = abstol_f[i]; } reltol = reltol_f; t_initial = t_initial_f; t_final = t_final_f; cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if (condense_check_flag((void *)cvode_mem, "CVodeCreate", 0)) return PMC_CONDENSE_SOLVER_INIT_CVODE_MEM; flag = CVodeInit(cvode_mem, condense_vf, t_initial, y); if (condense_check_flag(&flag, "CVodeInit", 1)) return PMC_CONDENSE_SOLVER_INIT_CVODE; flag = CVodeSVtolerances(cvode_mem, reltol, abstol); if (condense_check_flag(&flag, "CVodeSVtolerances", 1)) return PMC_CONDENSE_SOLVER_SVTOL; flag = CVodeSetMaxNumSteps(cvode_mem, 100000); if (condense_check_flag(&flag, "CVodeSetMaxNumSteps", 1)) return PMC_CONDENSE_SOLVER_SET_MAX_STEPS; /*******************************************************/ // dense solver //flag = CVDense(cvode_mem, neq); //if (condense_check_flag(&flag, "CVDense", 1)) return(1); /*******************************************************/ /*******************************************************/ // iterative solver //pretype = PREC_LEFT; //maxl = 0; //flag = CVSptfqmr(cvode_mem, pretype, maxl); //if (condense_check_flag(&flag, "CVSptfqmr", 1)) return(1); //flag = CVSpilsSetJacTimesVecFn(cvode_mem, condense_jtimes); //if (condense_check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1); //flag = CVSpilsSetPreconditioner(cvode_mem, NULL, condense_prec); //if (condense_check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1); /*******************************************************/ /*******************************************************/ // explicit solver cv_mem = (CVodeMem)cvode_mem; cv_mem->cv_linit = condense_solver_Init; cv_mem->cv_lsetup = condense_solver_Setup; cv_mem->cv_lsolve = condense_solver_Solve; cv_mem->cv_lfree = condense_solver_Free; /*******************************************************/ t = t_initial; flag = CVode(cvode_mem, t_final, y, &t, CV_NORMAL); if (condense_check_flag(&flag, "CVode", 1)) return PMC_CONDENSE_SOLVER_FAIL; for (i = 0; i < neq; i++) { x_f[i] = y_data[i]; } N_VDestroy_Serial(y); N_VDestroy_Serial(abstol); CVodeFree(&cvode_mem); return PMC_CONDENSE_SOLVER_SUCCESS; }
Bloch_McConnell_CV_Model::Bloch_McConnell_CV_Model () { m_world->solverSettings = new bmnvec; /* for (int i=0;i<OPT_SIZE;i++) {m_iopt[i]=0; m_ropt[i]=0.0;} m_iopt[MXSTEP] = 1000000; m_ropt[HMAX] = 10000.0;// the maximum stepsize in msec of the integrator*/ m_reltol = RTOL; //cvode2.5: // create cvode memory pointer; no mallocs done yet. // m_cvode_mem = CVodeCreate(CV_BDF,CV_NEWTON); m_cvode_mem = CVodeCreate(CV_ADAMS,CV_FUNCTIONAL); // cvode allocate memory. // do CVodeMalloc with dummy values y0,abstol once here; // -> CVodeReInit can later be used //HACK int pools = m_world->GetNoOfCompartments(); N_Vector y0,abstol; y0 = N_VNew_Serial(NEQ*pools); abstol = N_VNew_Serial(NEQ*pools); ((bmnvec*) (m_world->solverSettings))->abstol = N_VNew_Serial(pools*NEQ); for(int i = 0; i< pools*NEQ; i+=NEQ){ NV_Ith_S(y0,AMPL+i) = 0.0; NV_Ith_S(y0,PHASE+i) = 0.0; NV_Ith_S(y0,ZC+i) = 0.0; NV_Ith_S(abstol,AMPL+i) = ATOL1; NV_Ith_S(abstol,PHASE+i) = ATOL2; NV_Ith_S(abstol,ZC+i) = ATOL3; } #ifndef CVODE26 if(CVodeMalloc(m_cvode_mem,bloch,0,y0,CV_SV,m_reltol,abstol) != CV_SUCCESS ) { cout << "CVodeMalloc failed! aborting..." << endl;exit (-1); } if(CVodeSetFdata(m_cvode_mem, (void *) m_world) !=CV_SUCCESS) { cout << "CVode function data could not be set. Panic!" << endl;exit (-1); } #else if(CVodeInit(m_cvode_mem,bloch,0,y0) != CV_SUCCESS ) { cout << "CVodeInit failed! aborting..." << endl;exit (-1); } if(CVodeSVtolerances(m_cvode_mem, m_reltol, abstol)!= CV_SUCCESS){ cout << "CVodeSVtolerances failed! aborting..." << endl;exit (-1); } if(CVodeSetUserData(m_cvode_mem, (void *) m_world) !=CV_SUCCESS) { cout << "CVode function data could not be set. Panic!" << endl;exit (-1); } #endif /* int flag; int blub = (3*pools); flag = CVDense(m_cvode_mem, blub); if (flag == CVDENSE_SUCCESS) cout<< "great" <<endl; else cout<< "bad" <<endl; */ N_VDestroy_Serial(y0); N_VDestroy_Serial(abstol); /*if(CVodeSetFdata(m_cvode_mem, (void *) m_world) !=CV_SUCCESS) { cout << "CVode function data could not be set. Panic!" << endl; exit (-1); } // set CVODE initial step size // CVodeSetInitStep(m_cvode_mem, 1e-4); // set CVODE maximum step size CVodeSetMaxErrTestFails(m_cvode_mem, 10); // set CVODE minimum step size CVodeSetMinStep(m_cvode_mem, 1e-15); */ CVodeSetMaxNumSteps(m_cvode_mem, 10000000); // maximum number of warnings t+h = t (if number negative -> no warnings are issued ) CVodeSetMaxHnilWarns(m_cvode_mem,2); }
void FCV_REINIT(realtype *t0, realtype *y0, int *iatol, realtype *rtol, realtype *atol, int *optin, long int *iopt, realtype *ropt, int *ier) { int itol; void *atolptr; atolptr = NULL; N_VSetArrayPointer(y0, F2C_vec); switch (*iatol) { case 1: itol = CV_SS; atolptr = (void *) atol; break; case 2: F2C_atolvec = N_VClone(F2C_vec); data_F2C_atolvec = N_VGetArrayPointer(F2C_atolvec); N_VSetArrayPointer(atol, F2C_atolvec); itol = CV_SV; atolptr = (void *) F2C_atolvec; break; case 3: itol = CV_WF; } /* Call CVodeSet* and CVReInit to re-initialize CVODE: CVf is the user's right-hand side function in y'=f(t,y) t0 is the initial time F2C_vec is the initial dependent variable vector itol specifies tolerance type rtol is the scalar relative tolerance atolptr is the absolute tolerance pointer (to scalar or vector or function) */ if (*optin == 1) { CV_optin = TRUE; if (iopt[0] > 0) CVodeSetMaxOrd(CV_cvodemem, (int)iopt[0]); if (iopt[1] > 0) CVodeSetMaxNumSteps(CV_cvodemem, iopt[1]); if (iopt[2] > 0) CVodeSetMaxHnilWarns(CV_cvodemem, (int)iopt[2]); if (iopt[13] > 0) CVodeSetStabLimDet(CV_cvodemem, TRUE); if (iopt[21] > 0) CVodeSetMaxErrTestFails(CV_cvodemem, (int)iopt[21]); if (iopt[22] > 0) CVodeSetMaxNonlinIters(CV_cvodemem, (int)iopt[22]); if (iopt[23] > 0) CVodeSetMaxConvFails(CV_cvodemem, (int)iopt[23]); if (ropt[0] != ZERO) CVodeSetInitStep(CV_cvodemem, ropt[0]); if (ropt[1] > ZERO) CVodeSetMaxStep(CV_cvodemem, ropt[1]); if (ropt[2] > ZERO) CVodeSetMinStep(CV_cvodemem, ropt[2]); if (ropt[7] != ZERO) CVodeSetStopTime(CV_cvodemem, ropt[7]); if (ropt[8] > ZERO) CVodeSetNonlinConvCoef(CV_cvodemem, ropt[8]); } else { CV_optin = FALSE; } *ier = CVodeReInit(CV_cvodemem, FCVf, *t0, F2C_vec, itol, *rtol, atolptr); /* reset data pointer into F2C_vec */ N_VSetArrayPointer(data_F2C_vec, F2C_vec); /* destroy F2C_atolvec if allocated */ if (F2C_atolvec != NULL) { N_VSetArrayPointer(data_F2C_atolvec, F2C_atolvec); N_VDestroy(F2C_atolvec); } if (*ier != CV_SUCCESS) { *ier = -1; return; } CV_iopt = iopt; CV_ropt = ropt; return; }
PetscErrorCode TSSetUp_Sundials(TS ts) { TS_Sundials *cvode = (TS_Sundials*)ts->data; PetscErrorCode ierr; PetscInt glosize,locsize,i,flag; PetscScalar *y_data,*parray; void *mem; PC pc; PCType pctype; PetscBool pcnone; PetscFunctionBegin; /* get the vector size */ ierr = VecGetSize(ts->vec_sol,&glosize);CHKERRQ(ierr); ierr = VecGetLocalSize(ts->vec_sol,&locsize);CHKERRQ(ierr); /* allocate the memory for N_Vec y */ cvode->y = N_VNew_Parallel(cvode->comm_sundials,locsize,glosize); if (!cvode->y) SETERRQ(PETSC_COMM_SELF,1,"cvode->y is not allocated"); /* initialize N_Vec y: copy ts->vec_sol to cvode->y */ ierr = VecGetArray(ts->vec_sol,&parray);CHKERRQ(ierr); y_data = (PetscScalar*) N_VGetArrayPointer(cvode->y); for (i = 0; i < locsize; i++) y_data[i] = parray[i]; ierr = VecRestoreArray(ts->vec_sol,NULL);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->update);CHKERRQ(ierr); ierr = VecDuplicate(ts->vec_sol,&cvode->ydot);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->update);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->ydot);CHKERRQ(ierr); /* Create work vectors for the TSPSolve_Sundials() routine. Note these are allocated with zero space arrays because the actual array space is provided by Sundials and set using VecPlaceArray(). */ ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w1);CHKERRQ(ierr); ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)ts),1,locsize,PETSC_DECIDE,0,&cvode->w2);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w1);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)cvode->w2);CHKERRQ(ierr); /* Call CVodeCreate to create the solver memory and the use of a Newton iteration */ mem = CVodeCreate(cvode->cvode_type, CV_NEWTON); if (!mem) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"CVodeCreate() fails"); cvode->mem = mem; /* Set the pointer to user-defined data */ flag = CVodeSetUserData(mem, ts); if (flag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSetUserData() fails"); /* Sundials may choose to use a smaller initial step, but will never use a larger step. */ flag = CVodeSetInitStep(mem,(realtype)ts->time_step); if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetInitStep() failed"); if (cvode->mindt > 0) { flag = CVodeSetMinStep(mem,(realtype)cvode->mindt); if (flag) { if (flag == CV_MEM_NULL) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, cvode_mem pointer is NULL"); else if (flag == CV_ILL_INPUT) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed, hmin is nonpositive or it exceeds the maximum allowable step size"); else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMinStep() failed"); } } if (cvode->maxdt > 0) { flag = CVodeSetMaxStep(mem,(realtype)cvode->maxdt); if (flag) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_LIB,"CVodeSetMaxStep() failed"); } /* Call CVodeInit to initialize the integrator memory and specify the * user's right hand side function in u'=f(t,u), the inital time T0, and * the initial dependent variable vector cvode->y */ flag = CVodeInit(mem,TSFunction_Sundials,ts->ptime,cvode->y); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeInit() fails, flag %d",flag); /* specifies scalar relative and absolute tolerances */ flag = CVodeSStolerances(mem,cvode->reltol,cvode->abstol); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVodeSStolerances() fails, flag %d",flag); /* Specify max num of steps to be taken by cvode in its attempt to reach the next output time */ flag = CVodeSetMaxNumSteps(mem,ts->max_steps); /* call CVSpgmr to use GMRES as the linear solver. */ /* setup the ode integrator with the given preconditioner */ ierr = TSSundialsGetPC(ts,&pc);CHKERRQ(ierr); ierr = PCGetType(pc,&pctype);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)pc,PCNONE,&pcnone);CHKERRQ(ierr); if (pcnone) { flag = CVSpgmr(mem,PREC_NONE,0); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); } else { flag = CVSpgmr(mem,PREC_LEFT,cvode->maxl); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmr() fails, flag %d",flag); /* Set preconditioner and solve routines Precond and PSolve, and the pointer to the user-defined block data */ flag = CVSpilsSetPreconditioner(mem,TSPrecond_Sundials,TSPSolve_Sundials); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpilsSetPreconditioner() fails, flag %d", flag); } flag = CVSpilsSetGSType(mem, MODIFIED_GS); if (flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CVSpgmrSetGSType() fails, flag %d",flag); PetscFunctionReturn(0); }
int Solver::init(rhsfunc f, int argc, char **argv, bool restarting, int nout, real tstep) { #ifdef CHECK int msg_point = msg_stack.push("Initialising CVODE solver"); #endif /// Call the generic initialisation first if(GenericSolver::init(f, argc, argv, restarting, nout, tstep)) return 1; // Save nout and tstep for use in run NOUT = nout; TIMESTEP = tstep; output.write("Initialising SUNDIALS' CVODE solver\n"); // Set the rhs solver function func = f; // Calculate number of variables (in generic_solver) int local_N = getLocalN(); // Get total problem size int neq; if(MPI_Allreduce(&local_N, &neq, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD)) { output.write("\tERROR: MPI_Allreduce failed!\n"); return 1; } output.write("\t3d fields = %d, 2d fields = %d neq=%d, local_N=%d\n", n3Dvars(), n2Dvars(), neq, local_N); // Allocate memory if((uvec = N_VNew_Parallel(MPI_COMM_WORLD, local_N, neq)) == NULL) bout_error("ERROR: SUNDIALS memory allocation failed\n"); // Put the variables into uvec if(save_vars(NV_DATA_P(uvec))) bout_error("\tERROR: Initial variable value not set\n"); /// Get options real abstol, reltol; int maxl; int mudq, mldq; int mukeep, mlkeep; bool use_precon, use_jacobian; real max_timestep; bool adams_moulton, func_iter; // Time-integration method options.setSection("solver"); options.get("mudq", mudq, n3Dvars()*(MXSUB+2)); options.get("mldq", mldq, n3Dvars()*(MXSUB+2)); options.get("mukeep", mukeep, n3Dvars()+n2Dvars()); options.get("mlkeep", mlkeep, n3Dvars()+n2Dvars()); options.get("ATOL", abstol, 1.0e-12); options.get("RTOL", reltol, 1.0e-5); options.get("maxl", maxl, 5); options.get("use_precon", use_precon, false); options.get("use_jacobian", use_jacobian, false); options.get("max_timestep", max_timestep, -1.); int mxsteps; // Maximum number of steps to take between outputs options.get("pvode_mxstep", mxsteps, 500); options.get("adams_moulton", adams_moulton, false); int lmm = CV_BDF; if(adams_moulton) { // By default use functional iteration for Adams-Moulton lmm = CV_ADAMS; output.write("\tUsing Adams-Moulton implicit multistep method\n"); options.get("func_iter", func_iter, true); }else { output.write("\tUsing BDF method\n"); // Use Newton iteration for BDF options.get("func_iter", func_iter, false); } int iter = CV_NEWTON; if(func_iter) iter = CV_FUNCTIONAL; // Call CVodeCreate if((cvode_mem = CVodeCreate(lmm, iter)) == NULL) bout_error("ERROR: CVodeCreate failed\n"); if( CVodeSetUserData(cvode_mem, this) < 0 ) // For callbacks, need pointer to solver object bout_error("ERROR: CVodeSetUserData failed\n"); if( CVodeInit(cvode_mem, cvode_rhs, simtime, uvec) < 0 ) bout_error("ERROR: CVodeInit failed\n"); if( CVodeSStolerances(cvode_mem, reltol, abstol) < 0 ) bout_error("ERROR: CVodeSStolerances failed\n"); CVodeSetMaxNumSteps(cvode_mem, mxsteps); if(max_timestep > 0.0) { // Setting a maximum timestep CVodeSetMaxStep(cvode_mem, max_timestep); } /// Newton method can include Preconditioners and Jacobian function if(!func_iter) { output.write("\tUsing Newton iteration\n"); /// Set Preconditioner if(use_precon) { if( CVSpgmr(cvode_mem, PREC_LEFT, maxl) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpgmr failed\n"); if(prefunc == NULL) { output.write("\tUsing BBD preconditioner\n"); if( CVBBDPrecInit(cvode_mem, local_N, mudq, mldq, mukeep, mlkeep, ZERO, cvode_bbd_rhs, NULL) ) bout_error("ERROR: CVBBDPrecInit failed\n"); }else { output.write("\tUsing user-supplied preconditioner\n"); if( CVSpilsSetPreconditioner(cvode_mem, NULL, cvode_pre) ) bout_error("ERROR: CVSpilsSetPreconditioner failed\n"); } }else { // Not using preconditioning output.write("\tNo preconditioning\n"); if( CVSpgmr(cvode_mem, PREC_NONE, maxl) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpgmr failed\n"); } /// Set Jacobian-vector multiplication function if((use_jacobian) && (jacfunc != NULL)) { output.write("\tUsing user-supplied Jacobian function\n"); if( CVSpilsSetJacTimesVecFn(cvode_mem, cvode_jac) != CVSPILS_SUCCESS ) bout_error("ERROR: CVSpilsSetJacTimesVecFn failed\n"); }else output.write("\tUsing difference quotient approximation for Jacobian\n"); }else { output.write("\tUsing Functional iteration\n"); } #ifdef CHECK msg_stack.pop(msg_point); #endif 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); } }
void FCV_MALLOC(realtype *t0, realtype *y0, int *meth, int *itmeth, int *iatol, realtype *rtol, realtype *atol, int *optin, long int *iopt, realtype *ropt, int *ier) { int lmm, iter, itol; void *atolptr; atolptr = NULL; if(F2C_vec->ops->nvgetarraypointer == NULL || F2C_vec->ops->nvsetarraypointer == NULL) { *ier = -1; printf("A required vector operation is not implemented.\n\n"); return; } /* Save the data array in F2C_vec into data_F2C_vec and then overwrite it with y0 */ data_F2C_vec = N_VGetArrayPointer(F2C_vec); N_VSetArrayPointer(y0, F2C_vec); lmm = (*meth == 1) ? CV_ADAMS : CV_BDF; iter = (*itmeth == 1) ? CV_FUNCTIONAL : CV_NEWTON; switch (*iatol) { case 1: F2C_atolvec = NULL; itol = CV_SS; atolptr = (void *) atol; break; case 2: F2C_atolvec = N_VClone(F2C_vec); data_F2C_atolvec = N_VGetArrayPointer(F2C_atolvec); N_VSetArrayPointer(atol, F2C_atolvec); itol = CV_SV; atolptr = (void *) F2C_atolvec; break; case 3: F2C_atolvec = NULL; itol = CV_WF; break; } /* Call CVodeCreate, CVodeSet*, and CVodeMalloc to initialize CVODE: lmm is the method specifier iter is the iteration method specifier CVf is the user's right-hand side function in y'=f(t,y) *t0 is the initial time F2C_vec is the initial dependent variable vector itol specifies tolerance type rtol is the scalar relative tolerance atolptr is the absolute tolerance pointer (to scalar or vector or function) A pointer to CVODE problem memory is createded and stored in CV_cvodemem. */ *ier = 0; CV_cvodemem = CVodeCreate(lmm, iter); if (CV_cvodemem == NULL) { *ier = -1; return; } if (*optin == 1) { CV_optin = TRUE; if (iopt[0] > 0) CVodeSetMaxOrd(CV_cvodemem, (int)iopt[0]); if (iopt[1] > 0) CVodeSetMaxNumSteps(CV_cvodemem, iopt[1]); if (iopt[2] > 0) CVodeSetMaxHnilWarns(CV_cvodemem, (int)iopt[2]); if (iopt[13] > 0) CVodeSetStabLimDet(CV_cvodemem, TRUE); if (iopt[21] > 0) CVodeSetMaxErrTestFails(CV_cvodemem, (int)iopt[21]); if (iopt[22] > 0) CVodeSetMaxNonlinIters(CV_cvodemem, (int)iopt[22]); if (iopt[23] > 0) CVodeSetMaxConvFails(CV_cvodemem, (int)iopt[23]); if (ropt[0] != ZERO) CVodeSetInitStep(CV_cvodemem, ropt[0]); if (ropt[1] > ZERO) CVodeSetMaxStep(CV_cvodemem, ropt[1]); if (ropt[2] > ZERO) CVodeSetMinStep(CV_cvodemem, ropt[2]); if (ropt[7] != ZERO) CVodeSetStopTime(CV_cvodemem, ropt[7]); if (ropt[8] > ZERO) CVodeSetNonlinConvCoef(CV_cvodemem, ropt[8]); } else { CV_optin = FALSE; } *ier = CVodeMalloc(CV_cvodemem, FCVf, *t0, F2C_vec, itol, *rtol, atolptr); /* reset data pointer into F2C_vec */ N_VSetArrayPointer(data_F2C_vec, F2C_vec); /* destroy F2C_atolvec if allocated */ if (F2C_atolvec != NULL) { N_VSetArrayPointer(data_F2C_atolvec, F2C_atolvec); N_VDestroy(F2C_atolvec); } if(*ier != CV_SUCCESS) { *ier = -1; return; } /* Store the unit roundoff in ropt for user access */ ropt[9] = UNIT_ROUNDOFF; CV_iopt = iopt; CV_ropt = ropt; return; }
/* ** ======== ** 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 CvodeSolver::initialize(const double &pVoiStart, const int &pStatesCount, double *pConstants, double *pStates, double *pRates, double *pAlgebraic, ComputeRatesFunction pComputeRates) { if (!mSolver) { // Initialise the ODE solver itself OpenCOR::CoreSolver::CoreOdeSolver::initialize(pVoiStart, pStatesCount, pConstants, pStates, pRates, pAlgebraic, pComputeRates); // Retrieve some of the CVODE properties if (mProperties.contains(MaximumStepProperty)) { mMaximumStep = mProperties.value(MaximumStepProperty).toDouble(); } else { emit error(QObject::tr("the 'maximum step' property value could not be retrieved")); return; } if (mProperties.contains(MaximumNumberOfStepsProperty)) { mMaximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsProperty).toInt(); } else { emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved")); return; } if (mProperties.contains(RelativeToleranceProperty)) { mRelativeTolerance = mProperties.value(RelativeToleranceProperty).toDouble(); } else { emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved")); return; } if (mProperties.contains(AbsoluteToleranceProperty)) { mAbsoluteTolerance = mProperties.value(AbsoluteToleranceProperty).toDouble(); } else { emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved")); return; } // Create the states vector mStatesVector = N_VMake_Serial(pStatesCount, pStates); // Create the CVODE solver mSolver = CVodeCreate(CV_BDF, CV_NEWTON); // Use our own error handler CVodeSetErrHandlerFn(mSolver, errorHandler, this); // Initialise the CVODE solver CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector); // Set some user data delete mUserData; // Just in case the solver got initialised before mUserData = new CvodeSolverUserData(pConstants, pAlgebraic, pComputeRates); CVodeSetUserData(mSolver, mUserData); // Set the linear solver CVDense(mSolver, pStatesCount); // Set the maximum step CVodeSetMaxStep(mSolver, mMaximumStep); // Set the maximum number of steps CVodeSetMaxNumSteps(mSolver, mMaximumNumberOfSteps); // Set the relative and absolute tolerances CVodeSStolerances(mSolver, mRelativeTolerance, mAbsoluteTolerance); } else { // Reinitialise the CVODE object CVodeReInit(mSolver, pVoiStart, mStatesVector); } }