6 #include "cantera/base/config.h"
14 #if SUNDIALS_VERSION == 22
16 #include "sundials_types.h"
17 #include "sundials_math.h"
19 #include "cvodes_dense.h"
20 #include "cvodes_diag.h"
21 #include "cvodes_spgmr.h"
22 #include "cvodes_band.h"
23 #include "nvector_serial.h"
27 #if SUNDIALS_VERSION >= 23
28 #include "sundials/sundials_types.h"
29 #include "sundials/sundials_math.h"
30 #include "sundials/sundials_nvector.h"
31 #include "nvector/nvector_serial.h"
32 #include "cvodes/cvodes.h"
33 #include "cvodes/cvodes_dense.h"
34 #include "cvodes/cvodes_diag.h"
35 #include "cvodes/cvodes_spgmr.h"
36 #include "cvodes/cvodes_band.h"
39 #error unsupported Sundials version!
42 #if SUNDIALS_VERSION >= 24
58 FuncData(FuncEval* f,
int npar = 0) {
59 m_pars.resize(npar, 1.0);
62 virtual ~FuncData() {}
80 static int cvodes_rhs(realtype t, N_Vector y, N_Vector ydot,
84 double* ydata = NV_DATA_S(y);
85 double* ydotdata = NV_DATA_S(ydot);
86 Cantera::FuncData* d = (Cantera::FuncData*)f_data;
88 if (d->m_pars.size() == 0) {
89 f->
eval(t, ydata, ydotdata, NULL);
94 std::cerr << err.
what() << std::endl;
97 std::cerr <<
"cvodes_rhs: unhandled exception" << std::endl;
106 CVodesIntegrator::CVodesIntegrator() :
119 m_reltolsens(1.0e-5),
120 m_abstolsens(1.0e-4),
125 m_maxErrTestFails(0),
128 m_mupper(0), m_mlower(0),
131 #if SUNDIALS_VERSION <= 23
133 "Support for these versions will be removed in Cantera 2.2.");
140 CVodesIntegrator::~CVodesIntegrator()
144 CVodeSensFree(m_cvode_mem);
146 CVodeFree(&m_cvode_mem);
149 N_VDestroy_Serial(m_y);
152 N_VDestroy_Serial(m_abstol);
161 return NV_Ith_S(m_y, k);
166 return NV_DATA_S(m_y);
175 N_VDestroy_Serial(m_abstol);
177 m_abstol = N_VNew_Serial(n);
179 for (
size_t i=0; i<n; i++) {
180 NV_Ith_S(m_abstol, i) = abstol[i];
194 m_reltolsens = reltol;
195 m_abstolsens = abstol;
218 CVodeSetMaxStep(m_cvode_mem, hmax);
226 CVodeSetMinStep(m_cvode_mem, hmin);
230 void CVodesIntegrator::setMaxSteps(
int nmax)
234 CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
240 m_maxErrTestFails = n;
242 CVodeSetMaxErrTestFails(m_cvode_mem, n);
251 m_iter = CV_FUNCTIONAL;
257 void CVodesIntegrator::sensInit(
double t0,
FuncEval& func)
260 size_t nv = func.
neq();
265 y = N_VNew_Serial(nv);
266 m_yS = N_VCloneVectorArray_Serial(m_np, y);
267 for (
size_t n = 0; n < m_np; n++) {
268 data = NV_DATA_S(m_yS[n]);
269 for (
size_t j = 0; j < nv; j++) {
276 #if SUNDIALS_VERSION <= 23
277 flag = CVodeSensMalloc(m_cvode_mem, m_np, CV_STAGGERED, m_yS);
278 if (flag != CV_SUCCESS) {
279 throw CVodesErr(
"Error in CVodeSensMalloc");
282 double rtol = m_reltolsens;
283 flag = CVodeSetSensTolerances(m_cvode_mem, CV_SS, rtol,
DATA_PTR(atol));
284 #elif SUNDIALS_VERSION >= 24
285 flag = CVodeSensInit(m_cvode_mem, m_np, CV_STAGGERED,
286 CVSensRhsFn(0), m_yS);
288 if (flag != CV_SUCCESS) {
289 throw CVodesErr(
"Error in CVodeSensMalloc");
292 double rtol = m_reltolsens;
293 flag = CVodeSensSStolerances(m_cvode_mem, rtol,
DATA_PTR(atol));
305 N_VDestroy_Serial(m_y);
307 m_y = N_VNew_Serial(m_neq);
308 for (
size_t i = 0; i < m_neq; i++) {
309 NV_Ith_S(m_y, i) = 0.0;
312 if (m_itol == CV_SV && m_nabs < m_neq) {
313 throw CVodesErr(
"not enough absolute tolerance values specified.");
319 CVodeFree(&m_cvode_mem);
328 m_cvode_mem = CVodeCreate(m_method, m_iter);
334 #if SUNDIALS_VERSION <= 23
335 if (m_itol == CV_SV) {
337 flag = CVodeMalloc(m_cvode_mem,
cvodes_rhs, m_t0, m_y, m_itol,
341 flag = CVodeMalloc(m_cvode_mem,
cvodes_rhs, m_t0, m_y, m_itol,
342 m_reltol, &m_abstols);
344 if (flag != CV_SUCCESS) {
345 if (flag == CV_MEM_FAIL) {
346 throw CVodesErr(
"Memory allocation failed.");
347 }
else if (flag == CV_ILL_INPUT) {
348 throw CVodesErr(
"Illegal value for CVodeMalloc input argument.");
353 #elif SUNDIALS_VERSION >= 24
355 flag = CVodeInit(m_cvode_mem,
cvodes_rhs, m_t0, m_y);
356 if (flag != CV_SUCCESS) {
357 if (flag == CV_MEM_FAIL) {
358 throw CVodesErr(
"Memory allocation failed.");
359 }
else if (flag == CV_ILL_INPUT) {
360 throw CVodesErr(
"Illegal value for CVodeInit input argument.");
366 if (m_itol == CV_SV) {
367 flag = CVodeSVtolerances(m_cvode_mem, m_reltol, m_abstol);
369 flag = CVodeSStolerances(m_cvode_mem, m_reltol, m_abstols);
371 if (flag != CV_SUCCESS) {
372 if (flag == CV_MEM_FAIL) {
373 throw CVodesErr(
"Memory allocation failed.");
374 }
else if (flag == CV_ILL_INPUT) {
375 throw CVodesErr(
"Illegal value for CVodeInit input argument.");
384 m_fdata =
new FuncData(&func, func.
nparams());
387 #if SUNDIALS_VERSION <= 23
388 flag = CVodeSetFdata(m_cvode_mem, (
void*)m_fdata);
389 if (flag != CV_SUCCESS) {
390 throw CVodesErr(
"CVodeSetFdata failed.");
392 #elif SUNDIALS_VERSION >= 24
393 flag = CVodeSetUserData(m_cvode_mem, (
void*)m_fdata);
394 if (flag != CV_SUCCESS) {
395 throw CVodesErr(
"CVodeSetUserData failed.");
400 flag = CVodeSetSensParams(m_cvode_mem,
DATA_PTR(m_fdata->m_pars),
407 void CVodesIntegrator::reinitialize(
double t0,
FuncEval& func)
421 #if SUNDIALS_VERSION <= 23
422 if (m_itol == CV_SV) {
423 result = CVodeReInit(m_cvode_mem,
cvodes_rhs, m_t0, m_y,
427 result = CVodeReInit(m_cvode_mem,
cvodes_rhs, m_t0, m_y,
431 if (result != CV_SUCCESS) {
432 throw CVodesErr(
"CVodeReInit failed. result = "+
int2str(result));
434 #elif SUNDIALS_VERSION >= 24
435 result = CVodeReInit(m_cvode_mem, m_t0, m_y);
436 if (result != CV_SUCCESS) {
437 throw CVodesErr(
"CVodeReInit failed. result = "+
int2str(result));
446 if (m_type == DENSE + NOJAC) {
448 CVDense(m_cvode_mem, N);
449 }
else if (m_type == DIAG) {
451 }
else if (m_type == GMRES) {
452 CVSpgmr(m_cvode_mem, PREC_NONE, 0);
453 }
else if (m_type == BAND + NOJAC) {
455 long int nu = m_mupper;
456 long int nl = m_mlower;
457 CVBand(m_cvode_mem, N, nu, nl);
463 CVodeSetMaxOrd(m_cvode_mem, m_maxord);
465 if (m_maxsteps > 0) {
466 CVodeSetMaxNumSteps(m_cvode_mem, m_maxsteps);
469 CVodeSetMaxStep(m_cvode_mem, m_hmax);
472 CVodeSetMinStep(m_cvode_mem, m_hmin);
474 if (m_maxErrTestFails > 0) {
475 CVodeSetMaxErrTestFails(m_cvode_mem, m_maxErrTestFails);
481 int flag = CVode(m_cvode_mem, tout, m_y, &
m_time, CV_NORMAL);
482 if (flag != CV_SUCCESS) {
484 "\nComponents with largest weighted error estimates:\n" +
getErrorInfo(10));
491 int flag = CVode(m_cvode_mem, tout, m_y, &
m_time, CV_ONE_STEP);
492 if (flag != CV_SUCCESS) {
494 "\nComponents with largest weighted error estimates:\n" +
getErrorInfo(10));
504 CVodeGetNumRhsEvals(m_cvode_mem, &ne);
509 double CVodesIntegrator::sensitivity(
size_t k,
size_t p)
516 #if SUNDIALS_VERSION <= 23
517 int flag = CVodeGetSens(m_cvode_mem,
m_time, m_yS);
518 #elif SUNDIALS_VERSION >= 24
519 int flag = CVodeGetSens(m_cvode_mem, &
m_time, m_yS);
521 if (flag != CV_SUCCESS) {
522 throw CVodesErr(
"CVodeGetSens failed. Error code: " +
int2str(flag));
528 throw CVodesErr(
"sensitivity: k out of range ("+
int2str(p)+
")");
531 throw CVodesErr(
"sensitivity: p out of range ("+
int2str(p)+
")");
533 return NV_Ith_S(m_yS[p],k);
538 N_Vector errs = N_VNew_Serial(m_neq);
539 N_Vector errw = N_VNew_Serial(m_neq);
540 CVodeGetErrWeights(m_cvode_mem, errw);
541 CVodeGetEstLocalErrors(m_cvode_mem, errs);
543 vector<pair<pair<double, double>,
size_t> > weightedErrors;
544 for (
size_t i=0; i<m_neq; i++) {
545 double err = NV_Ith_S(errs, i) * NV_Ith_S(errw, i);
546 weightedErrors.push_back(make_pair(make_pair(-abs(err), err), i));
551 sort(weightedErrors.begin(), weightedErrors.end());
553 for (
int i=0; i<N; i++) {
554 s << weightedErrors[i].second <<
": "
555 << weightedErrors[i].first.second << endl;
Backward Differentiation.
virtual void setProblemType(int probtype)
Set the problem type.
void applyOptions()
Applies user-specified options to the underlying CVODES solver.
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Exception thrown when a CVODES error is encountered.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
virtual void eval(double t, double *y, double *ydot, double *p)=0
Evaluate the right-hand-side function.
virtual void setMaxStepSize(double hmax)
Set the maximum step size.
virtual void setMethod(MethodType t)
Set the solution method.
virtual void setMinStepSize(double hmin)
Set the minimum step size.
virtual void setIterator(IterType t)
Set the linear iterator.
virtual int nEvals() const
The number of function evaluations.
virtual double * solution()
The current value of the solution of the system of equations.
const char * what() const
Get a description of the error.
virtual size_t neq()=0
Number of equations.
virtual void integrate(double tout)
Integrate the system of equations.
virtual void setSensitivityTolerances(double reltol, double abstol)
Set the sensitivity error tolerances.
virtual std::string getErrorInfo(int N)
Returns a string listing the weighted error estimates associated with each solution component...
Base class for exceptions thrown by Cantera classes.
virtual size_t nparams()
Number of sensitivity parameters.
virtual void setTolerances(double reltol, size_t n, double *abstol)
Set or reset the number of equations.
virtual void setMaxErrTestFails(int n)
Set the maximum permissible number of error test failures.
bool m_sens_ok
Indicates whether the sensitivities stored in m_yS have been updated for at the current integrator ti...
IterType
Specifies the method used for iteration.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
virtual doublereal step(double tout)
Integrate the system of equations.
Contains declarations for string manipulation functions within Cantera.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
Virtual base class for ODE right-hand-side function evaluators.
static int cvodes_rhs(realtype t, N_Vector y, N_Vector ydot, void *f_data)
Function called by cvodes to evaluate ydot given y.
MethodType
Specifies the method used to integrate the system of equations.
double m_time
The current integrator time.
virtual void getInitialConditions(double t0, size_t leny, double *y)=0
Fill the solution vector with the initial conditions at initial time t0.
virtual void initialize(double t0, FuncEval &func)
Initialize the integrator for a new problem.