9#include "sundials/sundials_types.h"
10#include "sundials/sundials_math.h"
12#if CT_SUNDIALS_VERSION >= 30
13 #if CT_SUNDIALS_USE_LAPACK
14 #include "sunlinsol/sunlinsol_lapackdense.h"
15 #include "sunlinsol/sunlinsol_lapackband.h"
17 #include "sunlinsol/sunlinsol_dense.h"
18 #include "sunlinsol/sunlinsol_band.h"
20 #include "sunlinsol/sunlinsol_spgmr.h"
21 #include "ida/ida_direct.h"
22 #include "ida/ida_spils.h"
24 #include "ida/ida_dense.h"
25 #include "ida/ida_spgmr.h"
26 #include "ida/ida_band.h"
28#include "nvector/nvector_serial.h"
32#if CT_SUNDIALS_VERSION < 25
35typedef long int sd_size_t;
78 static int ida_resid(realtype t, N_Vector y, N_Vector ydot, N_Vector r,
void* f_data)
85 int flag = f->
evalResidNJ(t, delta_t, NV_DATA_S(y), NV_DATA_S(ydot),
110#if CT_SUNDIALS_VERSION >= 30
111 static int ida_jacobian(realtype t, realtype c_j, N_Vector y, N_Vector yp,
112 N_Vector r, SUNMatrix Jac,
void *f_data,
113 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
120 if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
121 cols = SM_COLS_D(Jac);
122 }
else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
123 cols = SM_COLS_B(Jac);
132 static int ida_jacobian(sd_size_t nrows, realtype t, realtype c_j, N_Vector y, N_Vector ydot, N_Vector r,
133 DlsMat Jac,
void* f_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
140 Jac->cols, NV_DATA_S(r));
176 m_maxErrTestFails(-1),
178 m_maxNonlinConvFails(-1),
185IDA_Solver::~IDA_Solver()
191 N_VDestroy_Serial(
m_y);
194 N_VDestroy_Serial(
m_ydot);
197 N_VDestroy_Serial(m_abstol);
200 N_VDestroy_Serial(m_constraints);
206 return NV_Ith_S(
m_y,k);
209const doublereal* IDA_Solver::solutionVector()
const
211 return NV_DATA_S(
m_y);
216 return NV_Ith_S(
m_ydot,k);
219const doublereal* IDA_Solver::derivativeVector()
const
228 #if CT_SUNDIALS_VERSION >= 60
231 m_abstol = N_VNew_Serial(
m_neq);
234 for (
int i = 0; i <
m_neq; i++) {
235 NV_Ith_S(m_abstol, i) = abstol[i];
239 int flag = IDASVtolerances(
m_ida_mem, m_reltol, m_abstol);
240 if (flag != IDA_SUCCESS) {
242 "Memory allocation failed.");
253 int flag = IDASStolerances(
m_ida_mem, m_reltol, m_abstols);
254 if (flag != IDA_SUCCESS) {
256 "Memory allocation failed.");
261void IDA_Solver::setLinearSolverType(
int solverType)
268 setLinearSolverType(0);
278void IDA_Solver::setMaxOrder(
int n)
309 #if CT_SUNDIALS_VERSION >= 60
311 #elif CT_SUNDIALS_VERSION >= 30
316 if (flag != IDA_SUCCESS) {
318 "IDADlsSetDenseJacFn failed.");
323void IDA_Solver::setMaxErrTestFailures(
int maxErrTestFails)
338void IDA_Solver::inclAlgebraicInErrorTest(
bool yesno)
354 N_VDestroy_Serial(
m_y);
357 N_VDestroy_Serial(
m_ydot);
360 N_VDestroy_Serial(m_id);
363 N_VDestroy_Serial(m_constraints);
366 #if CT_SUNDIALS_VERSION >= 60
373 m_constraints = N_VNew_Serial(
m_neq);
376 for (
int i=0; i<
m_neq; i++) {
377 NV_Ith_S(
m_y, i) = 0.0;
378 NV_Ith_S(
m_ydot, i) = 0.0;
379 NV_Ith_S(m_constraints, i) = 0.0;
390 #if CT_SUNDIALS_VERSION >= 60
397 if (m_itol == IDA_SV) {
399 if (flag != IDA_SUCCESS) {
400 if (flag == IDA_MEM_FAIL) {
402 "Memory allocation failed.");
403 }
else if (flag == IDA_ILL_INPUT) {
405 "Illegal value for IDAInit input argument.");
407 throw CanteraError(
"IDA_Solver::init",
"IDAInit failed.");
410 flag = IDASVtolerances(
m_ida_mem, m_reltol, m_abstol);
411 if (flag != IDA_SUCCESS) {
412 throw CanteraError(
"IDA_Solver::init",
"Memory allocation failed.");
416 if (flag != IDA_SUCCESS) {
417 if (flag == IDA_MEM_FAIL) {
419 "Memory allocation failed.");
420 }
else if (flag == IDA_ILL_INPUT) {
422 "Illegal value for IDAInit input argument.");
424 throw CanteraError(
"IDA_Solver::init",
"IDAInit failed.");
427 flag = IDASStolerances(
m_ida_mem, m_reltol, m_abstols);
428 if (flag != IDA_SUCCESS) {
429 throw CanteraError(
"IDA_Solver::init",
"Memory allocation failed.");
434 if (m_type == 1 || m_type == 0) {
437 #if CT_SUNDIALS_VERSION >= 30
438 SUNLinSolFree((SUNLinearSolver)
m_linsol);
440 #if CT_SUNDIALS_VERSION >= 60
447 "Unable to create SUNDenseMatrix of size {0} x {0}", N);
449 #if CT_SUNDIALS_VERSION >= 60
450 #if CT_SUNDIALS_USE_LAPACK
460 #if CT_SUNDIALS_USE_LAPACK
472 throw CanteraError(
"IDA_Solver::init",
"IDADense failed");
474 }
else if (m_type == 2) {
476 long int nu = m_mupper;
477 long int nl = m_mlower;
478 #if CT_SUNDIALS_VERSION >= 30
479 SUNLinSolFree((SUNLinearSolver)
m_linsol);
481 #if CT_SUNDIALS_VERSION >= 60
483 #elif CT_SUNDIALS_VERSION >= 40
490 "Unable to create SUNBandMatrix of size {} with bandwidths "
491 "{} and {}", N, nu, nl);
493 #if CT_SUNDIALS_VERSION >= 60
494 #if CT_SUNDIALS_USE_LAPACK
504 #if CT_SUNDIALS_USE_LAPACK
517 "unsupported linear solver type");
521 #if CT_SUNDIALS_VERSION >= 60
523 #elif CT_SUNDIALS_VERSION >= 30
528 if (flag != IDA_SUCCESS) {
530 "IDADlsSetDenseJacFn failed.");
536 flag = IDASetUserData(
m_ida_mem, m_fdata.get());
537 if (flag != IDA_SUCCESS) {
538 throw CanteraError(
"IDA_Solver::init",
"IDASetUserData failed.");
544 if (flag != IDA_SUCCESS) {
545 throw CanteraError(
"IDA_Solver::init",
"IDASetMaxOrd failed.");
550 if (flag != IDA_SUCCESS) {
551 throw CanteraError(
"IDA_Solver::init",
"IDASetMaxNumSteps failed.");
556 if (flag != IDA_SUCCESS) {
557 throw CanteraError(
"IDA_Solver::init",
"IDASetInitStep failed.");
562 if (flag != IDA_SUCCESS) {
563 throw CanteraError(
"IDA_Solver::init",
"IDASetStopTime failed.");
568 if (flag != IDA_SUCCESS) {
570 "IDASetMaxErrTestFails failed.");
575 if (flag != IDA_SUCCESS) {
577 "IDASetmaxNonlinIters failed.");
582 if (flag != IDA_SUCCESS) {
584 "IDASetMaxConvFails failed.");
589 if (flag != IDA_SUCCESS) {
590 throw CanteraError(
"IDA_Solver::init",
"IDASetSuppressAlg failed.");
597 doublereal tout1 = tout;
606 int flag = IDACalcIC(
m_ida_mem, IDA_Y_INIT, tout1);
607 if (flag != IDA_SUCCESS) {
608 throw CanteraError(
"IDA_Solver::correctInitial_Y_given_Yp",
609 "IDACalcIC failed: error = {}", flag);
613 if (flag != IDA_SUCCESS) {
614 throw CanteraError(
"IDA_Solver::correctInitial_Y_given_Yp",
615 "IDAGetSolution failed: error = {}", flag);
617 for (
int i = 0; i <
m_neq; i++) {
618 y[i] = NV_Ith_S(
m_y, i);
619 yp[i] = NV_Ith_S(
m_ydot, i);
625 int icopt = IDA_YA_YDP_INIT;
626 doublereal tout1 = tout;
635 int flag = IDACalcIC(
m_ida_mem, icopt, tout1);
636 if (flag != IDA_SUCCESS) {
637 throw CanteraError(
"IDA_Solver::correctInitial_YaYp_given_Yd",
638 "IDACalcIC failed: error = {}", flag);
642 if (flag != IDA_SUCCESS) {
643 throw CanteraError(
"IDA_Solver::correctInitial_YaYp_given_Yd",
644 "IDAGetSolution failed: error = {}", flag);
646 for (
int i = 0; i <
m_neq; i++) {
647 y[i] = NV_Ith_S(
m_y, i);
648 yp[i] = NV_Ith_S(
m_ydot, i);
654 double tretn = tout - 1000;
657 if (flag != IDA_SUCCESS) {
658 throw CanteraError(
"IDA_Solver::solve",
"IDA error encountered.");
660 while (tretn < tout) {
662 throw CanteraError(
"IDA_Solver::solve",
"tout <= tcurrent");
668 throw CanteraError(
"IDA_Solver::solve",
"IDA error encountered.");
669 }
else if (flag == IDA_TSTOP_RETURN) {
671 }
else if (flag == IDA_ROOT_RETURN) {
673 }
else if (flag == IDA_WARNING) {
674 throw CanteraError(
"IDA_Solver::solve",
"IDA Warning encountered.");
680 if (flag != IDA_SUCCESS && flag != IDA_TSTOP_RETURN) {
681 throw CanteraError(
"IDA_Solver::solve",
"IDA error encountered.");
691 throw CanteraError(
"IDA_Solver::step",
"tout <= tcurrent");
697 throw CanteraError(
"IDA_Solver::step",
"IDA error encountered.");
698 }
else if (flag == IDA_TSTOP_RETURN) {
700 }
else if (flag == IDA_ROOT_RETURN) {
702 }
else if (flag == IDA_WARNING) {
703 throw CanteraError(
"IDA_Solver::step",
"IDA Warning encountered.");
712 long int lenrw, leniw;
714 case REAL_WORKSPACE_SIZE:
715 flag = IDAGetWorkSpace(
m_ida_mem, &lenrw, &leniw);
716 return doublereal(lenrw);
static int ida_jacobian(sd_size_t nrows, realtype t, realtype c_j, N_Vector y, N_Vector ydot, N_Vector r, DlsMat Jac, void *f_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
Function called by by IDA to evaluate the Jacobian, given y and ydot.
static int ida_resid(realtype t, N_Vector y, N_Vector ydot, N_Vector r, void *f_data)
Function called by IDA to evaluate the residual, given y and ydot.
Header file for class IDA_Solver.
Base class for exceptions thrown by Cantera classes.
integer m_neq
Number of total equations in the system.
Wrapper for Sundials IDA solver.
virtual doublereal step(doublereal tout)
Take one internal step.
virtual void setStopTime(doublereal tstop)
Set the stop time.
virtual void correctInitial_Y_given_Yp(doublereal *y, doublereal *yp, doublereal tout)
Calculate consistent value of the starting solution given the starting solution derivatives.
virtual void setMaxNumSteps(int n)
Set the maximum number of time steps.
virtual void setBandedLinearSolver(int m_upper, int m_lower)
Set up the problem to use a band solver.
virtual doublereal solution(int k) const
the current value of solution component k.
N_Vector m_y
Current value of the solution vector.
virtual void setJacobianType(int formJac)
Set the form of the Jacobian.
virtual void correctInitial_YaYp_given_Yd(doublereal *y, doublereal *yp, doublereal tout)
Calculate consistent value of the algebraic constraints and derivatives at the start of the problem.
void * m_linsol
Sundials linear solver object.
int m_maxNonlinConvFails
Maximum number of nonlinear convergence failures.
virtual void setInitialStepSize(doublereal h0)
Set the initial step size.
virtual int solve(doublereal tout)
Step the system to a final value of the time.
int m_maxNonlinIters
Maximum number of nonlinear solver iterations at one solution.
SundialsContext m_sundials_ctx
SUNContext object for Sundials>=6.0.
IDA_Solver(ResidJacEval &f)
Constructor.
doublereal m_told
Value of the previous time.
virtual void setDenseLinearSolver()
Set up the problem to use a dense linear direct solver.
doublereal m_deltat
Value of deltaT for the current step.
int m_maxErrTestFails
maximum number of error test failures
virtual void setTolerances(doublereal reltol, doublereal *abstol)
Set error tolerances.
virtual void setMaxNonlinIterations(int n)
Set the maximum number of nonlinear iterations on a timestep.
doublereal m_tcurrent
Value of the current time.
int m_maxord
maximum time step order of the method
virtual doublereal getOutputParameter(int flag) const
Get the value of a solver-specific output parameter.
virtual void init(doublereal t0)
initialize.
int m_formJac
Form of the Jacobian.
doublereal m_told_old
Value of the previous, previous time.
virtual void setMaxNonlinConvFailures(int n)
Set the maximum number of nonlinear solver convergence failures.
virtual double getCurrentStepFromIDA()
Get the current step size from IDA via a call.
virtual doublereal derivative(int k) const
the current value of the derivative of solution component k.
doublereal m_h0
Value of the initial time step.
void * m_linsol_matrix
matrix used by Sundials
N_Vector m_ydot
Current value of the derivative of the solution vector.
doublereal m_t0
Initial value of the time.
int m_maxsteps
Maximum number of time steps allowed.
doublereal m_tstop
maximum time
int m_setSuppressAlg
If true, the algebraic variables don't contribute to error tolerances.
void * m_ida_mem
Pointer to the IDA memory for the problem.
A simple class to hold an array of parameter values and a pointer to an instance of a subclass of Res...
int nparams() const
Return the number of parameters in the calculation.
Wrappers for the function evaluators for Nonlinear solvers and Time steppers.
virtual int evalJacobianDP(const doublereal t, const doublereal delta_t, doublereal cj, const doublereal *const y, const doublereal *const ydot, doublereal *const *jacobianColPts, doublereal *const resid)
Calculate an analytical Jacobian and the residual at the current time and values.
virtual int evalResidNJ(const doublereal t, const doublereal delta_t, const doublereal *const y, const doublereal *const ydot, doublereal *const resid, const ResidEval_Type_Enum evalType=Base_ResidEval, const int id_x=-1, const doublereal delta_x=0.0)
Evaluate the residual function.
virtual int getInitialConditions(const doublereal t0, doublereal *const y, doublereal *const ydot)
Fill in the initial conditions.
Namespace for the Cantera kernel.
Contains declarations for string manipulation functions within Cantera.