/** * @file CVodeInt.cpp */ // Copyright 2001 California Institute of Technology #include "CVodeInt.h" using namespace std; // CVODE includes #include "../../ext/cvode/include/llnltyps.h" #include "../../ext/cvode/include/llnlmath.h" #include "../../ext/cvode/include/cvode.h" #include "../../ext/cvode/include/cvdense.h" #include "../../ext/cvode/include/cvdiag.h" #include "../../ext/cvode/include/cvspgmr.h" #include "../../ext/cvode/include/cvode.h" #include "cantera/base/stringUtils.h" extern "C" { /** * Function called by CVODE to evaluate ydot given y. The CVODE * integrator allows passing in a void* pointer to access * external data. This pointer is cast to a pointer to a instance * of class FuncEval. The equations to be integrated should be * specified by deriving a class from FuncEval that evaluates the * desired equations. * @ingroup odeGroup */ static void cvode_rhs(integer N, real t, N_Vector y, N_Vector ydot, void* f_data) { double* ydata = N_VDATA(y); double* ydotdata = N_VDATA(ydot); Cantera::FuncEval* f = (Cantera::FuncEval*)f_data; f->eval(t, ydata, ydotdata, NULL); } /** * Function called by CVODE to evaluate the Jacobian matrix. * (temporary) * @ingroup odeGroup */ static void cvode_jac(integer N, DenseMat J, RhsFn f, void* f_data, real t, N_Vector y, N_Vector fy, N_Vector ewt, real h, real uround, void* jac_data, long int* nfePtr, N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) { // get pointers to start of data double* ydata = N_VDATA(y); double* fydata = N_VDATA(fy); double* ewtdata = N_VDATA(ewt); double* ydot = N_VDATA(vtemp1); Cantera::FuncEval* func = (Cantera::FuncEval*)f_data; int i,j; double* col_j; double ysave, dy; for (j=0; j < N; j++) { col_j = (J->data)[j]; ysave = ydata[j]; dy = 1.0/ewtdata[j]; ydata[j] = ysave + dy; dy = ydata[j] - ysave; func->eval(t, ydata, ydot, NULL); for (i=0; i < N; i++) { col_j[i] = (ydot[i] - fydata[i])/dy; } ydata[j] = ysave; } } } namespace Cantera { CVodeInt::CVodeInt() : m_neq(0), m_cvode_mem(0), m_t0(0.0), m_y(0), m_abstol(0), m_type(DENSE+NOJAC), m_itol(0), m_method(BDF), m_iter(NEWTON), m_maxord(0), m_reltol(1.e-9), m_abstols(1.e-15), m_nabs(0), m_hmax(0.0), m_maxsteps(20000) { m_ropt.resize(OPT_SIZE,0.0); m_iopt = new long[OPT_SIZE]; fill(m_iopt, m_iopt+OPT_SIZE,0); } CVodeInt::~CVodeInt() { if (m_cvode_mem) { CVodeFree(m_cvode_mem); } if (m_y) { N_VFree(m_y); } if (m_abstol) { N_VFree(m_abstol); } delete[] m_iopt; } double& CVodeInt::solution(size_t k) { return N_VIth(m_y, int(k)); } double* CVodeInt::solution() { return N_VDATA(m_y); } void CVodeInt::setTolerances(double reltol, size_t n, double* abstol) { m_itol = 1; m_nabs = int(n); if (m_nabs != m_neq) { if (m_abstol) { N_VFree(m_abstol); } m_abstol = N_VNew(m_nabs, 0); } for (int i=0; i