/** * @file RxnRates.h * */ /* $Author$ * $Revision$ * $Date$ */ // Copyright 2001 California Institute of Technology #ifndef CT_RXNRATES_H #define CT_RXNRATES_H #include "reaction_defs.h" #include "ctexceptions.h" namespace Cantera { //! Arrhenius reaction rate type depends only on temperature /** * A reaction rate coefficient of the following form. * * \f[ * k_f = A T^b \exp (-E/RT) * \f] * */ class Arrhenius { public: //! return the rate coefficient type. static int type() { return ARRHENIUS_REACTION_RATECOEFF_TYPE; } //! Default constructor. Arrhenius() : m_logA(-1.0E300), m_b (0.0), m_E (0.0), m_A(0.0) {} //! Constructor with Arrhenius parameters specified with an array. Arrhenius(int csize, const doublereal* c) : m_b (c[1]), m_E (c[2]), m_A (c[0]) { if (m_A <= 0.0) { m_logA = -1.0E300; } else { m_logA = log(m_A); } } /// Constructor. /// @param A pre-exponential. The unit system is /// (kmol, m, s). The actual units depend on the reaction /// order and the dimensionality (surface or bulk). /// @param b Temperature exponent. Non-dimensional. /// @param E Activation energy in temperature units. Kelvin. Arrhenius(doublereal A, doublereal b, doublereal E) : m_b (b), m_E (E), m_A (A) { if (m_A <= 0.0) { m_logA = -1.0E300; } else { m_logA = log(m_A); } } //! Update concentration-dependent parts of the rate coefficient. /*! * For this class, there are no * concentration-dependent parts, so this method does nothing. */ void update_C(const doublereal* c) { } /** * Update the value of the logarithm of the rate constant. * * Note, this function should never be called for negative A values. * If it does then it will produce a negative overflow result, and * a zero net forwards reaction rate, instead of a negative reaction * rate constant that is the expected result. */ doublereal update(doublereal logT, doublereal recipT) const { return m_logA + m_b*logT - m_E*recipT; } /** * Update the value the rate constant. * * This function returns the actual value of the rate constant. * It can be safely called for negative values of the pre-exponential * factor. */ doublereal updateRC(doublereal logT, doublereal recipT) const { return m_A * exp(m_b*logT - m_E*recipT); } void writeUpdateRHS(std::ostream& s) const { s << " exp(" << m_logA; if (m_b != 0.0) s << " + " << m_b << " * tlog"; if (m_E != 0.0) s << " - " << m_E << " * rt"; s << ");" << std::endl; } doublereal activationEnergy_R() const { return m_E; } static bool alwaysComputeRate() { return false;} protected: doublereal m_logA, m_b, m_E, m_A; }; class ArrheniusSum { public: static int type() { return ARRHENIUS_SUM_REACTION_RATECOEFF_TYPE; } ArrheniusSum() : m_nterms(0) {} void addArrheniusTerm(doublereal A, doublereal b, doublereal E) { if (A > 0.0) { m_terms.push_back(Arrhenius(A, b, E)); m_sign.push_back(1); } else if (A < 0.0) { m_terms.push_back(Arrhenius(-A, b, E)); m_sign.push_back(-1); } m_nterms++; } void update_C(const doublereal* c) {} /** * Update the value of the logarithm of the rate constant. * */ doublereal update(doublereal logT, doublereal recipT) const { int n; doublereal f, fsum = 0.0; for (n = 0; n < m_nterms; n++) { f = m_terms[n].updateRC(logT, recipT); fsum += m_sign[n]*f; } return log(fsum); } /** * Update the value the rate constant. * * This function returns the actual value of the rate constant. * It can be safely called for negative values of the pre-exponential * factor. */ doublereal updateRC(doublereal logT, doublereal recipT) const { int n; doublereal f, fsum = 0.0; for (n = 0; n < m_nterms; n++) { f = m_terms[n].updateRC(logT, recipT); fsum += m_sign[n]*f; } return fsum; } void writeUpdateRHS(std::ostream& s) const { ; } static bool alwaysComputeRate() { return false;} protected: std::vector m_terms; vector_int m_sign; int m_nterms; }; /** * An Arrhenius rate with coverage-dependent terms. */ class SurfaceArrhenius { public: static int type() { return ARRHENIUS_REACTION_RATECOEFF_TYPE; } SurfaceArrhenius() : m_logA(-1.0E300), m_b (0.0), m_E (0.0), m_A(0.0), m_acov(0.0), m_ecov(0.0), m_mcov(0.0), m_ncov(0), m_nmcov(0) { } SurfaceArrhenius( int csize, const doublereal* c ) : m_b (c[1]), m_E (c[2]), m_A (c[0]), m_acov(0.0), m_ecov(0.0), m_mcov(0.0), m_ncov(0), m_nmcov(0) { if (m_A <= 0.0) { m_logA = -1.0E300; } else { m_logA = log(c[0]); } if (csize >= 7) { for (int n = 3; n < csize-3; n += 4) { addCoverageDependence(int(c[n]), c[n+1], c[n+2], c[n+3]); } } } void addCoverageDependence(int k, doublereal a, doublereal m, doublereal e) { m_ncov++; m_sp.push_back(k); m_ac.push_back(a); m_ec.push_back(e); if (m != 0.0) { m_msp.push_back(k); m_mc.push_back(m); m_nmcov++; } } void update_C(const doublereal* theta) { m_acov = 0.0; m_ecov = 0.0; m_mcov = 0.0; int n, k; doublereal th; for (n = 0; n < m_ncov; n++) { k = m_sp[n]; m_acov += m_ac[n] * theta[k]; m_ecov += m_ec[n] * theta[k]; } for (n = 0; n < m_nmcov; n++) { k = m_msp[n]; // changed n to k, dgg 1/22/04 th = fmaxx(theta[k], Tiny); // th = fmaxx(theta[n], Tiny); m_mcov += m_mc[n]*log(th); } } /** * Update the value of the logarithm of the rate constant. * * This calculation is not safe for negative values of * the preexponential. */ doublereal update(doublereal logT, doublereal recipT) const { return m_logA + m_acov + m_b*logT - (m_E + m_ecov)*recipT + m_mcov; } /** * Update the value the rate constant. * * This function returns the actual value of the rate constant. * It can be safely called for negative values of the pre-exponential * factor. */ doublereal updateRC(doublereal logT, doublereal recipT) const { return m_A * exp(m_acov + m_b*logT - (m_E + m_ecov)*recipT + m_mcov); } doublereal activationEnergy_R() const { return m_E + m_ecov; } static bool alwaysComputeRate() { return true;} protected: doublereal m_logA, m_b, m_E, m_A; doublereal m_acov, m_ecov, m_mcov; vector_int m_sp, m_msp; vector_fp m_ac, m_ec, m_mc; int m_ncov, m_nmcov; }; #ifdef INCL_TST class TST { public: static int type(){ return TSTRATE; } TST() {} TST( const vector_fp& c ) { m_b.resize(10); copy(c.begin(), c.begin() + 10, m_b.begin()); m_k = int(c[10]); } void update_C(const vector_fp& c) { doublereal ck = c[m_k]; delta_s0 = m_b[0] + m_b[1]*ck + m_b[2]*ck*ck; delta_e0 = m_b[5] + m_b[6]*ck + m_b[7]*ck*ck; } doublereal update(doublereal logT, doublereal recipT) const { doublereal delta_s = delta_s0*(1.0 + m_b[3]*logT + m_b[4]*recipT); doublereal delta_E = delta_e0*(1.0 + m_b[8]*logT + m_b[9]*recipT); return logBoltz_Planck + logT + delta_s - delta_E*recipT; } doublereal updateRC(doublereal logT, doublereal recipT) const { doublereal lres = update(logT, recipT); return exp(lres); } void writeUpdateRHS(std::ostream& s) const {} protected: doublereal delta_s0, delta_e0; int m_k; vector_fp m_b; }; #endif //! Arrhenius reaction rate type depends only on temperature /** * A reaction rate coefficient of the following form. * * \f[ * k_f = A T^b \exp (-E/RT) * \f] * */ class ExchangeCurrent { public: //! return the rate coefficient type. static int type() { return EXCHANGE_CURRENT_REACTION_RATECOEFF_TYPE; } //! Default constructor. ExchangeCurrent() : m_logA(-1.0E300), m_b (0.0), m_E (0.0), m_A(0.0) {} //! Constructor with Arrhenius parameters specified with an array. ExchangeCurrent(int csize, const doublereal* c) : m_b (c[1]), m_E (c[2]), m_A (c[0]) { if (m_A <= 0.0) { m_logA = -1.0E300; } else { m_logA = log(m_A); } } /// Constructor. /// @param A pre-exponential. The unit system is /// (kmol, m, s). The actual units depend on the reaction /// order and the dimensionality (surface or bulk). /// @param b Temperature exponent. Non-dimensional. /// @param E Activation energy in temperature units. Kelvin. ExchangeCurrent(doublereal A, doublereal b, doublereal E) : m_b (b), m_E (E), m_A (A) { if (m_A <= 0.0) { m_logA = -1.0E300; } else { m_logA = log(m_A); } } //! Update concentration-dependent parts of the rate coefficient. /*! * For this class, there are no * concentration-dependent parts, so this method does nothing. */ void update_C(const doublereal* c) { } /** * Update the value of the logarithm of the rate constant. * * Note, this function should never be called for negative A values. * If it does then it will produce a negative overflow result, and * a zero net forwards reaction rate, instead of a negative reaction * rate constant that is the expected result. */ doublereal update(doublereal logT, doublereal recipT) const { return m_logA + m_b*logT - m_E*recipT; } /** * Update the value the rate constant. * * This function returns the actual value of the rate constant. * It can be safely called for negative values of the pre-exponential * factor. */ doublereal updateRC(doublereal logT, doublereal recipT) const { return m_A * exp(m_b*logT - m_E*recipT); } void writeUpdateRHS(std::ostream& s) const { s << " exp(" << m_logA; if (m_b != 0.0) s << " + " << m_b << " * tlog"; if (m_E != 0.0) s << " - " << m_E << " * rt"; s << ");" << std::endl; } doublereal activationEnergy_R() const { return m_E; } static bool alwaysComputeRate() { return false;} protected: doublereal m_logA, m_b, m_E, m_A; }; // class LandauTeller { // public: // static int type(){ return LANDAUTELLER; } // LandauTeller(){} // LandauTeller( const vector_fp& c ) : m_c(c) { m_c[0] = log(c[0]); } // doublereal update(doublereal logT, doublereal recipT) const { // return m_c[0] + m_c[1]*tt[1] - m_c[2]*tt[2] // + m_c[3]*tt[3] + m_c[4]*tt[4]; // } // //void writeUpdateRHS(ostream& s) const { // // s << exp(m_logA); // // s << " * exp("; // // if (m_b != 0.0) s << m_b << " * tlog"; // // if (m_E != 0.0) s << " - " << m_E << " * rt"; // // if (m_E != 0.0) s << " - " << m_E << " * rt"; // // s << ");" << endl; // // } // //} // protected: // doublereal m_logA, m_b, m_E; // }; //} } #endif