13 #if SUNDIALS_VERSION >= 24
14 #include "sundials/sundials_types.h"
15 #include "sundials/sundials_math.h"
17 #include "ida/ida_dense.h"
18 #include "ida/ida_spgmr.h"
19 #include "ida/ida_band.h"
20 #include "nvector/nvector_serial.h"
24 #if SUNDIALS_VERSION < 25
25 typedef int sd_size_t;
27 typedef long int sd_size_t;
31 inline static N_Vector nv(
void* x)
33 return reinterpret_cast<N_Vector
>(x);
48 ResidData(ResidJacEval* f, IDA_Solver* s,
int npar = 0) {
53 virtual ~ResidData() {
78 static int ida_resid(realtype t, N_Vector y, N_Vector ydot, N_Vector r,
void* f_data)
80 double* ydata = NV_DATA_S(y);
81 double* ydotdata = NV_DATA_S(ydot);
82 double* rdata = NV_DATA_S(r);
83 Cantera::ResidData* d = (Cantera::ResidData*) f_data;
85 Cantera::IDA_Solver* s = d->m_solver;
86 double delta_t = s->getCurrentStepFromIDA();
89 int flag = f->
evalResidNJ(t, delta_t, ydata, ydotdata, rdata);
113 static int ida_jacobian(sd_size_t nrows, realtype t, realtype c_j, N_Vector y, N_Vector ydot, N_Vector r,
114 DlsMat Jac,
void* f_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
116 doublereal* ydata = NV_DATA_S(y);
117 doublereal* ydotdata = NV_DATA_S(ydot);
118 doublereal* rdata = NV_DATA_S(r);
119 Cantera::ResidData* d = (Cantera::ResidData*) f_data;
121 doublereal*
const* colPts = Jac->cols;
122 Cantera::IDA_Solver* s = d->m_solver;
123 double delta_t = s->getCurrentStepFromIDA();
125 f->
evalJacobianDP(t, delta_t, c_j, ydata, ydotdata, colPts, rdata);
140 IDA_Solver::IDA_Solver(ResidJacEval& f) :
166 m_maxErrTestFails(-1),
168 m_maxNonlinConvFails(-1),
176 IDA_Solver::~IDA_Solver()
182 N_VDestroy_Serial(nv(m_y));
185 N_VDestroy_Serial(nv(m_ydot));
188 N_VDestroy_Serial(nv(m_abstol));
191 N_VDestroy_Serial(nv(m_constraints));
196 doublereal IDA_Solver::solution(
int k)
const
198 return NV_Ith_S(nv(m_y),k);
201 const doublereal* IDA_Solver::solutionVector()
const
203 return NV_DATA_S(nv(m_y));
206 doublereal IDA_Solver::derivative(
int k)
const
208 return NV_Ith_S(nv(m_ydot),k);
211 const doublereal* IDA_Solver::derivativeVector()
const
213 return NV_DATA_S(nv(m_ydot));
217 void IDA_Solver::setTolerances(
double reltol,
double* abstol)
221 m_abstol =
reinterpret_cast<void*
>(N_VNew_Serial(m_neq));
223 for (
int i = 0; i < m_neq; i++) {
224 NV_Ith_S(nv(m_abstol), i) = abstol[i];
228 int flag = IDASVtolerances(m_ida_mem, m_reltol, nv(m_abstol));
229 if (flag != IDA_SUCCESS) {
230 throw IDA_Err(
"Memory allocation failed.");
235 void IDA_Solver::setTolerances(doublereal reltol, doublereal abstol)
241 int flag = IDASStolerances(m_ida_mem, m_reltol, m_abstols);
242 if (flag != IDA_SUCCESS) {
243 throw IDA_Err(
"Memory allocation failed.");
248 void IDA_Solver::setLinearSolverType(
int solverType)
253 void IDA_Solver::setDenseLinearSolver()
255 setLinearSolverType(0);
258 void IDA_Solver::setBandedLinearSolver(
int m_upper,
int m_lower)
265 void IDA_Solver::setMaxOrder(
int n)
270 void IDA_Solver::setMaxNumSteps(
int n)
275 void IDA_Solver::setInitialStepSize(doublereal h0)
280 void IDA_Solver::setStopTime(doublereal tstop)
285 doublereal IDA_Solver::getCurrentStepFromIDA()
288 IDAGetCurrentStep(m_ida_mem, &hcur);
292 void IDA_Solver::setJacobianType(
int formJac)
296 if (m_formJac == 1) {
297 int flag = IDADlsSetDenseJacFn(m_ida_mem, ida_jacobian);
298 if (flag != IDA_SUCCESS) {
299 throw IDA_Err(
"IDADlsSetDenseJacFn failed.");
305 void IDA_Solver::setMaxErrTestFailures(
int maxErrTestFails)
307 m_maxErrTestFails = maxErrTestFails;
310 void IDA_Solver::setMaxNonlinIterations(
int n)
312 m_maxNonlinIters = n;
315 void IDA_Solver::setMaxNonlinConvFailures(
int n)
317 m_maxNonlinConvFails = n;
320 void IDA_Solver::inclAlgebraicInErrorTest(
bool yesno)
323 m_setSuppressAlg = 0;
325 m_setSuppressAlg = 1;
330 void IDA_Solver::init(doublereal t0)
338 N_VDestroy_Serial(nv(m_y));
341 N_VDestroy_Serial(nv(m_ydot));
344 N_VDestroy_Serial(nv(m_id));
347 N_VDestroy_Serial(nv(m_constraints));
350 m_y =
reinterpret_cast<void*
>(N_VNew_Serial(m_neq));
351 m_ydot =
reinterpret_cast<void*
>(N_VNew_Serial(m_neq));
352 m_constraints =
reinterpret_cast<void*
>(N_VNew_Serial(m_neq));
354 for (
int i=0; i<m_neq; i++) {
355 NV_Ith_S(nv(m_y), i) = 0.0;
356 NV_Ith_S(nv(m_ydot), i) = 0.0;
357 NV_Ith_S(nv(m_constraints), i) = 0.0;
361 m_resid.getInitialConditions(m_t0, NV_DATA_S(nv(m_y)), NV_DATA_S(nv(m_ydot)));
368 m_ida_mem = IDACreate();
374 if (m_itol == IDA_SV) {
375 #if SUNDIALS_VERSION <= 23
377 flag = IDAMalloc(m_ida_mem, ida_resid, m_t0, nv(m_y), nv(m_ydot),
378 m_itol, m_reltol, nv(m_abstol));
379 if (flag != IDA_SUCCESS) {
380 if (flag == IDA_MEM_FAIL) {
381 throw IDA_Err(
"Memory allocation failed.");
382 }
else if (flag == IDA_ILL_INPUT) {
383 throw IDA_Err(
"Illegal value for IDAMalloc input argument.");
385 throw IDA_Err(
"IDAMalloc failed.");
389 #elif SUNDIALS_VERSION >= 24
390 flag = IDAInit(m_ida_mem, ida_resid, m_t0, nv(m_y), nv(m_ydot));
391 if (flag != IDA_SUCCESS) {
392 if (flag == IDA_MEM_FAIL) {
393 throw IDA_Err(
"Memory allocation failed.");
394 }
else if (flag == IDA_ILL_INPUT) {
395 throw IDA_Err(
"Illegal value for IDAMalloc input argument.");
397 throw IDA_Err(
"IDAMalloc failed.");
400 flag = IDASVtolerances(m_ida_mem, m_reltol, nv(m_abstol));
401 if (flag != IDA_SUCCESS) {
402 throw IDA_Err(
"Memory allocation failed.");
406 #if SUNDIALS_VERSION <= 23
408 flag = IDAMalloc(m_ida_mem, ida_resid, m_t0, nv(m_y), nv(m_ydot),
409 m_itol, m_reltol, &m_abstols);
410 if (flag != IDA_SUCCESS) {
411 if (flag == IDA_MEM_FAIL) {
412 throw IDA_Err(
"Memory allocation failed.");
413 }
else if (flag == IDA_ILL_INPUT) {
414 throw IDA_Err(
"Illegal value for IDAMalloc input argument.");
416 throw IDA_Err(
"IDAMalloc failed.");
420 #elif SUNDIALS_VERSION >= 24
421 flag = IDAInit(m_ida_mem, ida_resid, m_t0, nv(m_y), nv(m_ydot));
422 if (flag != IDA_SUCCESS) {
423 if (flag == IDA_MEM_FAIL) {
424 throw IDA_Err(
"Memory allocation failed.");
425 }
else if (flag == IDA_ILL_INPUT) {
426 throw IDA_Err(
"Illegal value for IDAMalloc input argument.");
428 throw IDA_Err(
"IDAMalloc failed.");
431 flag = IDASStolerances(m_ida_mem, m_reltol, m_abstols);
432 if (flag != IDA_SUCCESS) {
433 throw IDA_Err(
"Memory allocation failed.");
442 if (m_type == 1 || m_type == 0) {
444 flag = IDADense(m_ida_mem, N);
446 throw IDA_Err(
"IDADense failed");
448 }
else if (m_type == 2) {
450 long int nu = m_mupper;
451 long int nl = m_mlower;
452 IDABand(m_ida_mem, N, nu, nl);
454 throw IDA_Err(
"unsupported linear solver type");
457 if (m_formJac == 1) {
458 flag = IDADlsSetDenseJacFn(m_ida_mem, ida_jacobian);
459 if (flag != IDA_SUCCESS) {
460 throw IDA_Err(
"IDADlsSetDenseJacFn failed.");
465 m_fdata =
new ResidData(&m_resid,
this, m_resid.nparams());
466 #if SUNDIALS_VERSION <= 23
467 flag = IDASetRdata(m_ida_mem, (
void*)m_fdata);
468 if (flag != IDA_SUCCESS) {
469 throw IDA_Err(
"IDASetRdata failed.");
471 #elif SUNDIALS_VERSION >= 24
472 flag = IDASetUserData(m_ida_mem, (
void*)m_fdata);
473 if (flag != IDA_SUCCESS) {
474 throw IDA_Err(
"IDASetUserData failed.");
480 flag = IDASetMaxOrd(m_ida_mem, m_maxord);
481 if (flag != IDA_SUCCESS) {
482 throw IDA_Err(
"IDASetMaxOrd failed.");
485 if (m_maxsteps > 0) {
486 flag = IDASetMaxNumSteps(m_ida_mem, m_maxsteps);
487 if (flag != IDA_SUCCESS) {
488 throw IDA_Err(
"IDASetMaxNumSteps failed.");
492 flag = IDASetInitStep(m_ida_mem, m_h0);
493 if (flag != IDA_SUCCESS) {
494 throw IDA_Err(
"IDASetInitStep failed.");
498 flag = IDASetStopTime(m_ida_mem, m_tstop);
499 if (flag != IDA_SUCCESS) {
500 throw IDA_Err(
"IDASetStopTime failed.");
503 if (m_maxErrTestFails >= 0) {
504 flag = IDASetMaxErrTestFails(m_ida_mem, m_maxErrTestFails);
505 if (flag != IDA_SUCCESS) {
506 throw IDA_Err(
"IDASetMaxErrTestFails failed.");
509 if (m_maxNonlinIters > 0) {
510 flag = IDASetMaxNonlinIters(m_ida_mem, m_maxNonlinIters);
511 if (flag != IDA_SUCCESS) {
512 throw IDA_Err(
"IDASetmaxNonlinIters failed.");
515 if (m_maxNonlinConvFails >= 0) {
516 flag = IDASetMaxConvFails(m_ida_mem, m_maxNonlinConvFails);
517 if (flag != IDA_SUCCESS) {
518 throw IDA_Err(
"IDASetMaxConvFails failed.");
521 if (m_setSuppressAlg != 0) {
522 flag = IDASetSuppressAlg(m_ida_mem, m_setSuppressAlg);
523 if (flag != IDA_SUCCESS) {
524 throw IDA_Err(
"IDASetSuppressAlg failed.");
539 void IDA_Solver::correctInitial_Y_given_Yp(doublereal* y, doublereal* yp, doublereal tout)
541 int icopt = IDA_Y_INIT;
542 doublereal tout1 = tout;
551 int flag = IDACalcIC(m_ida_mem, icopt, tout1);
552 if (flag != IDA_SUCCESS) {
553 throw IDA_Err(
"IDACalcIC failed: error = " +
int2str(flag));
557 flag = IDAGetConsistentIC(m_ida_mem, nv(m_y), nv(m_ydot));
558 if (flag != IDA_SUCCESS) {
559 throw IDA_Err(
"IDAGetSolution failed: error = " +
int2str(flag));
561 doublereal* yy = NV_DATA_S(nv(m_y));
562 doublereal* yyp = NV_DATA_S(nv(m_ydot));
564 for (
int i = 0; i < m_neq; i++) {
584 void IDA_Solver::correctInitial_YaYp_given_Yd(doublereal* y, doublereal* yp, doublereal tout)
587 int icopt = IDA_YA_YDP_INIT;
588 doublereal tout1 = tout;
597 int flag = IDACalcIC(m_ida_mem, icopt, tout1);
598 if (flag != IDA_SUCCESS) {
599 throw IDA_Err(
"IDACalcIC failed: error = " +
int2str(flag));
603 flag = IDAGetConsistentIC(m_ida_mem, nv(m_y), nv(m_ydot));
604 if (flag != IDA_SUCCESS) {
605 throw IDA_Err(
"IDAGetSolution failed: error = " +
int2str(flag));
607 doublereal* yy = NV_DATA_S(nv(m_y));
608 doublereal* yyp = NV_DATA_S(nv(m_ydot));
610 for (
int i = 0; i < m_neq; i++) {
620 flag = IDASetStopTime(m_ida_mem, tout);
621 if (flag != IDA_SUCCESS) {
622 throw IDA_Err(
" IDA error encountered.");
625 if (tout <= m_tcurrent) {
626 throw IDA_Err(
" tout <= tcurrent");
630 flag = IDASolve(m_ida_mem, tout, &tretn, nv(m_y), nv(m_ydot), IDA_ONE_STEP);
632 throw IDA_Err(
" IDA error encountered.");
633 }
else if (flag == IDA_TSTOP_RETURN) {
635 }
else if (flag == IDA_ROOT_RETURN) {
637 }
else if (flag == IDA_WARNING) {
638 throw IDA_Err(
" IDA Warning encountered.");
641 m_deltat = m_tcurrent - m_told;
642 }
while (tretn < tout);
644 if (flag != IDA_SUCCESS && flag != IDA_TSTOP_RETURN) {
645 throw IDA_Err(
" IDA error encountered.");
650 double IDA_Solver::step(
double tout)
654 if (tout <= m_tcurrent) {
655 throw IDA_Err(
" tout <= tcurrent");
659 flag = IDASolve(m_ida_mem, tout, &t, nv(m_y), nv(m_ydot), IDA_ONE_STEP);
661 throw IDA_Err(
" IDA error encountered.");
662 }
else if (flag == IDA_TSTOP_RETURN) {
664 }
else if (flag == IDA_ROOT_RETURN) {
666 }
else if (flag == IDA_WARNING) {
667 throw IDA_Err(
" IDA Warning encountered.");
670 m_deltat = m_tcurrent - m_told;
674 doublereal IDA_Solver::getOutputParameter(
int flag)
const
676 long int lenrw, leniw;
678 case REAL_WORKSPACE_SIZE:
679 flag = IDAGetWorkSpace(m_ida_mem, &lenrw, &leniw);
680 return doublereal(lenrw);