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_BAND(long int *neq, long int *mupper, long int *mlower, int *ier) { /* neq is the problem size mupper is the upper bandwidth mlower is the lower bandwidth */ *ier = CVBand(CV_cvodemem, *neq, *mupper, *mlower); CV_ls = 2; }
int CVBandB(void *cvadj_mem, long int nB, long int mupperB, long int mlowerB) { 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 = CVBand(cvode_mem, nB, mupperB, mlowerB); 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 CVBandB(void *cvadj_mem, long int nB, long int mupperB, long int mlowerB) { CVadjMem ca_mem; CVBandMemB cvbandB_mem; CVodeMem cvB_mem; int flag; if (cvadj_mem == NULL) { CVProcessError(NULL, CVBAND_ADJMEM_NULL, "CVBAND", "CVBandB", MSGB_CAMEM_NULL); return(CVBAND_ADJMEM_NULL); } ca_mem = (CVadjMem) cvadj_mem; cvB_mem = ca_mem->cvb_mem; /* Get memory for CVBandMemRecB */ cvbandB_mem = (CVBandMemB) malloc(sizeof(CVBandMemRecB)); if (cvbandB_mem == NULL) { CVProcessError(cvB_mem, CVBAND_MEM_FAIL, "CVBAND", "CVBandB", MSGB_MEM_FAIL); return(CVBAND_MEM_FAIL); } bjac_B = NULL; jac_data_B = NULL; /* attach lmemB and lfreeB */ lmemB = cvbandB_mem; lfreeB = CVBandFreeB; flag = CVBand(cvB_mem, nB, mupperB, mlowerB); if (flag != CVBAND_SUCCESS) { free(cvbandB_mem); cvbandB_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 main(void) { realtype dx, dy, reltol, abstol, t, tout, umax; N_Vector u; UserData data; void *cvode_mem; int iout, flag; long int nst; u = NULL; data = NULL; cvode_mem = NULL; /* Create a serial vector */ u = N_VNew_Serial(NEQ); /* Allocate u vector */ if(check_flag((void*)u, "N_VNew_Serial", 0)) return(1); reltol = ZERO; /* Set the tolerances */ abstol = ATOL; data = (UserData) malloc(sizeof *data); /* Allocate data memory */ if(check_flag((void *)data, "malloc", 2)) return(1); dx = data->dx = XMAX/(MX+1); /* Set grid coefficients in data */ dy = data->dy = YMAX/(MY+1); data->hdcoef = ONE/(dx*dx); data->hacoef = HALF/(TWO*dx); data->vdcoef = ONE/(dy*dy); SetIC(u, data); /* Initialize u vector */ /* 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 u'=f(t,u), the inital time T0, and * the initial dependent variable vector u. */ flag = CVodeInit(cvode_mem, f, T0, u); if(check_flag(&flag, "CVodeInit", 1)) return(1); /* Call CVodeSStolerances to specify the scalar relative tolerance * and scalar absolute tolerance */ flag = CVodeSStolerances(cvode_mem, reltol, abstol); if (check_flag(&flag, "CVodeSStolerances", 1)) return(1); /* Set the pointer to user-defined data */ flag = CVodeSetUserData(cvode_mem, data); if(check_flag(&flag, "CVodeSetUserData", 1)) return(1); /* Call CVBand to specify the CVBAND band linear solver */ flag = CVBand(cvode_mem, NEQ, MY, MY); if(check_flag(&flag, "CVBand", 1)) return(1); /* Set the user-supplied Jacobian routine Jac */ flag = CVDlsSetBandJacFn(cvode_mem, Jac); if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1); /* In loop over output points: call CVode, print results, test for errors */ umax = N_VMaxNorm(u); PrintHeader(reltol, abstol, umax); for(iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1)) break; umax = N_VMaxNorm(u); flag = CVodeGetNumSteps(cvode_mem, &nst); check_flag(&flag, "CVodeGetNumSteps", 1); PrintOutput(t, umax, nst); } PrintFinalStats(cvode_mem); /* Print some final statistics */ N_VDestroy_Serial(u); /* Free the u vector */ CVodeFree(&cvode_mem); /* Free the integrator memory */ free(data); /* Free the user data */ return(0); }
int CVBandB(void *cvode_mem, int which, int nB, int mupperB, int mlowerB) { 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, "CVSBAND", "CVBandB", 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, "CVSBAND", "CVBandB", 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, "CVSBAND", "CVBandB", MSGCV_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, "CVSBAND", "CVBandB", MSGD_MEM_FAIL); return(CVDLS_MEM_FAIL); } /* set matrix type */ cvdlsB_mem->d_typeB = SUNDIALS_BAND; /* initialize Jacobian function */ cvdlsB_mem->d_bjacB = NULL; /* attach lmemB and lfreeB */ cvB_mem->cv_lmem = cvdlsB_mem; cvB_mem->cv_lfree = cvBandFreeB; flag = CVBand(cvodeB_mem, nB, mupperB, mlowerB); if (flag != CVDLS_SUCCESS) { free(cvdlsB_mem); cvdlsB_mem = NULL; } return(flag); }
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); } }
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); }
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 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; }
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 OpenSMOKE_CVODE_Sundials<T>::Solve(const double xend) { int flag; this->x_ = this->x0_; this->xend_ = xend; for(int i=0;i<this->n_;i++) NV_Ith_S(y0Sundials_,i) = this->y0_[i]; if (firstCall_ == true) { firstCall_ = false; /* 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_, std::string("CVodeCreate"), 0)) exit(-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 y0Sundials_. */ flag = CVodeInit(cvode_mem_, this->odeSystem_->GetSystemFunctionsStatic, this->odeSystem_->GetWriteFunctionStatic, this->x0_, y0Sundials_); if (check_flag(&flag, std::string("CVodeInit"), 1)) exit(-1); /* Call CVodeSVtolerances to specify the scalar relative tolerance * and vector absolute tolerances */ flag = CVodeSStolerances(cvode_mem_, this->relTolerance_[0], this->absTolerance_[0]); if (check_flag(&flag, std::string("CVodeSVtolerances"), 1)) exit(-1); /* Call Solver */ if (this->iUseLapack_ == false) { if (this->mUpper_ == 0 && this->mLower_ == 0) { // std::cout << "CVODE Solver: Dense Jacobian (without Lapack)..." << std::endl; flag = CVDense(cvode_mem_, this->n_); if (check_flag(&flag, std::string("CVDense"), 1)) exit(-1); } else { // std::cout << "CVODE Solver: Band Jacobian (without Lapack)..." << std::endl; flag = CVBand(cvode_mem_, this->n_, this->mUpper_, this->mLower_); if (check_flag(&flag, std::string("CVBand"), 1)) exit(-1); } } else { if (this->mUpper_ == 0 && this->mLower_ == 0) { // std::cout << "CVODE Solver: Dense Jacobian (with Lapack)..." << std::endl; flag = CVLapackDense(cvode_mem_, this->n_); if (check_flag(&flag, std::string("CVLapackDense"), 1)) exit(-1); } else { // std::cout << "CVODE Solver: Band Jacobian (with Lapack)..." << std::endl; flag = CVLapackBand(cvode_mem_, this->n_, this->mUpper_, this->mLower_); if (check_flag(&flag, std::string("CVLapackBand"), 1)) exit(-1); } } } else { flag = CVodeReInit(cvode_mem_, this->x0_, y0Sundials_); if (check_flag(&flag, std::string("CVodeReInit"), 1)) exit(-1); } AnalyzeUserOptions(); /* Solving */ this->tStart_ = this->GetClockTime(); flag = CVode(cvode_mem_, this->xend_, ySundials_, &this->x_, CV_NORMAL); this->tEnd_ = this->GetClockTime(); this->x0_ = this->x_; for(int i=0;i<this->n_;i++) NV_Ith_S(y0Sundials_,i) = NV_Ith_S(ySundials_,i); for(int i=0;i<this->n_;i++) this->y_[i] = NV_Ith_S(ySundials_,i); }