void CVodesIntegrator::setMaxStepSize(doublereal hmax) { m_hmax = hmax; if (m_cvode_mem) { CVodeSetMaxStep(m_cvode_mem, hmax); } }
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); } }
void Cvode::maxstep(double x) { if (use_daspk_) { if (daspk_->mem_) { IDASetMaxStep(daspk_->mem_, x); } }else{ if (mem_) { CVodeSetMaxStep(mem_, x); } } }
int CVodeSetMaxStepB(void *cvadj_mem, realtype hmaxB) { CVadjMem ca_mem; void *cvode_mem; int flag; ca_mem = (CVadjMem) cvadj_mem; cvode_mem = (void *)ca_mem->cvb_mem; flag = CVodeSetMaxStep(cvode_mem, hmaxB); return(flag); }
int CVodeSetMaxStepB(void *cvadj_mem, realtype hmaxB) { CVadjMem ca_mem; void *cvode_mem; int flag; if (cvadj_mem == NULL) { CVProcessError(NULL, CV_ADJMEM_NULL, "CVODEA", "CVodeSetMaxStepB", MSGAM_NULL_CAMEM); return(CV_ADJMEM_NULL); } ca_mem = (CVadjMem) cvadj_mem; cvode_mem = (void *)ca_mem->cvb_mem; flag = CVodeSetMaxStep(cvode_mem, hmaxB); return(flag); }
void FCV_SETRIN(char key_name[], realtype *rval, int *ier) { if (!strncmp(key_name,"INIT_STEP",9)) *ier = CVodeSetInitStep(CV_cvodemem, *rval); else if (!strncmp(key_name,"MAX_STEP",8)) *ier = CVodeSetMaxStep(CV_cvodemem, *rval); else if (!strncmp(key_name,"MIN_STEP",8)) *ier = CVodeSetMinStep(CV_cvodemem, *rval); else if (!strncmp(key_name,"STOP_TIME",9)) *ier = CVodeSetStopTime(CV_cvodemem, *rval); else if (!strncmp(key_name,"NLCONV_COEF",11)) *ier = CVodeSetNonlinConvCoef(CV_cvodemem, *rval); else { *ier = -99; fprintf(stderr, "FCVSETRIN: Unrecognized key.\n\n"); } }
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 CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB) { 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", "CVodeSetMaxStepB", 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", "CVodeSetMaxStepB", 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", "CVodeSetMaxStepB", 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 = CVodeSetMaxStep(cvodeB_mem, hmaxB); 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 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 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); }
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; }
/* ** ======== ** 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; }
/// Set the maximum time step of the linear multistep method. void SetMaxStep(double dt_max) { flag = CVodeSetMaxStep(sundials_mem, dt_max); }
/* * 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); }
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; }
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); }
/* Main Function */ int main(int argc, char *argv[]) { char tmpLName[11],tmpFName[11]; /* rivFlux File names */ Model_Data mData; /* Model Data */ Control_Data cData; /* Solver Control Data */ N_Vector CV_Y; /* State Variables Vector */ void *cvode_mem; /* Model Data Pointer */ int flag; /* flag to test return value */ FILE *Ofile[22]; /* Output file */ char *ofn[22]; FILE *iproj; /* Project File */ int N; /* Problem size */ int i,j,k; /* loop index */ realtype t; /* simulation time */ realtype NextPtr, StepSize; /* stress period & step size */ clock_t start, end_r, end_s; /* system clock at points */ realtype cputime_r, cputime_s; /* for duration in realtype */ char *filename; /* Project Input Name */ if(argc!=2) { iproj=fopen("projectName.txt","r"); if(iproj==NULL) { printf("\t\nUsage ./pihm project_name"); printf("\t\n OR "); printf("\t\nUsage ./pihm, and have a file in the current directory named projectName.txt with the project name in it"); exit(0); } else { filename = (char *)malloc(15*sizeof(char)); fscanf(iproj,"%s",filename); } } else { /* get user specified file name in command line */ filename = (char *)malloc(strlen(argv[1])*sizeof(char)); strcpy(filename,argv[1]); } /* Open Output Files */ ofn[0] = (char *)malloc((strlen(filename)+3)*sizeof(char)); strcpy(ofn[0], filename); Ofile[0]=fopen(strcat(ofn[0], ".GW"),"w"); ofn[1] = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ofn[1], filename); Ofile[1]=fopen(strcat(ofn[1], ".surf"),"w"); ofn[2] = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(ofn[2], filename); Ofile[2]=fopen(strcat(ofn[2], ".et0"),"w"); ofn[3] = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(ofn[3], filename); Ofile[3]=fopen(strcat(ofn[3], ".et1"),"w"); ofn[4] = (char *)malloc((strlen(filename)+4)*sizeof(char)); strcpy(ofn[4], filename); Ofile[4]=fopen(strcat(ofn[4], ".et2"),"w"); ofn[5] = (char *)malloc((strlen(filename)+3)*sizeof(char)); strcpy(ofn[5], filename); Ofile[5]=fopen(strcat(ofn[5], ".is"),"w"); ofn[6] = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ofn[6], filename); Ofile[6]=fopen(strcat(ofn[6], ".snow"),"w"); for(i=0;i<11;i++) { sprintf(tmpLName,".rivFlx%d",i); strcpy(tmpFName,filename); strcat(tmpFName,tmpLName); Ofile[7+i]=fopen(tmpFName,"w"); } ofn[18] = (char *)malloc((strlen(filename)+6)*sizeof(char)); strcpy(ofn[18], filename); Ofile[18]=fopen(strcat(ofn[18], ".stage"),"w"); ofn[19] = (char *)malloc((strlen(filename)+6)*sizeof(char)); strcpy(ofn[19], filename); Ofile[19]=fopen(strcat(ofn[19], ".unsat"),"w"); ofn[20] = (char *)malloc((strlen(filename)+5)*sizeof(char)); strcpy(ofn[20], filename); Ofile[20]=fopen(strcat(ofn[20], ".Rech"),"w"); /* allocate memory for model data structure */ mData = (Model_Data)malloc(sizeof *mData); printf("\n ... PIHM 2.0 is starting ... \n"); /* read in 9 input files with "filename" as prefix */ read_alloc(filename, mData, &cData); /* if(mData->UnsatMode ==1) { } */ if(mData->UnsatMode ==2) { /* problem size */ N = 3*mData->NumEle + 2*mData->NumRiv; mData->DummyY=(realtype *)malloc((3*mData->NumEle+2*mData->NumRiv)*sizeof(realtype)); } /* initial state variable depending on machine*/ CV_Y = N_VNew_Serial(N); /* initialize mode data structure */ initialize(filename, mData, &cData, CV_Y); printf("\nSolving ODE system ... \n"); /* allocate memory for solver */ cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON); if(cvode_mem == NULL) {printf("CVodeMalloc failed. \n"); return(1);} flag = CVodeSetFdata(cvode_mem, mData); flag = CVodeSetInitStep(cvode_mem,cData.InitStep); flag = CVodeSetStabLimDet(cvode_mem,TRUE); flag = CVodeSetMaxStep(cvode_mem,cData.MaxStep); flag = CVodeMalloc(cvode_mem, f, cData.StartTime, CV_Y, CV_SS, cData.reltol, &cData.abstol); flag = CVSpgmr(cvode_mem, PREC_NONE, 0); flag = CVSpgmrSetGSType(cvode_mem, MODIFIED_GS); /* set start time */ t = cData.StartTime; start = clock(); /* start solver in loops */ for(i=0; i<cData.NumSteps; i++) { /* if (cData.Verbose != 1) { printf(" Running: %-4.1f%% ... ", (100*(i+1)/((realtype) cData.NumSteps))); fflush(stdout); } */ /* inner loops to next output points with ET step size control */ while(t < cData.Tout[i+1]) { if (t + cData.ETStep >= cData.Tout[i+1]) { NextPtr = cData.Tout[i+1]; } else { NextPtr = t + cData.ETStep; } StepSize = NextPtr - t; /* calculate Interception Storage */ is_sm_et(t, StepSize, mData,CV_Y); printf("\n Tsteps = %f ",t); flag = CVode(cvode_mem, NextPtr, CV_Y, &t, CV_NORMAL); update(t,mData); } PrintData(Ofile,&cData,mData, CV_Y,t); } /* Free memory */ N_VDestroy_Serial(CV_Y); /* Free integrator memory */ CVodeFree(cvode_mem); free(mData); return 0; }
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); }
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); } }