moved files to kinetics subdirectory

This commit is contained in:
Dave Goodwin 2007-05-04 14:27:23 +00:00
parent 9581e8db9a
commit 0762b467c2
35 changed files with 11909 additions and 0 deletions

View file

@ -0,0 +1,532 @@
/**
* @file EdgeKinetics.cpp
*
*/
// Copyright 2002 California Institute of Technology
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "EdgeKinetics.h"
#include "SurfPhase.h"
#include "ReactionData.h"
//#include "StoichManager.h"
#include "RateCoeffMgr.h"
#include <iostream>
using namespace std;
namespace Cantera {
//////////////////////////////////////////////////////////////////
/**
* Construct an empty EdgeKinetics reaction mechanism.
*/
EdgeKinetics::
EdgeKinetics() :
Kinetics(),
m_kk(0),
m_redo_rates(false),
m_nirrev(0),
m_nrev(0),
m_finalized(false),
m_has_electrochem_rxns(false)
{
m_kdata = new EdgeKineticsData;
m_kdata->m_temp = 0.0;
}
/**
* Destructor
*/
EdgeKinetics::
~EdgeKinetics(){
delete m_kdata;
}
/**
* Update properties that depend on temperature
*
*/
void EdgeKinetics::
_update_rates_T() {
_update_rates_phi();
doublereal T = thermo(surfacePhaseIndex()).temperature();
if (T != m_kdata->m_temp || m_redo_rates) {
m_kdata->m_logtemp = log(T);
m_rates.update(T, m_kdata->m_logtemp, DATA_PTR(m_kdata->m_rfn));
if (m_has_electrochem_rxns)
applyButlerVolmerCorrection(DATA_PTR(m_kdata->m_rfn));
m_kdata->m_temp = T;
updateKc();
m_kdata->m_ROP_ok = false;
m_redo_rates = false;
}
}
void EdgeKinetics::
_update_rates_phi() {
int np = nPhases();
for (int n = 0; n < np; n++) {
if (thermo(n).electricPotential() != m_phi[n]) {
m_phi[n] = thermo(n).electricPotential();
m_redo_rates = true;
}
}
}
/**
* Update properties that depend on concentrations. This method
* fills out the array of generalized concentrations by calling
* method getActivityConcentrations for each phase, which classes
* representing phases should overload to return the appropriate
* quantities.
*/
void EdgeKinetics::
_update_rates_C() {
int n;
//m_rates.update(m_kdata->m_temp,
// m_kdata->m_logtemp, m_kdata->m_rfn.begin());
int np = nPhases();
for (n = 0; n < np; n++) {
thermo(n).getActivityConcentrations(DATA_PTR(m_conc) + m_start[n]);
}
m_kdata->m_ROP_ok = false;
}
/**
* Update the equilibrium constants in molar units for all
* reversible reactions. Irreversible reactions have their
* equilibrium constant set to zero.
*/
void EdgeKinetics::updateKc() {
int i, irxn;
vector_fp& m_rkc = m_kdata->m_rkcn;
fill(m_rkc.begin(), m_rkc.end(), 0.0);
if (m_nrev > 0) {
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
for (n = 0; n < np; n++) {
thermo(n).getStandardChemPotentials(DATA_PTR(m_mu0) + m_start[n]);
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
m_mu0[ik] -= rt*thermo(n).logStandardConc(k);
m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
ik++;
}
}
// compute Delta mu^0 for all reversible reactions
m_reactantStoich.decrementReactions(DATA_PTR(m_mu0),
DATA_PTR(m_rkc));
m_revProductStoich.incrementReactions(DATA_PTR(m_mu0),
DATA_PTR(m_rkc));
for (i = 0; i < m_nrev; i++) {
irxn = m_revindex[i];
m_rkc[irxn] = exp(m_rkc[irxn]*rrt);
}
for (i = 0; i != m_nirrev; ++i) {
m_rkc[ m_irrev[i] ] = 0.0;
}
}
}
void EdgeKinetics::checkPartialEquil() {
int i, irxn;
vector_fp dmu(nTotalSpecies(), 0.0);
vector_fp rmu(nReactions(), 0.0);
if (m_nrev > 0) {
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
for (n = 0; n < np; n++) {
thermo(n).getChemPotentials(DATA_PTR(dmu) + m_start[n]);
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
dmu[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
cout << thermo(n).speciesName(k) << " " << dmu[ik] << endl;
ik++;
}
}
// compute Delta mu^ for all reversible reactions
m_reactantStoich.decrementReactions(DATA_PTR(dmu), DATA_PTR(rmu));
m_revProductStoich.incrementReactions(DATA_PTR(dmu), DATA_PTR(rmu));
for (i = 0; i < m_nrev; i++) {
irxn = m_revindex[i];
cout << "Reaction " << irxn << " " << exp(rmu[irxn]*rrt) << endl;
}
}
}
/**
* Get the equilibrium constants of all reactions, whether
* reversible or not.
*/
void EdgeKinetics::getEquilibriumConstants(doublereal* kc) {
int i;
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
for (n = 0; n < np; n++) {
thermo(n).getStandardChemPotentials(DATA_PTR(m_mu0) + m_start[n]);
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
m_mu0[ik] -= rt*thermo(n).logStandardConc(k);
m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
ik++;
}
}
fill(kc, kc + m_ii, 0.0);
m_reactantStoich.decrementReactions(DATA_PTR(m_mu0), kc);
m_revProductStoich.incrementReactions(DATA_PTR(m_mu0), kc);
m_irrevProductStoich.incrementReactions(DATA_PTR(m_mu0), kc);
for (i = 0; i < m_ii; i++) {
kc[i] = exp(-kc[i]*rrt);
}
}
/**
* For reactions that transfer charge across a potential difference,
* the activation energies are modified by the potential difference.
* (see, for example, Baird and Falkner, "Electrochemical Methods").
* This method applies this correction.
*/
void EdgeKinetics::applyButlerVolmerCorrection(doublereal* kf) {
int i;
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
// compute the electrical potential energy of each species
for (n = 0; n < np; n++) {
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
m_pot[ik] = Faraday*thermo(n).charge(k)*m_phi[n];
ik++;
}
}
// compute the change in electrical potential energy for each
// reaction. This will only be non-zero if a potential
// difference is present.
fill(DATA_PTR(m_rwork), DATA_PTR(m_rwork) + m_ii, 0.0);
m_reactantStoich.decrementReactions(DATA_PTR(m_pot), DATA_PTR(m_rwork));
m_revProductStoich.incrementReactions(DATA_PTR(m_pot), DATA_PTR(m_rwork));
m_irrevProductStoich.incrementReactions(DATA_PTR(m_pot), DATA_PTR(m_rwork));
// modify the reaction rates. Only modify those with a
// non-zero activation energy, and do not decrease the
// activation energy below zero.
doublereal ea, eamod;
int nct = m_beta.size();
int irxn;
for (i = 0; i < nct; i++) {
irxn = m_ctrxn[i];
eamod = m_beta[i]*m_rwork[irxn];
//cout << "i, beta = " << i << " " << m_beta[i] << endl;
if (eamod != 0.0 && m_E[i] != 0.0) {
ea = GasConstant * m_E[i];
if (eamod + ea < 0.0) {
writelog("Warning: act energy mod too large");
eamod = -ea;
}
kf[irxn] *= exp(-eamod*rrt);
}
}
}
/**
* Update the rates of progress of the reactions in the reaciton
* mechanism. This routine operates on internal data.
*/
void EdgeKinetics::updateROP() {
_update_rates_T();
_update_rates_C();
if (m_kdata->m_ROP_ok) return;
const vector_fp& rf = m_kdata->m_rfn;
const vector_fp& m_rkc = m_kdata->m_rkcn;
array_fp& ropf = m_kdata->m_ropf;
array_fp& ropr = m_kdata->m_ropr;
array_fp& ropnet = m_kdata->m_ropnet;
// copy rate coefficients into ropf
copy(rf.begin(), rf.end(), ropf.begin());
// multiply by perturbation factor
multiply_each(ropf.begin(), ropf.end(), m_perturb.begin());
// copy the forward rates to the reverse rates
copy(ropf.begin(), ropf.end(), ropr.begin());
// for reverse rates computed from thermochemistry, multiply
// the forward rates copied into m_ropr by the reciprocals of
// the equilibrium constants
multiply_each(ropr.begin(), ropr.end(), m_rkc.begin());
// multiply ropf by concentration products
m_reactantStoich.multiply(DATA_PTR(m_conc), DATA_PTR(ropf));
// for reversible reactions, multiply ropr by concentration
// products
m_revProductStoich.multiply(DATA_PTR(m_conc), DATA_PTR(ropr));
// do global reactions
//m_globalReactantStoich.power(DATA_PTR(m_conc), ropf.begin());
for (int j = 0; j != m_ii; ++j) {
ropnet[j] = ropf[j] - ropr[j];
}
m_kdata->m_ROP_ok = true;
}
/**
* Add a single reaction to the mechanism. This routine
* must be called after init() and before finalize().
* This function branches on the types of reactions allowed
* by the interfaceKinetics manager in order to install
* the reaction correctly in the manager.
* The manager allows the following reaction types
* Elementary
* Surface
* Global
* There is no difference between elementary and surface
* reactions.
*/
void EdgeKinetics::
addReaction(const ReactionData& r) {
int nr = r.reactants.size();
// a global reaction is idnetified as one with
// a reactant stoichiometric coefficient not equal
// to the molecularity for some reactant
bool isglobal = false;
for (int n = 0; n < nr; n++) {
if (r.rstoich[n] != int(r.order[n])) {
isglobal = true; break;
}
}
if (isglobal)
addGlobalReaction(r);
else
addElementaryReaction(r);
installReagents( r );
installGroups(reactionNumber(), r.rgroups, r.pgroups);
incrementRxnCount();
m_rxneqn.push_back(r.equation);
}
void EdgeKinetics::
addElementaryReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
vector_fp rp = r.rateCoeffParameters;
// coverage dependence
int ncov = r.cov.size();
for (int m = 0; m < ncov; m++) rp.push_back(r.cov[m]);
iloc = m_rates.install( reactionNumber(), r.rateCoeffType, rp.size(),
DATA_PTR(rp) );
// store activation energy
if (r.beta > 0.0) {
m_has_electrochem_rxns = true;
m_E.push_back(r.rateCoeffParameters[2]);
m_beta.push_back(r.beta);
m_ctrxn.push_back(reactionNumber());
}
// add constant term to rate coeff value vector
m_kdata->m_rfn.push_back(r.rateCoeffParameters[0]);
registerReaction( reactionNumber(), ELEMENTARY_RXN, iloc);
}
void EdgeKinetics::
addGlobalReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
vector_fp rp = r.rateCoeffParameters;
int ncov = r.cov.size();
for (int m = 0; m < ncov; m++) rp.push_back(r.cov[m]);
iloc = m_rates.install( reactionNumber(),
r.rateCoeffType, rp.size(),
DATA_PTR(rp) );
// add constant term to rate coeff value vector
m_kdata->m_rfn.push_back(r.rateCoeffParameters[0]);
int nr = r.order.size();
vector_fp ordr(nr);
for (int n = 0; n < nr; n++) {
ordr[n] = r.order[n] - r.rstoich[n];
}
m_globalReactantStoich.add( reactionNumber(),
r.reactants, ordr);
registerReaction( reactionNumber(), GLOBAL_RXN, iloc);
}
void EdgeKinetics::installReagents(const ReactionData& r) {
m_kdata->m_ropf.push_back(0.0); // extend by one for new rxn
m_kdata->m_ropr.push_back(0.0);
m_kdata->m_ropnet.push_back(0.0);
int n, ns, m;
doublereal nsFlt;
int rnum = reactionNumber();
vector_int rk;
int nr = r.reactants.size();
for (n = 0; n < nr; n++) {
nsFlt = r.rstoich[n];
ns = (int) nsFlt;
if ((doublereal) ns != nsFlt) {
if (ns < 1) ns = 1;
}
m_rrxn[r.reactants[n]][rnum] = ns;
for (m = 0; m < ns; m++) {
rk.push_back(r.reactants[n]);
}
}
m_reactants.push_back(rk);
vector_int pk;
int np = r.products.size();
for (n = 0; n < np; n++) {
nsFlt = r.pstoich[n];
ns = (int) nsFlt;
if ((doublereal) ns != nsFlt) {
if (ns < 1) ns = 1;
}
m_prxn[r.products[n]][rnum] = ns;
for (m = 0; m < ns; m++) {
pk.push_back(r.products[n]);
}
}
m_products.push_back(pk);
m_kdata->m_rkcn.push_back(0.0);
m_reactantStoich.add( reactionNumber(), rk);
if (r.reversible) {
m_revProductStoich.add(reactionNumber(), pk);
//m_dn.push_back(pk.size() - rk.size());
m_revindex.push_back(reactionNumber());
m_nrev++;
}
else {
m_irrevProductStoich.add(reactionNumber(), pk);
//m_dn.push_back(pk.size() - rk.size());
m_irrev.push_back( reactionNumber() );
m_nirrev++;
}
}
void EdgeKinetics::installGroups(int irxn,
const vector<grouplist_t>& r, const vector<grouplist_t>& p) {
if (!r.empty()) {
m_rgroups[reactionNumber()] = r;
m_pgroups[reactionNumber()] = p;
}
}
/**
* Prepare the class for the addition of reactions. This function
* must be called after instantiation of the class, but before
* any reactions are actually added to the mechanism.
* This function calculates m_kk the number of species in all
* phases participating in the reaction mechanism. We don't know
* m_kk previously, before all phases have been added.
*/
void EdgeKinetics::init() {
int n;
m_kk = 0;
int np = nPhases();
for (n = 0; n < np; n++) {
m_kk += thermo(n).nSpecies();
}
m_rrxn.resize(m_kk);
m_prxn.resize(m_kk);
m_conc.resize(m_kk);
m_mu0.resize(m_kk);
m_pot.resize(m_kk, 0.0);
m_phi.resize(np, 0.0);
}
/**
* Finish adding reactions and prepare for use. This function
* must be called after all reactions are entered into the mechanism
* and before the mechanism is used to calculate reaction rates.
*
* Here, we resize work arrays based on the number of reactions,
* since we don't know this number up to now.
*/
void EdgeKinetics::finalize() {
m_rwork.resize(nReactions());
m_finalized = true;
}
bool EdgeKinetics::ready() const {
return (m_finalized);
}
}

View file

@ -0,0 +1,392 @@
/**
* @file EdgeKinetics.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_EDGEKINETICS_H
#define CT_EDGEKINETICS_H
#include <fstream>
#include <math.h>
#include <map>
#include <stdlib.h>
#include "mix_defs.h"
#include "Kinetics.h"
#include "utilities.h"
#include "RateCoeffMgr.h"
#include "StoichManager.h"
namespace Cantera {
// forward references
class ReactionData;
class EdgeKineticsData;
class ThermoPhase;
class SurfPhase;
class ImplicitSurfChem;
/**
* Holds mechanism-specific data.
*/
class EdgeKineticsData {
public:
EdgeKineticsData() :
m_ROP_ok(false),
m_temp(0.0), m_logtemp(0.0)
{}
virtual ~EdgeKineticsData(){}
doublereal m_logp0, m_logc0;
array_fp m_ropf, m_ropr, m_ropnet;
//array_fp m_rfn_low, m_rfn_high;
bool m_ROP_ok;
doublereal m_temp, m_logtemp;
vector_fp m_rfn;
vector_fp m_rkcn;
};
class EdgeKinetics : public Kinetics {
public:
/**
* Constructor
*
*/
EdgeKinetics();
/// Destructor.
virtual ~EdgeKinetics();
/**
* Identifies the subclass of the Kinetics manager type.
* These are listed in mix_defs.h.
*/
virtual int ID() { return cEdgeKinetics; }
/**
* Identifies the subclass of the Kinetics manager type.
* These are listed in mix_defs.h.
*/
virtual int type() { return cEdgeKinetics; }
/**
* Set the electric potential in the nth phase
*
* @param n phase Index in this kinetics object.
* @param V Electric potential (volts)
*/
void setElectricPotential(int n, doublereal V) {
thermo(n).setElectricPotential(V);
m_redo_rates = true;
}
/**
* @name Reaction Rates Of Progress
*/
//@{
/**
* Forward rates of progress.
* Return the forward rates of progress in array fwdROP, which
* must be dimensioned at least as large as the total number
* of reactions.
* Units are kmol/m2/s
*/
virtual void getFwdRatesOfProgress(doublereal* fwdROP) {
updateROP();
std::copy(m_kdata->m_ropf.begin(), m_kdata->m_ropf.end(), fwdROP);
}
/**
* Reverse rates of progress.
* Return the reverse rates of progress in array revROP, which
* must be dimensioned at least as large as the total number
* of reactions.
* Units are kmol/m2/s
*/
virtual void getRevRatesOfProgress(doublereal* revROP) {
updateROP();
std::copy(m_kdata->m_ropr.begin(), m_kdata->m_ropr.end(), revROP);
}
/**
* Net rates of progress. Return the net (forward - reverse)
* rates of progress in array netROP, which must be
* dimensioned at least as large as the total number of
* reactions.
* Units are kmol/m2/s
*/
virtual void getNetRatesOfProgress(doublereal* netROP) {
updateROP();
std::copy(m_kdata->m_ropnet.begin(), m_kdata->m_ropnet.end(), netROP);
}
/**
* Equilibrium constants. Return the equilibrium constants of
* the reactions in concentration units in array kc, which
* must be dimensioned at least as large as the total number
* of reactions.
*/
virtual void getEquilibriumConstants(doublereal* kc);
//@}
/**
* @name Species Production Rates
*/
//@{
/**
* Species creation rates [kmol/m^2/s]. Return the species
* creation rates in array cdot, which must be
* dimensioned at least as large as the total number of
* species in all phases of the kinetics
* model
*
*/
virtual void getCreationRates(doublereal* cdot) {
updateROP();
std::fill(cdot, cdot + m_kk, 0.0);
m_revProductStoich.incrementSpecies(
&m_kdata->m_ropf[0], cdot);
m_irrevProductStoich.incrementSpecies(
&m_kdata->m_ropf[0], cdot);
m_reactantStoich.incrementSpecies(
&m_kdata->m_ropr[0], cdot);
}
/**
* Species destruction rates [kmol/m^2/s]. Return the species
* destruction rates in array ddot, which must be
* dimensioned at least as large as the total number of
* species in all phases of the kinetics
* model
*
*/
virtual void getDestructionRates(doublereal* ddot) {
updateROP();
std::fill(ddot, ddot + m_kk, 0.0);
m_revProductStoich.incrementSpecies(
&m_kdata->m_ropr[0], ddot);
m_reactantStoich.incrementSpecies(
&m_kdata->m_ropf[0], ddot);
}
/**
* Species net production rates [kmol/m^2/s]. Return the species
* net production rates (creation - destruction) in array
* wdot, which must be dimensioned at least as large as the
* total number of species in all phases of the kinetics
* model
*/
virtual void getNetProductionRates(doublereal* net) {
updateROP();
std::fill(net, net + m_kk, 0.0);
m_revProductStoich.incrementSpecies(
&m_kdata->m_ropnet[0], net);
m_irrevProductStoich.incrementSpecies(
&m_kdata->m_ropnet[0], net);
m_reactantStoich.decrementSpecies(
&m_kdata->m_ropnet[0], net);
}
//@}
/**
* @name Reaction Mechanism Informational Query Routines
*/
//@{
/**
* Stoichiometric coefficient of species k as a reactant in
* reaction i.
*/
virtual doublereal reactantStoichCoeff(int k, int i) const {
return m_rrxn[k][i];
}
/**
* Stoichiometric coefficient of species k as a product in
* reaction i.
*/
virtual doublereal productStoichCoeff(int k, int i) const {
return m_prxn[k][i];
}
/**
* Flag specifying the type of reaction. The legal values and
* their meaning are specific to the particular kinetics
* manager.
*/
virtual int reactionType(int i) const {
return m_index[i].first;
}
/**
* True if reaction i has been declared to be reversible. If
* isReversible(i) is false, then the reverse rate of progress
* for reaction i is always zero.
*/
virtual bool isReversible(int i) {
if (std::find(m_revindex.begin(), m_revindex.end(), i)
< m_revindex.end()) return true;
else return false;
}
/**
* Return a string representing the reaction.
*/
virtual std::string reactionString(int i) const {
return m_rxneqn[i];
}
//@}
/**
* @name Reaction Mechanism Construction
*/
//@{
/**
* Prepare the class for the addition of reactions. This function
* must be called after instantiation of the class, but before
* any reactions are actually added to the mechanism.
* This function calculates m_kk the number of species in all
* phases participating in the reaction mechanism. We don't know
* m_kk previously, before all phases have been added.
*/
virtual void init();
/**
* Add a single reaction to the mechanism.
*/
virtual void addReaction(const ReactionData& r);
/**
* Finish adding reactions and prepare for use. This function
* must be called after all reactions are entered into the mechanism
* and before the mechanism is used to calculate reaction rates.
*/
virtual void finalize();
virtual bool ready() const;
void updateROP();
const std::vector<grouplist_t>& reactantGroups(int i)
{ return m_rgroups[i]; }
const std::vector<grouplist_t>& productGroups(int i)
{ return m_pgroups[i]; }
void _update_rates_T();
void _update_rates_phi();
void _update_rates_C();
void checkPartialEquil();
protected:
/**
* m_kk here is the number of species in all of the phases
* that participate in the kinetics mechanism.
*/
int m_kk;
Rate1<SurfaceArrhenius> m_rates;
//Rate1<Arrhenius> m_rates;
bool m_redo_rates;
/**
* Vector of information about reactions in the
* mechanism.
* The key is the reaction index (0 < i < m_ii).
* The first pair is the reactionType of the reaction.
* The second pair is ...
*/
mutable std::map<int, std::pair<int, int> > m_index;
std::vector<int> m_irrev;
StoichManagerN m_reactantStoich;
StoichManagerN m_revProductStoich;
StoichManagerN m_irrevProductStoich;
StoichManagerN m_globalReactantStoich;
int m_nirrev;
/**
* Number of reversible reactions in the mechanism
*/
int m_nrev;
std::map<int, std::vector<grouplist_t> > m_rgroups;
std::map<int, std::vector<grouplist_t> > m_pgroups;
std::vector<int> m_rxntype;
mutable std::vector<std::map<int, doublereal> > m_rrxn;
mutable std::vector<std::map<int, doublereal> > m_prxn;
vector_int m_revindex;
std::vector<std::string> m_rxneqn;
/**
* Temporary data storage used in calculating the rates of
* of reactions.
*/
EdgeKineticsData* m_kdata;
/**
* An array of generalized concentrations
* \f$ C_k \f$ that are defined such that \f$ a_k = C_k /
* C^0_k, \f$ where \f$ C^0_k \f$ is a standard concentration/
* These generalized concentrations are used
* by this kinetics manager class to compute the forward and
* reverse rates of elementary reactions. The "units" for the
* concentrations of each phase depend upon the implementation
* of kinetics within that phase.
* The order of the species within the vector is based on
* the order of listed ThermoPhase objects in the class, and the
* order of the species within each ThermoPhase class.
*/
vector_fp m_conc;
vector_fp m_mu0;
vector_fp m_phi;
vector_fp m_pot;
vector_fp m_rwork;
vector_fp m_E;
vector_fp m_beta;
vector_int m_ctrxn;
private:
int reactionNumber(){ return m_ii;}
void addElementaryReaction(const ReactionData& r);
void addGlobalReaction(const ReactionData& r);
void installReagents(const ReactionData& r);
void installGroups(int irxn, const std::vector<grouplist_t>& r,
const std::vector<grouplist_t>& p);
void updateKc();
void registerReaction(int rxnNumber, int type, int loc) {
m_index[rxnNumber] = std::pair<int, int>(type, loc);
}
void applyButlerVolmerCorrection(doublereal* kf);
bool m_finalized;
bool m_has_electrochem_rxns;
};
}
#endif

View file

@ -0,0 +1,81 @@
/**
* @file Enhanced3BConc.h
*/
/* $Author$
* $Date$
* $Revision$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_ENH_CONC_H
#define CT_ENH_CONC_H
#include <map>
namespace Cantera {
/**
* Computes enhanced third-body concentrations.
* @see GasKinetics
*/
class Enhanced3BConc {
public:
Enhanced3BConc() : m_n (0), m_deflt (1.0) {}
Enhanced3BConc(int n, const std::map<int, doublereal>& enhanced,
doublereal deflt = 1.0) {
std::map<int, doublereal>::const_iterator iter;
for (iter = enhanced.begin(); iter != enhanced.end(); ++iter) {
m_index.push_back( iter->first );
m_eff.push_back( iter->second - deflt);
}
m_deflt = deflt;
m_n = n;
}
Enhanced3BConc(int n, const vector_int& e_index,
const vector_fp& efficiencies, doublereal deflt = 1.0)
: m_index (e_index), m_eff (efficiencies) {
int i;
m_n = n;
m_deflt = deflt;
for (i = 0; i < m_n; i++) {
m_eff[i] -= m_deflt;
}
}
doublereal update(const vector_fp& c, doublereal ctot) const {
int i;
doublereal sum = 0.0;
for (i = 0; i < m_n; i++) {
sum += m_eff[i] * c[m_index[i]];
}
return m_deflt * ctot + sum;
}
void getEfficiencies(vector_fp& eff) const {
int i;
for (i = 0; i < m_n; i++) {
eff[m_index[i]] = m_eff[i] + m_deflt;
}
}
private:
int m_n;
vector_int m_index;
vector_fp m_eff;
doublereal m_deflt;
};
}
#endif

View file

@ -0,0 +1,288 @@
/**
* @file FalloffFactory.cpp
*/
/* $Author$
* $Date$
* $Revision$
*/
// Copyright 2001 California Institute of Technology
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include <math.h>
#include "FalloffFactory.h"
namespace Cantera {
FalloffFactory* FalloffFactory::s_factory = 0;
/**
* The 3-parameter Troe falloff parameterization.
* This parameterization is
* defined by
* \f[ F = F_{cent}^{1/(1 + f_1^2)} \f]
* where
* \f[ F_{cent} = (1 - A)\exp(-T/T_3) + A \exp(-T/T_1) \f]
* \f[ f_1 = (\log_{10} P_r + C) / \left(N - 0.14
* (\log_{10} P_r + C)\right) \f]
* \f[ C = -0.4 - 0.67 \log_{10} F_{cent} \f]
* \f[ N = 0.75 - 1.27 \log_{10} F_{cent} \f]
*/
class Troe3 : public Falloff {
public:
/// Default constructor.
Troe3() : m_a (0.0), m_rt3 (0.0), m_rt1 (0.0) {}
// Destructor. Does nothing.
virtual ~Troe3() {}
/**
* Initialize.
* @param c Coefficient vector of length 3,
* with entries \f$ (A, T_3, T_1) \f$
*/
virtual void init(const vector_fp& c) {
m_a = c[0];
m_rt3 = 1.0/c[1];
m_rt1 = 1.0/c[2];
}
virtual void updateTemp(doublereal T, workPtr work) const {
doublereal Fcent = (1.0 - m_a) * exp(- T * m_rt3 )
+ m_a * exp(- T * m_rt1 );
*work = log10( fmaxx( Fcent, SmallNumber ) );
}
virtual doublereal F(doublereal pr, const_workPtr work) const {
doublereal lpr,f1,lgf, cc, nn;
lpr = log10( fmaxx(pr,SmallNumber) );
cc = -0.4 - 0.67 * (*work);
nn = 0.75 - 1.27 * (*work);
f1 = ( lpr + cc )/ ( nn - 0.14 * ( lpr + cc ) );
lgf = (*work) / ( 1.0 + f1 * f1 );
return pow(10.0, lgf );
}
virtual size_t workSize() { return 1; }
protected:
doublereal m_a, m_rt3, m_rt1;
private:
};
/**
* The 4-parameter Troe falloff parameterization. This parameterization is
* defined by
*
* \f[ F = F_{cent}^{1/(1 + f_1^2)} \f]
* where
* \f[ F_{cent} = (1 - A)\exp(-T/T_3) + A \exp(-T/T_1) + \exp(-T_2/T) \f]
* \f[ f_1 = (\log_{10} P_r + C) / \left(N - 0.14
* (\log_{10} P_r + C)\right) \f]
* \f[ C = -0.4 - 0.67 \log_{10} F_{cent} \f]
* \f[ N = 0.75 - 1.27 \log_{10} F_{cent} \f]
*
*/
class Troe4 : public Falloff {
public:
Troe4() : m_a (0.0), m_rt3 (0.0), m_rt1 (0.0),
m_t2 (0.0) {}
virtual ~Troe4() {}
virtual void init(const vector_fp& c) {
m_a = c[0];
m_rt3 = 1.0/c[1];
m_rt1 = 1.0/c[2];
m_t2 = c[3];
}
virtual void updateTemp(doublereal T, workPtr work) const {
doublereal Fcent = (1.0 - m_a) * exp(- T * m_rt3 )
+ m_a * exp(- T * m_rt1 )
+ exp(- m_t2 / T );
*work = log10( fmaxx( Fcent, SmallNumber ) );
}
virtual doublereal F(doublereal pr, const_workPtr work) const {
doublereal lpr,f1,lgf, cc, nn;
lpr = log10( fmaxx(pr,SmallNumber) );
cc = -0.4 - 0.67 * (*work);
nn = 0.75 - 1.27 * (*work);
f1 = ( lpr + cc )/ ( nn - 0.14 * ( lpr + cc ) );
lgf = (*work) / ( 1.0 + f1 * f1 );
return pow(10.0, lgf );
}
virtual size_t workSize() { return 1; }
protected:
doublereal m_a, m_rt3, m_rt1;
doublereal m_t2;
private:
};
/**
* The 3-parameter SRI falloff function.
*/
class SRI3 : public Falloff {
public:
SRI3() {}
virtual ~SRI3() {}
virtual void init(const vector_fp& c) {
m_a = c[0];
m_b = c[1];
m_c = c[2];
}
virtual void updateTemp(doublereal T, workPtr work) const {
*work = m_a * exp( - m_b / T);
if (m_c != 0.0) *work += exp( - T/m_c );
}
virtual doublereal F(doublereal pr, const_workPtr work) const {
doublereal lpr = log10( fmaxx(pr,SmallNumber) );
doublereal xx = 1.0/(1.0 + lpr*lpr);
doublereal ff = pow( *work , xx);
return ff;
}
virtual size_t workSize() { return 1; }
protected:
doublereal m_a, m_b, m_c;
private:
};
/**
* The 5-parameter SRI falloff function.
*/
class SRI5 : public Falloff {
public:
SRI5() {}
virtual ~SRI5() {}
virtual void init(const vector_fp& c) {
m_a = c[0];
m_b = c[1];
m_c = c[2];
m_d = c[3];
m_e = c[4];
}
virtual void updateTemp(doublereal T, workPtr work) const {
*work = m_a * exp( - m_b / T);
if (m_c != 0.0) *work += exp( - T/m_c );
work[1] = m_d * pow(T,m_e);
}
virtual doublereal F(doublereal pr, const_workPtr work) const {
doublereal lpr = log10( fmaxx(pr,SmallNumber) );
doublereal xx = 1.0/(1.0 + lpr*lpr);
return pow( *work, xx) * work[1];
}
virtual size_t workSize() { return 2; }
protected:
doublereal m_a, m_b, m_c;
doublereal m_d, m_e;
private:
};
/**
* Wang-Frenklach falloff function. Reference: Wang, H., and
* Frenklach, M., Chem. Phys. Lett. vol. 205, 271 (1993).
*/
class WF93 : public Falloff {
public:
WF93() {}
virtual ~WF93() {}
virtual void init(const vector_fp& c) {
m_a = c[0];
m_rt1 = 1.0/c[1];
m_t2 = c[2];
m_rt3 = 1.0/c[3];
m_alpha0 = c[4];
m_alpha1 = c[5];
m_alpha2 = c[6];
m_sigma0 = c[7];
m_sigma1 = c[8];
m_sigma2 = c[9];
}
virtual void updateTemp(doublereal T, workPtr work) const {
work[0] = m_alpha0 + (m_alpha1 + m_alpha2*T)*T; // alpha
work[1] = m_sigma0 + (m_sigma1 + m_sigma2*T)*T; // sigma
doublereal Fcent = (1.0 - m_a) * exp(- T * m_rt3 )
+ m_a * exp(- T * m_rt1 ) + exp(-m_t2/T);
work[2] = log10(Fcent);
}
virtual doublereal F(doublereal pr, const_workPtr work) const {
doublereal lpr = log10( fmaxx(pr, SmallNumber) );
doublereal x = (lpr - work[0])/work[1];
doublereal flog = work[2]/exp(x*x);
return pow( 10.0, flog);
}
virtual size_t workSize() { return 3; }
protected:
doublereal m_alpha0, m_alpha1, m_alpha2;
doublereal m_sigma0, m_sigma1, m_sigma2;
doublereal m_a, m_rt1, m_t2, m_rt3;
private:
};
Falloff* FalloffFactory::newFalloff(int type, const vector_fp& c) {
Falloff* f;
switch(type) {
case TROE3_FALLOFF:
f = new Troe3(); break;
case TROE4_FALLOFF:
f = new Troe4(); break;
case SRI3_FALLOFF:
f = new SRI3(); break;
case SRI5_FALLOFF:
f = new SRI5(); break;
case WF_FALLOFF:
f = new WF93(); break;
default: return 0;
}
f->init(c);
return f;
}
}

View file

@ -0,0 +1,136 @@
/**
* @file FalloffFactory.h
*
* Parameterizations for reaction falloff functions. Used by classes
* that implement gas-phase kinetics (GasKinetics, GRI_30_Kinetics).
*/
/*
* $Author$
* $Date$
* $Revision$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_NEWFALLOFF_H
#define CT_NEWFALLOFF_H
#include "ct_defs.h"
#include "reaction_defs.h"
namespace Cantera {
/**
* Base class for falloff function calculators. Each instance of a
* subclass of Falloff computes one falloff function.
*/
class Falloff {
public:
Falloff(){}
virtual ~Falloff(){}
/**
* Initialize. Must be called before any other method is
* invoked.
*
* @param c Vector of coefficients of the parameterization.
* The number and meaning of these coefficients is
* subclass-dependent.
*/
virtual void init(const vector_fp& c) =0;
/**
* Update the temperature-dependent portions of the falloff
* function, if any. This method evaluates temperature-dependent
* intermediate results and stores them in the 'work' array.
* If not overloaded, the default behavior is to do nothing.
* @param T Temperature [K].
* @param work storage space for intermediate results.
*/
virtual void updateTemp (doublereal T, workPtr work) const {}
/**
* The falloff function. This is defined so that the
* rate coefficient is
* \f[ k = F(Pr)\frac{Pr}{1 + Pr}. \f]
* Here \f$ Pr \f$ is the reduced pressure, defined by
* \f[
* Pr = \frac{k_0 [M]}{k_\infty}.
* \f]
* @param pr reduced pressure (dimensionless).
* @param work array of size workSize() containing cached
* temperature-dependent intermediate results from a prior call
* to updateTemp.
*/
virtual doublereal F(doublereal pr, const_workPtr work) const =0;
/**
* The size of the work array required.
*/
virtual size_t workSize() =0;
protected:
private:
};
/**
* Factory class to construct falloff function calculators.
* The falloff factory is accessed through static method factory:
* @code
* Falloff* f = FalloffFactory::factory()->newFalloff(type, c)
* @endcode
* @ingroup falloffGroup
*/
class FalloffFactory {
public:
/**
* Return a pointer to the factory. On the first call, a new
* instance is created. Since there is no need to instantiate
* more than one factory, on all subsequent calls, a pointer
* to the existing factory is returned.
*/
static FalloffFactory* factory() {
if (!s_factory) s_factory = new FalloffFactory;
return s_factory;
}
static void deleteFalloffFactory() {
if (s_factory) {
delete s_factory;
s_factory = 0;
}
}
/**
* Destructor doesn't do anything. We do not delete statically
* created single instance of this class here, because it would
* create an infinite loop if destructor is called for that
* single instance. Instead, to delete single instance, we
* call delete[] from FalloffMng's destructor.
*/
virtual ~FalloffFactory() {
}
/**
* Return a pointer to a new falloff function calculator.
* @param type Integer flag specifying the type of falloff function.
* The standard types are defined in file reaction_defs.h. A factory
* class derived from FalloffFactory may define other types as well.
*/
virtual Falloff* newFalloff(int type, const vector_fp& c);
private:
static FalloffFactory* s_factory;
FalloffFactory(){}
};
}
#endif

123
Cantera/src/kinetics/FalloffMgr.h Executable file
View file

@ -0,0 +1,123 @@
/**
* @file FalloffMgr.h
*
* $Author$
* $Date$
* $Revision$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_FALLOFFMGR_H
#define CT_FALLOFFMGR_H
#include "reaction_defs.h"
#include "FalloffFactory.h"
namespace Cantera {
/**
* A falloff manager that implements any set of falloff functions.
* @ingroup falloffGroup
*/
class FalloffMgr {
public:
/**
* Constructor.
* @param f If supplied, this factory will be used to construct
* falloff function calculators. If omitted, the standard factory
* will be used.
*/
FalloffMgr(FalloffFactory* f = 0) :
m_n(0), m_n0(0), m_worksize(0) {
if (f == 0) m_factory = FalloffFactory::factory();
else m_factory = f;
}
/**
* Destructor. Deletes all installed falloff function
* calculators.
*/
virtual ~FalloffMgr(){
int i;
for (i = 0; i < m_n; i++) delete m_falloff[i];
if (m_factory) {
FalloffFactory::deleteFalloffFactory();
m_factory = 0;
}
}
/**
* Install a new falloff function calculator. @param rxn
* Index of the falloff reaction. This will be used to determine
* which array entry is modified in method pr_to_falloff.
*
* @param type of falloff function to install.
* @param c vector of coefficients for the falloff function.
*/
void install(int rxn, int type,
const vector_fp& c) {
if (type != SIMPLE_FALLOFF) {
m_rxn.push_back(rxn);
Falloff* f = m_factory->newFalloff(type,c);
m_offset.push_back(m_worksize);
m_worksize += f->workSize();
m_falloff.push_back(f);
m_n++;
}
else {
m_rxn0.push_back(rxn);
m_n0++;
}
}
/**
* Size of the work array required to store intermediate results.
*/
size_t workSize() { return m_worksize; }
/**
* Update the cached temperature-dependent intermediate
* results for all installed falloff functions.
* @param t Temperature [K].
* @param work Work array. Must be dimensioned at least workSize().
*/
void updateTemp(doublereal t, workPtr work) {
int i;
for (i = 0; i < m_n; i++) {
m_falloff[i]->updateTemp(t,
work + m_offset[i]);
}
}
/**
* Given a vector of reduced pressures for each falloff reaction,
* replace each entry by the value of the falloff function.
*/
void pr_to_falloff(doublereal* values, const_workPtr work) {
doublereal pr;
int i;
for (i = 0; i < m_n0; i++) {
values[m_rxn0[i]] /= (1.0 + values[m_rxn0[i]]);
}
for (i = 0; i < m_n; i++) {
pr = values[m_rxn[i]];
values[m_rxn[i]] *=
m_falloff[i]->F(pr, work + m_offset[i]) /(1.0 + pr);
}
}
protected:
vector_int m_rxn, m_rxn0;
std::vector<Falloff*> m_falloff;
FalloffFactory* m_factory;
vector_int m_loc;
int m_n, m_n0;
std::vector<vector_fp::difference_type> m_offset;
size_t m_worksize;
};
}
#endif

View file

@ -0,0 +1,999 @@
/**
* @file GRI_30_Kinetics.cpp
*
*/
// Copyright 2001 California Institute of Technology
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "GRI_30_Kinetics.h"
#include "ReactionData.h"
//#include "StoichManager.h"
#include "Enhanced3BConc.h"
#include "ThirdBodyMgr.h"
#include "RateCoeffMgr.h"
#include "IdealGasPhase.h"
#include <iostream>
using namespace std;
namespace Cantera {
/**
* Construct an empty reaction mechanism.
*/
GRI_30_Kinetics::
GRI_30_Kinetics(thermo_t* th) : GasKinetics(th) {}
void GRI_30_Kinetics::
gri30_update_rates_T() {
doublereal T = thermo().temperature();
if (fabs(T - m_kdata->m_temp) > m_dt_threshold) {
doublereal logT = log(T);
m_kdata->m_logc_ref = m_kdata->m_logp_ref - logT;
update_rates(T, logT, &m_kdata->m_rfn[0]);
m_falloff_low_rates.update(T, logT, &m_kdata->m_rfn_low[0]);
m_falloff_high_rates.update(T, logT, &m_kdata->m_rfn_high[0]);
m_falloffn.updateTemp(T, &m_kdata->falloff_work[0]);
m_kdata->m_temp = T;
gri30_updateKc();
m_kdata->m_ROP_ok = false;
}
};
/**
* Update the equilibrium constants in molar units.
* @todo This formulation assumes an ideal gas.
*/
void GRI_30_Kinetics::gri30_updateKc() {
doublereal* rkc = &m_kdata->m_rkcn[0];
const doublereal* a =
&((IdealGasPhase*)m_thermo[0])->expGibbs_RT_ref()[0];
doublereal exp_c_ref = exp(m_kdata->m_logc_ref);
update_kc(a, exp_c_ref, rkc);
}
void GRI_30_Kinetics::gri30_updateROP() {
gri30_update_rates_T();
_update_rates_C();
if (m_kdata->m_ROP_ok) return;
const vector_fp& rf = m_kdata->m_rfn;
const vector_fp& rkc = m_kdata->m_rkcn;
array_fp& ropf = m_kdata->m_ropf;
array_fp& ropnet = m_kdata->m_ropnet;
copy(rf.begin(), rf.end(), ropf.begin());
m_3b_concm.multiply( &ropf[0], &m_kdata->concm_3b_values[0] );
processFalloffReactions();
multiply_each(ropf.begin(), ropf.end(), m_perturb.begin());
eval_ropnet(&m_conc[0], &ropf[0], &rkc[0], &ropnet[0]);
m_kdata->m_ROP_ok = true;
}
void GRI_30_Kinetics::update_rates(double t, double tlog, double* rf) {
double rt = 1.0/t;
rf[0] = exp(25.5108 + -1 * tlog);
rf[1] = exp(26.9379 + -1 * tlog);
rf[2] = exp(3.65584 + 2.7 * tlog - 3150.48 * rt);
rf[4] = exp(9.17264 + 2 * tlog - 2013.09 * rt);
rf[10] = exp(13.8353 + 1.5 * tlog - 4328.13 * rt);
rf[14] = exp(24.3868 - 1781.58 * rt);
rf[17] = exp(5.96101 + 2.5 * tlog - 1560.14 * rt);
rf[18] = exp(4.86753 + 2.5 * tlog - 2516.36 * rt);
rf[20] = exp(9.51044 + 2 * tlog - 956.215 * rt);
rf[21] = exp(38.3674 + -1.41 * tlog - 14569.7 * rt);
rf[22] = exp(8.84506 + 2 * tlog - 956.215 * rt);
rf[24] = exp(9.43348 + 1.83 * tlog - 110.72 * rt);
rf[26] = exp(11.4053 + 1.92 * tlog - 2863.61 * rt);
rf[28] = exp(23.0259 - 4026.17 * rt);
rf[29] = exp(21.2829 - 679.416 * rt);
rf[30] = exp(21.6396 - 24056.4 * rt);
rf[31] = exp(25.3284 - 20130.9 * rt);
rf[32] = exp(28.6606 + -0.86 * tlog);
rf[33] = exp(30.666 + -1.24 * tlog);
rf[34] = exp(30.0523 + -0.76 * tlog);
rf[35] = exp(30.8891 + -1.24 * tlog);
rf[36] = exp(27.2743 + -0.8 * tlog);
rf[37] = exp(30.9082 + -0.6707 * tlog - 8576.25 * rt);
rf[38] = exp(27.631 + -1 * tlog);
rf[39] = exp(25.2231 + -0.6 * tlog);
rf[40] = exp(31.7254 + -1.25 * tlog);
rf[41] = exp(33.9409 + -2 * tlog);
rf[42] = exp(37.6298 + -2 * tlog);
rf[43] = exp(22.102 - 337.695 * rt);
rf[44] = exp(24.5255 - 537.494 * rt);
rf[45] = exp(25.1541 - 319.577 * rt);
rf[46] = exp(9.40096 + 2 * tlog - 2617.01 * rt);
rf[47] = exp(23.0259 - 1811.78 * rt);
rf[52] = exp(13.4 + 1.62 * tlog - 5455.46 * rt);
rf[57] = exp(10.9578 + 1.9 * tlog - 1379.97 * rt);
rf[60] = exp(18.9215 + 0.65 * tlog - -142.929 * rt);
rf[61] = exp(24.2137 + -0.09 * tlog - 306.995 * rt);
rf[63] = exp(10.6334 + 1.63 * tlog - 968.294 * rt);
rf[65] = exp(21.1287 + 0.5 * tlog - -55.3598 * rt);
rf[66] = exp(26.2916 + -0.23 * tlog - 538.5 * rt);
rf[67] = exp(9.74097 + 2.1 * tlog - 2450.93 * rt);
rf[68] = exp(8.34284 + 2.1 * tlog - 2450.93 * rt);
rf[74] = exp(7.18917 + 2.53 * tlog - 6160.04 * rt);
rf[77] = exp(11.6527 + 1.9 * tlog - 3789.63 * rt);
rf[79] = exp(24.6353 - 4026.17 * rt);
rf[80] = exp(23.1481 - 1725.21 * rt);
rf[83] = exp(12.283 + 1.51 * tlog - 1726.22 * rt);
rf[85] = exp(3.57515 + 2.4 * tlog - -1061.9 * rt);
rf[86] = exp(23.3974 - -251.636 * rt);
rf[87] = exp(21.4164 - 214.897 * rt);
rf[88] = exp(35.0694 - 14801.2 * rt);
rf[92] = exp(9.33256 + 2 * tlog - 1509.81 * rt);
rf[95] = exp(10.9331 + 1.6 * tlog - 2727.73 * rt);
rf[96] = exp(34.0987 + -1.34 * tlog - 713.135 * rt);
rf[97] = exp(11.5129 + 1.6 * tlog - 1570.21 * rt);
rf[98] = exp(10.7706 + 1.228 * tlog - 35.229 * rt);
rf[100] = exp(15.0481 + 1.18 * tlog - -224.962 * rt);
rf[103] = exp(7.2724 + 2 * tlog - -422.748 * rt);
rf[104] = exp(8.7483 + 2 * tlog - 754.907 * rt);
rf[106] = exp(-15.3388 + 4.5 * tlog - -503.271 * rt);
rf[107] = exp(6.22258 + 2.3 * tlog - 6794.16 * rt);
rf[108] = exp(10.4253 + 2 * tlog - 7045.8 * rt);
rf[109] = exp(-14.5432 + 4 * tlog - -1006.54 * rt);
rf[111] = exp(8.18869 + 2 * tlog - 1258.18 * rt);
rf[112] = exp(8.17188 + 2.12 * tlog - 437.846 * rt);
rf[113] = exp(22.7382 - 1006.54 * rt);
rf[114] = exp(18.683 - -820.332 * rt);
rf[115] = exp(26.7635 - 6039.26 * rt);
rf[119] = exp(25.7339 - 11877.2 * rt);
rf[120] = exp(8.63052 + 2 * tlog - 6039.26 * rt);
rf[121] = exp(24.7837 - 289.884 * rt);
rf[125] = exp(25.4054 - 1565.17 * rt);
rf[126] = exp(22.4655 - -379.97 * rt);
rf[131] = exp(25.9703 - 7947.66 * rt);
rf[132] = exp(25.2729 - -259.185 * rt);
rf[134] = exp(22.3327 - 754.907 * rt);
rf[135] = exp(6.21461 + 2 * tlog - 3638.65 * rt);
rf[136] = exp(28.101 - 6011.07 * rt);
rf[138] = exp(7.80792 + 2 * tlog - 4162.05 * rt);
rf[141] = exp(23.4313 - 301.963 * rt);
rf[142] = exp(22.9205 - 301.963 * rt);
rf[148] = exp(23.2082 - -286.865 * rt);
rf[149] = exp(23.4959 - -286.865 * rt);
rf[153] = exp(24.4121 - -276.799 * rt);
rf[154] = exp(24.2956 - 15339.7 * rt);
rf[155] = exp(21.5605 - 10224 * rt);
rf[156] = exp(3.19867 + 2.47 * tlog - 2606.95 * rt);
rf[158] = exp(22.6461 + 0.1 * tlog - 5334.68 * rt);
rf[160] = exp(1.19996 + 2.81 * tlog - 2949.17 * rt);
rf[161] = exp(10.309 + 1.5 * tlog - 5002.52 * rt);
rf[162] = exp(9.21034 + 1.5 * tlog - 5002.52 * rt);
rf[163] = exp(5.42495 + 2 * tlog - 4630.1 * rt);
rf[164] = exp(8.72258 + 1.74 * tlog - 5259.18 * rt);
rf[165] = exp(34.9442 + -1 * tlog - 8555.61 * rt);
rf[166] = exp(32.8621 + -1 * tlog - 8555.61 * rt);
rf[167] = exp(23.3222 - 201.309 * rt);
rf[168] = exp(23.6136 - 452.944 * rt);
rf[169] = exp(-35.3874 + 7.6 * tlog - -1776.55 * rt);
rf[170] = exp(23.0259 - -379.97 * rt);
rf[171] = exp(17.855 + 0.9 * tlog - 1003.02 * rt);
rf[172] = exp(31.4553 + -1.39 * tlog - 510.82 * rt);
rf[174] = exp(20.5489 - 1950.18 * rt);
rf[175] = exp(21.8864 - 429.794 * rt);
rf[177] = exp(24.0191 - 178.661 * rt);
rf[178] = exp(16.0127 + 1 * tlog - 3271.26 * rt);
rf[179] = exp(24.2378 - 193.759 * rt);
rf[180] = exp(21.0597 - 5440.36 * rt);
rf[181] = exp(24.0906 - 11650.7 * rt);
rf[182] = exp(26.6817 - 9501.76 * rt);
rf[183] = exp(21.4164 - 10598.9 * rt);
rf[185] = exp(21.47 - -241.57 * rt);
rf[186] = exp(32.2945 + -1.41 * tlog);
rf[187] = exp(22.0842 - -120.785 * rt);
rf[188] = exp(25.6061 - 181.178 * rt);
rf[190] = exp(24.189 - 166.08 * rt);
rf[192] = exp(14.5087 + 1.2 * tlog);
rf[193] = exp(6.1334 + 2 * tlog - 3271.26 * rt);
rf[194] = exp(7.15462 + 1.5 * tlog - 50.3271 * rt);
rf[196] = exp(23.719 - 6970.31 * rt);
rf[197] = exp(23.796 + -0.23 * tlog);
rf[198] = exp(26.6232 + -0.45 * tlog);
rf[201] = exp(24.4121 - 1836.94 * rt);
rf[202] = exp(11.4076 + 1.5 * tlog - -231.505 * rt);
rf[204] = exp(25.5908 + -0.11 * tlog - 2506.29 * rt);
rf[211] = exp(31.4332 + -1.32 * tlog - 372.421 * rt);
rf[213] = exp(20.6179 + 0.72 * tlog - 332.159 * rt);
rf[214] = exp(9.4727 + 1.9 * tlog - -478.108 * rt);
rf[215] = exp(23.0259 - 6542.53 * rt);
rf[218] = exp(22.8027 - 3754.4 * rt);
rf[219] = exp(22.5381 - -221.439 * rt);
rf[220] = exp(5.68698 + 2.45 * tlog - 1127.33 * rt);
rf[225] = exp(21.4164 - 10065.4 * rt);
rf[226] = exp(26.4598 - 27201.8 * rt);
rf[227] = exp(32.878 + -1.52 * tlog - 372.421 * rt);
rf[228] = exp(35.8738 + -2 * tlog - 402.617 * rt);
rf[229] = exp(59.9064 + -3.3 * tlog - 63714.1 * rt);
rf[230] = exp(3.01062 + 2.64 * tlog - 2506.29 * rt);
rf[231] = exp(1.62334 + 2.64 * tlog - 2506.29 * rt);
rf[232] = exp(15.179 + 1.58 * tlog - 13387 * rt);
rf[233] = exp(7.00307 + 2.03 * tlog - 6728.74 * rt);
rf[234] = exp(1.4816 + 2.26 * tlog - 3220.94 * rt);
rf[235] = exp(-1.83258 + 2.56 * tlog - 4529.44 * rt);
rf[237] = exp(24.8176 - 201.309 * rt);
rf[238] = exp(24.8664 - 23160.5 * rt);
rf[239] = exp(14.9533 + 0.88 * tlog - 10130.9 * rt);
rf[241] = exp(23.0259 - 37242.1 * rt);
rf[242] = exp(18.4207 - 32712.6 * rt);
rf[248] = exp(33.3676 + -1.38 * tlog - 639.155 * rt);
rf[249] = exp(26.3931 + -0.69 * tlog - 382.486 * rt);
rf[250] = exp(24.3609 + -0.36 * tlog - 291.897 * rt);
rf[251] = exp(33.3676 + -1.38 * tlog - 639.155 * rt);
rf[252] = exp(26.3931 + -0.69 * tlog - 382.486 * rt);
rf[253] = exp(24.3609 + -0.36 * tlog - 291.897 * rt);
rf[254] = exp(25.2876 - 14494.2 * rt);
rf[255] = exp(20.7233 - 10946.1 * rt);
rf[261] = exp(11.4927 + 1.41 * tlog - 4277.81 * rt);
rf[262] = exp(11.9184 + 1.57 * tlog - 22143.9 * rt);
rf[263] = exp(7.69621 + 2.11 * tlog - 5737.29 * rt);
rf[264] = exp(10.0213 + 1.7 * tlog - 1912.43 * rt);
rf[265] = exp(4.65396 + 2.5 * tlog - 6693.51 * rt);
rf[266] = exp(10.4043 + 1.5 * tlog - 1811.78 * rt);
rf[267] = exp(8.10168 + 1.5 * tlog - 1811.78 * rt);
rf[268] = exp(30.0991 - 42637.1 * rt);
rf[269] = exp(28.373 + -0.69 * tlog - 1434.32 * rt);
rf[270] = exp(19.4139 + 0.18 * tlog - 1066.94 * rt);
rf[271] = exp(25.8591 + -0.75 * tlog - 1454.45 * rt);
rf[272] = exp(9.90349 + 2 * tlog - 1006.54 * rt);
rf[274] = exp(27.1367 + -0.31 * tlog - 145.949 * rt);
rf[275] = exp(22.0316 + 0.15 * tlog - -45.2944 * rt);
rf[276] = exp(6.29157 + 2.4 * tlog - 4989.93 * rt);
rf[277] = exp(10.8198 + 1.6 * tlog - 480.624 * rt);
rf[278] = exp(9.14846 + 1.94 * tlog - 3251.13 * rt);
rf[279] = exp(23.0259 - 7221.94 * rt);
rf[280] = exp(29.4491 + -0.752 * tlog - 173.629 * rt);
rf[281] = exp(21.9019 - -354.806 * rt);
rf[282] = exp(21.8219 - 5686.97 * rt);
rf[284] = exp(8.80986 + 1.83 * tlog - 110.72 * rt);
rf[286] = exp(29.2405 - 8721.69 * rt);
rf[287] = exp(15.895 + 0.5 * tlog - -883.241 * rt);
rf[289] = exp(22.4811 - 754.907 * rt);
rf[290] = exp(21.5987 - 754.907 * rt);
rf[291] = exp(26.0216 - 5530.45 * rt);
rf[292] = exp(18.038 + 0.25 * tlog - -470.559 * rt);
rf[293] = exp(19.5292 + 0.29 * tlog - 5.53598 * rt);
rf[294] = exp(7.19818 + 1.61 * tlog - -193.256 * rt);
rf[295] = exp(22.488 - 909.914 * rt);
rf[296] = exp(22.488 - 909.914 * rt);
rf[297] = exp(24.1278 - 19703.1 * rt);
rf[298] = exp(14.5334 + 1.16 * tlog - 1210.37 * rt);
rf[299] = exp(14.5334 + 1.16 * tlog - 1210.37 * rt);
rf[300] = exp(16.9695 + 0.73 * tlog - -560.141 * rt);
rf[301] = exp(21.8252 - 6000.5 * rt);
rf[302] = exp(7.90839 + 1.77 * tlog - 2979.37 * rt);
rf[312] = exp(5.26269 + 2.68 * tlog - 1870.16 * rt);
rf[313] = exp(7.18539 + 2.54 * tlog - 3400.1 * rt);
rf[314] = exp(10.3609 + 1.8 * tlog - 470.055 * rt);
rf[315] = exp(-0.972861 + 2.72 * tlog - 754.907 * rt);
rf[316] = exp(-7.00979 + 3.65 * tlog - 3600.4 * rt);
rf[320] = exp(8.30894 + 2.19 * tlog - 447.911 * rt);
rf[322] = exp(17.0542 + 0.255 * tlog - -474.585 * rt);
rf[324] = exp(23.6818 + -0.32 * tlog);
}
void GRI_30_Kinetics::update_kc(const double* a, double exp_c0, double* rkc) {
rkc[0] = a[3]*exp_c0/(a[2]*a[2]);
rkc[1] = a[4]*exp_c0/(a[1]*a[2]);
rkc[2] = a[1]*a[4]/(a[0]*a[2]);
rkc[3] = a[3]*a[4]/(a[2]*a[6]);
rkc[4] = a[4]*a[6]/(a[2]*a[7]);
rkc[5] = a[1]*a[14]/(a[2]*a[9]);
rkc[6] = a[1]*a[16]/(a[2]*a[10]);
rkc[7] = a[0]*a[14]/(a[2]*a[11]);
rkc[8] = a[1]*a[16]/(a[2]*a[11]);
rkc[9] = a[1]*a[17]/(a[2]*a[12]);
rkc[10] = a[4]*a[12]/(a[2]*a[13]);
rkc[11] = a[15]*exp_c0/(a[2]*a[14]);
rkc[12] = a[4]*a[14]/(a[2]*a[16]);
rkc[13] = a[1]*a[15]/(a[2]*a[16]);
rkc[14] = a[4]*a[16]/(a[2]*a[17]);
rkc[15] = a[4]*a[17]/(a[2]*a[18]);
rkc[16] = a[4]*a[17]/(a[2]*a[19]);
rkc[17] = a[4]*a[18]/(a[2]*a[20]);
rkc[18] = a[4]*a[19]/(a[2]*a[20]);
rkc[19] = a[9]*a[14]/(a[2]*a[21]);
rkc[20] = a[1]*a[27]/(a[2]*a[22]);
rkc[21] = a[4]*a[21]/(a[2]*a[22]);
rkc[22] = a[10]*a[14]/(a[2]*a[22]);
rkc[23] = a[1]*a[28]/(a[2]*a[23]);
rkc[24] = a[12]*a[16]/(a[2]*a[24]);
rkc[25] = a[12]*a[17]/(a[2]*a[25]);
rkc[26] = a[4]*a[25]/(a[2]*a[26]);
rkc[27] = a[1]*a[14]*a[14]/(a[2]*a[27]*exp_c0);
rkc[28] = a[4]*a[27]/(a[2]*a[28]);
rkc[29] = a[10]*a[15]/(a[2]*a[28]);
rkc[30] = a[2]*a[15]/(a[3]*a[14]);
rkc[31] = a[6]*a[16]/(a[3]*a[17]);
rkc[32] = a[6]*exp_c0/(a[1]*a[3]);
rkc[33] = a[3]*a[6]*exp_c0/(a[1]*a[3]*a[3]);
rkc[34] = a[5]*a[6]*exp_c0/(a[1]*a[3]*a[5]);
rkc[35] = a[6]*a[47]*exp_c0/(a[1]*a[3]*a[47]);
rkc[36] = a[6]*a[48]*exp_c0/(a[1]*a[3]*a[48]);
rkc[37] = a[2]*a[4]/(a[1]*a[3]);
rkc[38] = a[0]*exp_c0/(a[1]*a[1]);
rkc[39] = a[0]*a[0]*exp_c0/(a[0]*a[1]*a[1]);
rkc[40] = a[0]*a[5]*exp_c0/(a[1]*a[1]*a[5]);
rkc[41] = a[0]*a[15]*exp_c0/(a[1]*a[1]*a[15]);
rkc[42] = a[5]*exp_c0/(a[1]*a[4]);
rkc[43] = a[2]*a[5]/(a[1]*a[6]);
rkc[44] = a[0]*a[3]/(a[1]*a[6]);
rkc[45] = a[4]*a[4]/(a[1]*a[6]);
rkc[46] = a[0]*a[6]/(a[1]*a[7]);
rkc[47] = a[4]*a[5]/(a[1]*a[7]);
rkc[48] = a[0]*a[8]/(a[1]*a[9]);
rkc[49] = a[12]*exp_c0/(a[1]*a[10]);
rkc[50] = a[0]*a[9]/(a[1]*a[11]);
rkc[51] = a[13]*exp_c0/(a[1]*a[12]);
rkc[52] = a[0]*a[12]/(a[1]*a[13]);
rkc[53] = a[17]*exp_c0/(a[1]*a[16]);
rkc[54] = a[0]*a[14]/(a[1]*a[16]);
rkc[55] = a[18]*exp_c0/(a[1]*a[17]);
rkc[56] = a[19]*exp_c0/(a[1]*a[17]);
rkc[57] = a[0]*a[16]/(a[1]*a[17]);
rkc[58] = a[20]*exp_c0/(a[1]*a[18]);
rkc[59] = a[0]*a[17]/(a[1]*a[18]);
rkc[60] = a[4]*a[12]/(a[1]*a[18]);
rkc[61] = a[5]*a[11]/(a[1]*a[18]);
rkc[62] = a[20]*exp_c0/(a[1]*a[19]);
rkc[63] = a[1]*a[18]/(a[1]*a[19]);
rkc[64] = a[0]*a[17]/(a[1]*a[19]);
rkc[65] = a[4]*a[12]/(a[1]*a[19]);
rkc[66] = a[5]*a[11]/(a[1]*a[19]);
rkc[67] = a[0]*a[18]/(a[1]*a[20]);
rkc[68] = a[0]*a[19]/(a[1]*a[20]);
rkc[69] = a[22]*exp_c0/(a[1]*a[21]);
rkc[70] = a[23]*exp_c0/(a[1]*a[22]);
rkc[71] = a[24]*exp_c0/(a[1]*a[23]);
rkc[72] = a[0]*a[22]/(a[1]*a[23]);
rkc[73] = a[25]*exp_c0/(a[1]*a[24]);
rkc[74] = a[0]*a[23]/(a[1]*a[24]);
rkc[75] = a[26]*exp_c0/(a[1]*a[25]);
rkc[76] = a[0]*a[24]/(a[1]*a[25]);
rkc[77] = a[0]*a[25]/(a[1]*a[26]);
rkc[78] = a[11]*a[14]/(a[1]*a[27]);
rkc[79] = a[0]*a[27]/(a[1]*a[28]);
rkc[80] = a[12]*a[14]/(a[1]*a[28]);
rkc[81] = a[1]*a[28]/(a[1]*a[29]);
rkc[82] = a[17]*exp_c0/(a[0]*a[14]);
rkc[83] = a[1]*a[5]/(a[0]*a[4]);
rkc[84] = a[7]*exp_c0/(a[4]*a[4]);
rkc[85] = a[2]*a[5]/(a[4]*a[4]);
rkc[86] = a[3]*a[5]/(a[4]*a[6]);
rkc[87] = a[5]*a[6]/(a[4]*a[7]);
rkc[88] = a[5]*a[6]/(a[4]*a[7]);
rkc[89] = a[1]*a[14]/(a[4]*a[8]);
rkc[90] = a[1]*a[16]/(a[4]*a[9]);
rkc[91] = a[1]*a[17]/(a[4]*a[10]);
rkc[92] = a[5]*a[9]/(a[4]*a[10]);
rkc[93] = a[1]*a[17]/(a[4]*a[11]);
rkc[94] = a[20]*exp_c0/(a[4]*a[12]);
rkc[95] = a[5]*a[10]/(a[4]*a[12]);
rkc[96] = a[5]*a[11]/(a[4]*a[12]);
rkc[97] = a[5]*a[12]/(a[4]*a[13]);
rkc[98] = a[1]*a[15]/(a[4]*a[14]);
rkc[99] = a[5]*a[14]/(a[4]*a[16]);
rkc[100] = a[5]*a[16]/(a[4]*a[17]);
rkc[101] = a[5]*a[17]/(a[4]*a[18]);
rkc[102] = a[5]*a[17]/(a[4]*a[19]);
rkc[103] = a[5]*a[18]/(a[4]*a[20]);
rkc[104] = a[5]*a[19]/(a[4]*a[20]);
rkc[105] = a[1]*a[27]/(a[4]*a[21]);
rkc[106] = a[1]*a[28]/(a[4]*a[22]);
rkc[107] = a[1]*a[29]/(a[4]*a[22]);
rkc[108] = a[5]*a[21]/(a[4]*a[22]);
rkc[109] = a[12]*a[14]/(a[4]*a[22]);
rkc[110] = a[5]*a[22]/(a[4]*a[23]);
rkc[111] = a[5]*a[23]/(a[4]*a[24]);
rkc[112] = a[5]*a[25]/(a[4]*a[26]);
rkc[113] = a[5]*a[27]/(a[4]*a[28]);
rkc[114] = a[3]*a[7]/(a[6]*a[6]);
rkc[115] = a[3]*a[7]/(a[6]*a[6]);
rkc[116] = a[4]*a[17]/(a[6]*a[10]);
rkc[117] = a[3]*a[13]/(a[6]*a[12]);
rkc[118] = a[4]*a[19]/(a[6]*a[12]);
rkc[119] = a[4]*a[15]/(a[6]*a[14]);
rkc[120] = a[7]*a[16]/(a[6]*a[17]);
rkc[121] = a[2]*a[14]/(a[3]*a[8]);
rkc[122] = a[1]*a[21]/(a[8]*a[10]);
rkc[123] = a[1]*a[22]/(a[8]*a[12]);
rkc[124] = a[2]*a[16]/(a[3]*a[9]);
rkc[125] = a[1]*a[10]/(a[0]*a[9]);
rkc[126] = a[1]*a[17]/(a[5]*a[9]);
rkc[127] = a[1]*a[22]/(a[9]*a[10]);
rkc[128] = a[1]*a[23]/(a[9]*a[12]);
rkc[129] = a[1]*a[24]/(a[9]*a[13]);
rkc[130] = a[27]*exp_c0/(a[9]*a[14]);
rkc[131] = a[14]*a[16]/(a[9]*a[15]);
rkc[132] = a[1]*a[28]/(a[9]*a[17]);
rkc[133] = a[14]*a[22]/(a[9]*a[27]);
rkc[135] = a[1]*a[12]/(a[0]*a[10]);
rkc[136] = a[0]*a[22]/(a[10]*a[10]);
rkc[137] = a[1]*a[24]/(a[10]*a[12]);
rkc[138] = a[12]*a[12]/(a[10]*a[13]);
rkc[139] = a[28]*exp_c0/(a[10]*a[14]);
rkc[140] = a[14]*a[23]/(a[10]*a[27]);
rkc[141] = a[10]*a[47]/(a[11]*a[47]);
rkc[142] = a[10]*a[48]/(a[11]*a[48]);
rkc[143] = a[1]*a[4]*a[14]/(a[3]*a[11]*exp_c0);
rkc[144] = a[5]*a[14]/(a[3]*a[11]);
rkc[145] = a[1]*a[12]/(a[0]*a[11]);
rkc[146] = a[20]*exp_c0/(a[5]*a[11]);
rkc[147] = a[5]*a[10]/(a[5]*a[11]);
rkc[148] = a[1]*a[24]/(a[11]*a[12]);
rkc[149] = a[12]*a[12]/(a[11]*a[13]);
rkc[150] = a[10]*a[14]/(a[11]*a[14]);
rkc[151] = a[10]*a[15]/(a[11]*a[15]);
rkc[152] = a[14]*a[17]/(a[11]*a[15]);
rkc[153] = a[12]*a[25]/(a[11]*a[26]);
rkc[154] = a[2]*a[19]/(a[3]*a[12]);
rkc[155] = a[4]*a[17]/(a[3]*a[12]);
rkc[156] = a[6]*a[13]/(a[7]*a[12]);
rkc[157] = a[26]*exp_c0/(a[12]*a[12]);
rkc[158] = a[1]*a[25]/(a[12]*a[12]);
rkc[159] = a[13]*a[14]/(a[12]*a[16]);
rkc[160] = a[13]*a[16]/(a[12]*a[17]);
rkc[161] = a[13]*a[18]/(a[12]*a[20]);
rkc[162] = a[13]*a[19]/(a[12]*a[20]);
rkc[163] = a[13]*a[23]/(a[12]*a[24]);
rkc[164] = a[13]*a[25]/(a[12]*a[26]);
rkc[165] = a[1]*a[5]*a[14]/(a[5]*a[16]*exp_c0);
rkc[166] = a[1]*a[14]/(a[16]*exp_c0);
rkc[167] = a[6]*a[14]/(a[3]*a[16]);
rkc[168] = a[6]*a[17]/(a[3]*a[18]);
rkc[169] = a[6]*a[17]/(a[3]*a[19]);
rkc[170] = a[14]*a[16]/(a[3]*a[21]);
rkc[171] = a[1]*a[22]/(a[0]*a[21]);
rkc[172] = a[16]*a[17]/(a[3]*a[23]);
rkc[173] = a[0]*a[22]/(a[24]*exp_c0);
rkc[174] = a[6]*a[24]/(a[3]*a[25]);
rkc[175] = a[4]*a[14]*a[14]/(a[3]*a[27]*exp_c0);
rkc[176] = a[14]*a[14]*a[22]/(a[27]*a[27]*exp_c0);
rkc[177] = a[2]*a[47]/(a[30]*a[35]);
rkc[178] = a[2]*a[35]/(a[3]*a[30]);
rkc[179] = a[1]*a[35]/(a[4]*a[30]);
rkc[180] = a[3]*a[47]/(a[2]*a[37]);
rkc[181] = a[35]*a[35]/(a[2]*a[37]);
rkc[182] = a[4]*a[47]/(a[1]*a[37]);
rkc[183] = a[6]*a[47]/(a[4]*a[37]);
rkc[184] = a[2]*a[47]/(a[37]*exp_c0);
rkc[185] = a[4]*a[36]/(a[6]*a[35]);
rkc[186] = a[36]*exp_c0/(a[2]*a[35]);
rkc[187] = a[3]*a[35]/(a[2]*a[36]);
rkc[188] = a[4]*a[35]/(a[1]*a[36]);
rkc[189] = a[1]*a[35]/(a[2]*a[31]);
rkc[190] = a[0]*a[30]/(a[1]*a[31]);
rkc[191] = a[1]*a[38]/(a[4]*a[31]);
rkc[192] = a[5]*a[30]/(a[4]*a[31]);
rkc[193] = a[2]*a[38]/(a[3]*a[31]);
rkc[194] = a[4]*a[35]/(a[3]*a[31]);
rkc[195] = a[1]*a[47]/(a[30]*a[31]);
rkc[196] = a[0]*a[38]/(a[5]*a[31]);
rkc[197] = a[4]*a[47]/(a[31]*a[35]);
rkc[198] = a[1]*a[37]/(a[31]*a[35]);
rkc[199] = a[4]*a[31]/(a[2]*a[32]);
rkc[200] = a[1]*a[38]/(a[2]*a[32]);
rkc[201] = a[0]*a[31]/(a[1]*a[32]);
rkc[202] = a[5]*a[31]/(a[4]*a[32]);
rkc[203] = a[1]*a[47]/(a[34]*exp_c0);
rkc[204] = a[1]*a[47]/(a[34]*exp_c0);
rkc[205] = a[6]*a[47]/(a[3]*a[34]);
rkc[206] = a[4]*a[47]/(a[2]*a[34]);
rkc[207] = a[31]*a[35]/(a[2]*a[34]);
rkc[208] = a[0]*a[47]/(a[1]*a[34]);
rkc[209] = a[5]*a[47]/(a[4]*a[34]);
rkc[210] = a[13]*a[47]/(a[12]*a[34]);
rkc[211] = a[38]*exp_c0/(a[1]*a[35]);
rkc[212] = a[4]*a[35]/(a[2]*a[38]);
rkc[213] = a[0]*a[35]/(a[1]*a[38]);
rkc[214] = a[5]*a[35]/(a[4]*a[38]);
rkc[215] = a[6]*a[35]/(a[3]*a[38]);
rkc[216] = a[14]*a[30]/(a[2]*a[39]);
rkc[217] = a[1]*a[46]/(a[4]*a[39]);
rkc[218] = a[4]*a[40]/(a[5]*a[39]);
rkc[219] = a[2]*a[46]/(a[3]*a[39]);
rkc[220] = a[1]*a[40]/(a[0]*a[39]);
rkc[221] = a[14]*a[35]/(a[2]*a[46]);
rkc[222] = a[14]*a[31]/(a[1]*a[46]);
rkc[223] = a[1]*a[14]*a[35]/(a[4]*a[46]*exp_c0);
rkc[224] = a[14]*a[47]/(a[30]*a[46]);
rkc[225] = a[15]*a[35]/(a[3]*a[46]);
rkc[226] = a[14]*a[30]/(a[46]*exp_c0);
rkc[227] = a[14]*a[37]/(a[35]*a[46]);
rkc[228] = a[15]*a[47]/(a[35]*a[46]);
rkc[229] = a[1]*a[39]/(a[40]*exp_c0);
rkc[230] = a[1]*a[46]/(a[2]*a[40]);
rkc[231] = a[14]*a[31]/(a[2]*a[40]);
rkc[232] = a[4]*a[39]/(a[2]*a[40]);
rkc[233] = a[1]*a[44]/(a[4]*a[40]);
rkc[234] = a[1]*a[45]/(a[4]*a[40]);
rkc[235] = a[14]*a[32]/(a[4]*a[40]);
rkc[236] = a[41]*exp_c0/(a[1]*a[40]);
rkc[237] = a[10]*a[47]/(a[30]*a[41]);
rkc[238] = a[30]*a[39]/(a[8]*a[47]);
rkc[239] = a[30]*a[40]/(a[9]*a[47]);
rkc[240] = a[42]*exp_c0/(a[9]*a[47]);
rkc[241] = a[31]*a[40]/(a[10]*a[47]);
rkc[242] = a[31]*a[40]/(a[11]*a[47]);
rkc[243] = a[2]*a[39]/(a[8]*a[35]);
rkc[244] = a[14]*a[30]/(a[8]*a[35]);
rkc[245] = a[2]*a[40]/(a[9]*a[35]);
rkc[246] = a[1]*a[46]/(a[9]*a[35]);
rkc[247] = a[16]*a[30]/(a[9]*a[35]);
rkc[248] = a[1]*a[45]/(a[10]*a[35]);
rkc[249] = a[4]*a[40]/(a[10]*a[35]);
rkc[250] = a[1]*a[43]/(a[10]*a[35]);
rkc[251] = a[1]*a[45]/(a[11]*a[35]);
rkc[252] = a[4]*a[40]/(a[11]*a[35]);
rkc[253] = a[1]*a[43]/(a[11]*a[35]);
rkc[254] = a[5]*a[40]/(a[12]*a[35]);
rkc[255] = a[4]*a[41]/(a[12]*a[35]);
rkc[256] = a[1]*a[14]*a[47]/(a[2]*a[42]*exp_c0);
rkc[257] = a[35]*a[40]/(a[2]*a[42]);
rkc[258] = a[2]*a[16]*a[47]/(a[3]*a[42]*exp_c0);
rkc[259] = a[1]*a[16]*a[47]/(a[4]*a[42]*exp_c0);
rkc[260] = a[10]*a[47]/(a[1]*a[42]);
rkc[261] = a[15]*a[31]/(a[2]*a[45]);
rkc[262] = a[14]*a[38]/(a[2]*a[45]);
rkc[263] = a[4]*a[46]/(a[2]*a[45]);
rkc[264] = a[14]*a[32]/(a[1]*a[45]);
rkc[265] = a[0]*a[46]/(a[1]*a[45]);
rkc[266] = a[5]*a[46]/(a[4]*a[45]);
rkc[267] = a[15]*a[32]/(a[4]*a[45]);
rkc[268] = a[14]*a[31]/(a[45]*exp_c0);
rkc[269] = a[1]*a[45]/(a[1]*a[43]);
rkc[270] = a[4]*a[40]/(a[1]*a[43]);
rkc[271] = a[14]*a[32]/(a[1]*a[43]);
rkc[272] = a[1]*a[45]/(a[1]*a[44]);
rkc[273] = a[14]*a[43]/(a[27]*a[35]);
rkc[274] = a[1]*a[41]/(a[12]*a[30]);
rkc[275] = a[0]*a[40]/(a[12]*a[30]);
rkc[276] = a[0]*a[32]/(a[1]*a[33]);
rkc[277] = a[5]*a[32]/(a[4]*a[33]);
rkc[278] = a[4]*a[32]/(a[2]*a[33]);
rkc[279] = a[14]*a[38]/(a[15]*a[31]);
rkc[280] = a[35]*a[46]/(a[36]*a[39]);
rkc[281] = a[15]*a[37]/(a[36]*a[46]);
rkc[282] = a[14]*a[35]/(a[15]*a[30]);
rkc[284] = a[1]*a[51]/(a[2]*a[24]);
rkc[285] = a[1]*a[52]/(a[2]*a[25]);
rkc[286] = a[3]*a[5]/(a[4]*a[6]);
rkc[288] = a[12]*exp_c0/(a[0]*a[9]);
rkc[290] = a[2]*a[17]/(a[3]*a[10]);
rkc[293] = a[2]*a[51]/(a[3]*a[23]);
rkc[294] = a[6]*a[22]/(a[3]*a[23]);
rkc[295] = a[4]*a[51]/(a[2]*a[52]);
rkc[298] = a[0]*a[51]/(a[1]*a[52]);
rkc[303] = a[51]*exp_c0/(a[1]*a[28]);
rkc[307] = a[12]*a[16]/(a[1]*a[51]);
rkc[308] = a[0]*a[28]/(a[1]*a[51]);
rkc[309] = a[5]*a[28]/(a[4]*a[51]);
rkc[310] = a[16]*a[18]/(a[4]*a[51]);
rkc[311] = a[50]*exp_c0/(a[12]*a[25]);
rkc[312] = a[4]*a[49]/(a[2]*a[50]);
rkc[313] = a[0]*a[49]/(a[1]*a[50]);
rkc[314] = a[5]*a[49]/(a[4]*a[50]);
rkc[315] = a[6]*a[50]/(a[7]*a[49]);
rkc[316] = a[13]*a[49]/(a[12]*a[50]);
rkc[317] = a[49]*exp_c0/(a[12]*a[24]);
rkc[318] = a[17]*a[25]/(a[2]*a[49]);
rkc[319] = a[50]*exp_c0/(a[1]*a[49]);
rkc[320] = a[12]*a[25]/(a[1]*a[49]);
rkc[321] = a[18]*a[25]/(a[4]*a[49]);
rkc[322] = a[3]*a[50]/(a[6]*a[49]);
rkc[324] = a[25]*a[25]/(a[12]*a[49]);
}
void GRI_30_Kinetics::get_wdot(const double* rop, double* wdot) {
wdot[0] = - rop[2] + rop[7] + rop[38] + rop[39] + rop[40] + rop[41] + rop[44] + rop[46] + rop[48] + rop[50] + rop[52] + rop[54] + rop[57] + rop[59] + rop[64] + rop[67] + rop[68] + rop[72] + rop[74] + rop[76] + rop[77] + rop[79] - rop[82] - rop[83] - rop[125] - rop[135] + rop[136] - rop[145] - rop[171] + rop[173] + rop[190] + rop[196] + rop[201] + rop[208] + rop[213] - rop[220] + rop[265] + rop[275] + rop[276] + rop[283] + rop[287] - rop[288] + rop[292] + rop[298] + rop[299] + rop[308] + rop[313];
wdot[1] = - rop[1] + rop[2] + rop[5] + rop[6] + rop[8] + rop[9] + rop[13] + rop[20] + rop[23] + rop[27] - rop[32] - rop[33] - rop[34] - rop[35] - rop[36] - rop[37] - 2*rop[38] - 2*rop[39] - 2*rop[40] - 2*rop[41] - rop[42] - rop[43] - rop[44] - rop[45] - rop[46] - rop[47] - rop[48] - rop[49] - rop[50] - rop[51] - rop[52] - rop[53] - rop[54] - rop[55] - rop[56] - rop[57] - rop[58] - rop[59] - rop[60] - rop[61] - rop[62] - rop[64] - rop[65] - rop[66] - rop[67] - rop[68] - rop[69] - rop[70] - rop[71] - rop[72] - rop[73] - rop[74] - rop[75] - rop[76] - rop[77] - rop[78] - rop[79] - rop[80] + rop[83] + rop[89] + rop[90] + rop[91] + rop[93] + rop[98] + rop[105] + rop[106] + rop[107] + rop[122] + rop[123] + rop[125] + rop[126] + rop[127] + rop[128] + rop[129] + rop[132] + rop[134] + rop[135] + rop[137] + rop[143] + rop[145] + rop[148] + rop[158] + rop[165] + rop[166] + rop[171] + rop[179] - rop[182] - rop[188] + rop[189] - rop[190] + rop[191] + rop[195] + rop[198] + rop[200] - rop[201] + rop[203] + rop[204] - rop[208] - rop[211] - rop[213] + rop[217] + rop[220] - rop[222] + rop[223] + rop[229] + rop[230] + rop[233] + rop[234] - rop[236] + rop[246] + rop[248] + rop[250] + rop[251] + rop[253] + rop[256] + rop[259] - rop[260] - rop[264] - rop[265] - rop[270] - rop[271] + rop[274] - rop[276] + rop[283] + rop[284] + rop[285] + 2*rop[289] + 2*rop[291] - rop[298] - rop[299] - rop[303] + rop[304] - rop[307] - rop[308] - rop[313] - rop[319] - rop[320];
wdot[2] = - 2*rop[0] - rop[1] - rop[2] - rop[3] - rop[4] - rop[5] - rop[6] - rop[7] - rop[8] - rop[9] - rop[10] - rop[11] - rop[12] - rop[13] - rop[14] - rop[15] - rop[16] - rop[17] - rop[18] - rop[19] - rop[20] - rop[21] - rop[22] - rop[23] - rop[24] - rop[25] - rop[26] - rop[27] - rop[28] - rop[29] + rop[30] + rop[37] + rop[43] + rop[85] + rop[121] + rop[124] + rop[154] + rop[177] + rop[178] - rop[180] - rop[181] + rop[184] - rop[186] - rop[187] - rop[189] + rop[193] - rop[199] - rop[200] - rop[206] - rop[207] - rop[212] - rop[216] + rop[219] - rop[221] - rop[230] - rop[231] - rop[232] + rop[243] + rop[245] - rop[256] - rop[257] + rop[258] - rop[261] - rop[262] - rop[263] - rop[278] - rop[283] - rop[284] - rop[285] + rop[290] + rop[293] - rop[295] - rop[296] - rop[304] - rop[312] - rop[318];
wdot[3] = + rop[0] + rop[3] - rop[30] - rop[31] - rop[32] - rop[33] - rop[34] - rop[35] - rop[36] - rop[37] + rop[44] + rop[86] + rop[114] + rop[115] + rop[117] - rop[121] - rop[124] - rop[134] - rop[143] - rop[144] - rop[154] - rop[155] - rop[167] - rop[168] - rop[169] - rop[170] - rop[172] - rop[174] - rop[175] - rop[178] + rop[180] + rop[187] - rop[193] - rop[194] - rop[205] - rop[215] - rop[219] - rop[225] - rop[258] + rop[286] - rop[289] - rop[290] - rop[293] - rop[294] - rop[297] - rop[305] - rop[306] + rop[322];
wdot[4] = + rop[1] + rop[2] + rop[3] + rop[4] + rop[10] + rop[12] + rop[14] + rop[15] + rop[16] + rop[17] + rop[18] + rop[21] + rop[26] + rop[28] + rop[37] - rop[42] + 2*rop[45] + rop[47] + rop[60] + rop[65] - rop[83] - 2*rop[84] - 2*rop[85] - rop[86] - rop[87] - rop[88] - rop[89] - rop[90] - rop[91] - rop[92] - rop[93] - rop[94] - rop[95] - rop[96] - rop[97] - rop[98] - rop[99] - rop[100] - rop[101] - rop[102] - rop[103] - rop[104] - rop[105] - rop[106] - rop[107] - rop[108] - rop[109] - rop[110] - rop[111] - rop[112] - rop[113] + rop[116] + rop[118] + rop[119] + rop[134] + rop[143] + rop[155] + rop[175] - rop[179] + rop[182] - rop[183] + rop[185] + rop[188] - rop[191] - rop[192] + rop[194] + rop[197] + rop[199] - rop[202] + rop[206] - rop[209] + rop[212] - rop[214] - rop[217] + rop[218] - rop[223] + rop[232] - rop[233] - rop[234] - rop[235] + rop[249] + rop[252] + rop[255] - rop[259] + rop[263] - rop[266] - rop[267] + rop[270] - rop[277] + rop[278] - rop[286] - rop[287] + rop[295] + rop[296] - rop[300] + rop[305] + rop[306] - rop[309] - rop[310] + rop[312] - rop[314] - rop[321] + rop[323];
wdot[5] = + rop[42] + rop[43] + rop[47] + rop[61] + rop[66] + rop[83] + rop[85] + rop[86] + rop[87] + rop[88] + rop[92] + rop[95] + rop[96] + rop[97] + rop[99] + rop[100] + rop[101] + rop[102] + rop[103] + rop[104] + rop[108] + rop[110] + rop[111] + rop[112] + rop[113] - rop[126] + rop[144] - rop[146] + rop[192] - rop[196] + rop[202] + rop[209] + rop[214] - rop[218] + rop[254] + rop[266] + rop[277] + rop[286] - rop[292] + rop[300] + rop[309] + rop[314];
wdot[6] = - rop[3] + rop[4] + rop[31] + rop[32] + rop[33] + rop[34] + rop[35] + rop[36] - rop[43] - rop[44] - rop[45] + rop[46] - rop[86] + rop[87] + rop[88] - 2*rop[114] - 2*rop[115] - rop[116] - rop[117] - rop[118] - rop[119] - rop[120] + rop[156] + rop[167] + rop[168] + rop[169] + rop[174] + rop[183] - rop[185] + rop[205] + rop[215] - rop[286] + rop[294] + rop[297] - rop[301] + rop[315] - rop[322] - rop[323];
wdot[7] = - rop[4] - rop[46] - rop[47] + rop[84] - rop[87] - rop[88] + rop[114] + rop[115] + rop[120] - rop[156] + rop[301] - rop[315];
wdot[8] = + rop[48] - rop[89] - rop[121] - rop[122] - rop[123] - rop[238] - rop[243] - rop[244];
wdot[9] = - rop[5] + rop[19] - rop[48] + rop[50] - rop[90] + rop[92] - rop[124] - rop[125] - rop[126] - rop[127] - rop[128] - rop[129] - rop[130] - rop[131] - rop[132] - rop[133] - rop[239] - rop[240] - rop[245] - rop[246] - rop[247] - rop[288];
wdot[10] = - rop[6] + rop[22] + rop[29] - rop[49] - rop[91] - rop[92] + rop[95] - rop[116] - rop[122] + rop[125] - rop[127] - rop[134] - rop[135] - 2*rop[136] - rop[137] - rop[138] - rop[139] - rop[140] + rop[141] + rop[142] + rop[147] + rop[150] + rop[151] + rop[237] - rop[241] - rop[248] - rop[249] - rop[250] + rop[260] - rop[289] - rop[290] - 2*rop[291] + rop[304];
wdot[11] = - rop[7] - rop[8] - rop[50] + rop[61] + rop[66] + rop[78] - rop[93] + rop[96] - rop[141] - rop[142] - rop[143] - rop[144] - rop[145] - rop[146] - rop[147] - rop[148] - rop[149] - rop[150] - rop[151] - rop[152] - rop[153] - rop[242] - rop[251] - rop[252] - rop[253] - rop[292];
wdot[12] = - rop[9] + rop[10] + rop[24] + rop[25] + rop[49] - rop[51] + rop[52] + rop[60] + rop[65] + rop[80] - rop[94] - rop[95] - rop[96] + rop[97] + rop[109] - rop[117] - rop[118] - rop[123] - rop[128] + rop[135] - rop[137] + 2*rop[138] + rop[145] - rop[148] + 2*rop[149] + rop[153] - rop[154] - rop[155] - rop[156] - 2*rop[157] - 2*rop[158] - rop[159] - rop[160] - rop[161] - rop[162] - rop[163] - rop[164] - rop[210] - rop[254] - rop[255] - rop[274] - rop[275] - rop[283] - rop[287] + rop[288] + rop[296] + rop[297] + rop[299] + rop[300] + rop[301] + rop[307] - rop[311] - rop[316] - rop[317] + rop[320] - rop[324];
wdot[13] = - rop[10] + rop[51] - rop[52] - rop[97] + rop[117] - rop[129] - rop[138] - rop[149] + rop[156] + rop[159] + rop[160] + rop[161] + rop[162] + rop[163] + rop[164] + rop[210] + rop[302] + rop[316];
wdot[14] = + rop[5] + rop[7] - rop[11] + rop[12] + rop[19] + rop[22] + 2*rop[27] - rop[30] + rop[54] + rop[78] + rop[80] - rop[82] + rop[89] - rop[98] + rop[99] + rop[109] - rop[119] + rop[121] - rop[130] + rop[131] + rop[133] + rop[134] - rop[139] + rop[140] + rop[143] + rop[144] + rop[152] + rop[159] + rop[165] + rop[166] + rop[167] + rop[170] + 2*rop[175] + 2*rop[176] + rop[216] + rop[221] + rop[222] + rop[223] + rop[224] + rop[226] + rop[227] + rop[231] + rop[235] + rop[244] + rop[256] + rop[262] + rop[264] + rop[268] + rop[271] + rop[273] + rop[279] + rop[282] + rop[283] + rop[296] + rop[297] + rop[299] + rop[300] + rop[301] + rop[302] + rop[305];
wdot[15] = + rop[11] + rop[13] + rop[29] + rop[30] + rop[98] + rop[119] - rop[131] - rop[152] + rop[225] + rop[228] + rop[261] + rop[267] - rop[279] + rop[281] - rop[282] + rop[289] + rop[304];
wdot[16] = + rop[6] + rop[8] - rop[12] - rop[13] + rop[14] + rop[24] + rop[31] - rop[53] - rop[54] + rop[57] + rop[90] - rop[99] + rop[100] + rop[120] + rop[124] + rop[131] - rop[159] + rop[160] - rop[165] - rop[166] - rop[167] + rop[170] + rop[172] + rop[247] + rop[258] + rop[259] + 2*rop[306] + rop[307] + rop[310];
wdot[17] = + rop[9] - rop[14] + rop[15] + rop[16] + rop[25] - rop[31] + rop[53] - rop[55] - rop[56] - rop[57] + rop[59] + rop[64] + rop[82] + rop[91] + rop[93] - rop[100] + rop[101] + rop[102] + rop[116] - rop[120] + rop[126] - rop[132] + rop[152] + rop[155] - rop[160] + rop[168] + rop[169] + rop[172] + rop[287] + rop[290] + rop[292] + rop[305] + rop[318] + rop[323];
wdot[18] = - rop[15] + rop[17] + rop[55] - rop[58] - rop[59] - rop[60] - rop[61] + rop[63] + rop[67] - rop[101] + rop[103] + rop[161] - rop[168] + rop[310] + rop[321];
wdot[19] = - rop[16] + rop[18] + rop[56] - rop[62] - rop[63] - rop[64] - rop[65] - rop[66] + rop[68] - rop[102] + rop[104] + rop[118] + rop[154] + rop[162] - rop[169];
wdot[20] = - rop[17] - rop[18] + rop[58] + rop[62] - rop[67] - rop[68] + rop[94] - rop[103] - rop[104] + rop[146] - rop[161] - rop[162];
wdot[21] = - rop[19] + rop[21] - rop[69] - rop[105] + rop[108] + rop[122] - rop[170] - rop[171];
wdot[22] = - rop[20] - rop[21] - rop[22] + rop[69] - rop[70] + rop[72] - rop[106] - rop[107] - rop[108] - rop[109] + rop[110] + rop[123] + rop[127] + rop[133] + rop[136] + rop[171] + rop[173] + rop[176] + rop[291] + rop[294];
wdot[23] = - rop[23] + rop[70] - rop[71] - rop[72] + rop[74] - rop[110] + rop[111] + rop[128] + rop[140] + rop[163] - rop[172] - rop[293] - rop[294];
wdot[24] = - rop[24] + rop[71] - rop[73] - rop[74] + rop[76] - rop[111] + rop[129] + rop[137] + rop[148] - rop[163] - rop[173] + rop[174] - rop[284] - rop[317];
wdot[25] = - rop[25] + rop[26] + rop[73] - rop[75] - rop[76] + rop[77] + rop[112] + rop[153] + rop[158] + rop[164] - rop[174] - rop[285] - rop[311] + rop[318] + rop[320] + rop[321] + rop[323] + 2*rop[324];
wdot[26] = - rop[26] + rop[75] - rop[77] - rop[112] - rop[153] + rop[157] - rop[164];
wdot[27] = + rop[20] - rop[27] + rop[28] - rop[78] + rop[79] + rop[105] + rop[113] + rop[130] - rop[133] - rop[140] - rop[175] - 2*rop[176] - rop[273];
wdot[28] = + rop[23] - rop[28] - rop[29] - rop[79] - rop[80] + rop[81] + rop[106] - rop[113] + rop[132] + rop[139] - rop[303] + rop[308] + rop[309];
wdot[29] = - rop[81] + rop[107];
wdot[30] = - rop[177] - rop[178] - rop[179] + rop[190] + rop[192] - rop[195] + rop[216] - rop[224] + rop[226] - rop[237] + rop[238] + rop[239] + rop[244] + rop[247] - rop[274] - rop[275] - rop[282];
wdot[31] = - rop[189] - rop[190] - rop[191] - rop[192] - rop[193] - rop[194] - rop[195] - rop[196] - rop[197] - rop[198] + rop[199] + rop[201] + rop[202] + rop[207] + rop[222] + rop[231] + rop[241] + rop[242] + rop[261] + rop[268] - rop[279];
wdot[32] = - rop[199] - rop[200] - rop[201] - rop[202] + rop[235] + rop[264] + rop[267] + rop[271] + rop[276] + rop[277] + rop[278];
wdot[33] = - rop[276] - rop[277] - rop[278];
wdot[34] = - rop[203] - rop[204] - rop[205] - rop[206] - rop[207] - rop[208] - rop[209] - rop[210];
wdot[35] = - rop[177] + rop[178] + rop[179] + 2*rop[181] - rop[185] - rop[186] + rop[187] + rop[188] + rop[189] + rop[194] - rop[197] - rop[198] + rop[207] - rop[211] + rop[212] + rop[213] + rop[214] + rop[215] + rop[221] + rop[223] + rop[225] - rop[227] - rop[228] - rop[243] - rop[244] - rop[245] - rop[246] - rop[247] - rop[248] - rop[249] - rop[250] - rop[251] - rop[252] - rop[253] - rop[254] - rop[255] + rop[257] - rop[273] + rop[280] + rop[282];
wdot[36] = + rop[185] + rop[186] - rop[187] - rop[188] - rop[280] - rop[281];
wdot[37] = - rop[180] - rop[181] - rop[182] - rop[183] - rop[184] + rop[198] + rop[227] + rop[281];
wdot[38] = + rop[191] + rop[193] + rop[196] + rop[200] + rop[211] - rop[212] - rop[213] - rop[214] - rop[215] + rop[262] + rop[279];
wdot[39] = - rop[216] - rop[217] - rop[218] - rop[219] - rop[220] + rop[229] + rop[232] + rop[238] + rop[243] - rop[280];
wdot[40] = + rop[218] + rop[220] - rop[229] - rop[230] - rop[231] - rop[232] - rop[233] - rop[234] - rop[235] - rop[236] + rop[239] + rop[241] + rop[242] + rop[245] + rop[249] + rop[252] + rop[254] + rop[257] + rop[270] + rop[275];
wdot[41] = + rop[236] - rop[237] + rop[255] + rop[274];
wdot[42] = + rop[240] - rop[256] - rop[257] - rop[258] - rop[259] - rop[260];
wdot[43] = + rop[250] + rop[253] - rop[269] - rop[270] - rop[271] + rop[273];
wdot[44] = + rop[233] - rop[272];
wdot[45] = + rop[234] + rop[248] + rop[251] - rop[261] - rop[262] - rop[263] - rop[264] - rop[265] - rop[266] - rop[267] - rop[268] + rop[269] + rop[272];
wdot[46] = + rop[217] + rop[219] - rop[221] - rop[222] - rop[223] - rop[224] - rop[225] - rop[226] - rop[227] - rop[228] + rop[230] + rop[246] + rop[263] + rop[265] + rop[266] + rop[280] - rop[281];
wdot[47] = + rop[177] + rop[180] + rop[182] + rop[183] + rop[184] + rop[195] + rop[197] + rop[203] + rop[204] + rop[205] + rop[206] + rop[208] + rop[209] + rop[210] + rop[224] + rop[228] + rop[237] - rop[238] - rop[239] - rop[240] - rop[241] - rop[242] + rop[256] + rop[258] + rop[259] + rop[260];
wdot[48] = 0.0;
wdot[49] = + rop[312] + rop[313] + rop[314] - rop[315] + rop[316] + rop[317] - rop[318] - rop[319] - rop[320] - rop[321] - rop[322] - rop[323] - rop[324];
wdot[50] = + rop[311] - rop[312] - rop[313] - rop[314] + rop[315] - rop[316] + rop[319] + rop[322];
wdot[51] = + rop[284] + rop[293] + rop[295] + rop[298] + rop[303] - rop[304] - rop[305] - rop[306] - rop[307] - rop[308] - rop[309] - rop[310];
wdot[52] = + rop[285] - rop[295] - rop[296] - rop[297] - rop[298] - rop[299] - rop[300] - rop[301] - rop[302];
}
void GRI_30_Kinetics::eval_ropnet(const double* c, const double* rf, const double* rkc, double* r) {
r[0] = rf[0] * (c[2] * c[2] - rkc[0] * c[3]);
r[1] = rf[1] * (c[2] * c[1] - rkc[1] * c[4]);
r[2] = rf[2] * (c[2] * c[0] - rkc[2] * c[1] * c[4]);
r[3] = rf[3] * (c[2] * c[6] - rkc[3] * c[4] * c[3]);
r[4] = rf[4] * (c[2] * c[7] - rkc[4] * c[4] * c[6]);
r[5] = rf[5] * (c[2] * c[9] - rkc[5] * c[1] * c[14]);
r[6] = rf[6] * (c[2] * c[10] - rkc[6] * c[1] * c[16]);
r[7] = rf[7] * (c[2] * c[11] - rkc[7] * c[0] * c[14]);
r[8] = rf[8] * (c[2] * c[11] - rkc[8] * c[1] * c[16]);
r[9] = rf[9] * (c[2] * c[12] - rkc[9] * c[1] * c[17]);
r[10] = rf[10] * (c[2] * c[13] - rkc[10] * c[4] * c[12]);
r[11] = rf[11] * (c[2] * c[14] - rkc[11] * c[15]);
r[12] = rf[12] * (c[2] * c[16] - rkc[12] * c[4] * c[14]);
r[13] = rf[13] * (c[2] * c[16] - rkc[13] * c[1] * c[15]);
r[14] = rf[14] * (c[2] * c[17] - rkc[14] * c[4] * c[16]);
r[15] = rf[15] * (c[2] * c[18] - rkc[15] * c[4] * c[17]);
r[16] = rf[16] * (c[2] * c[19] - rkc[16] * c[4] * c[17]);
r[17] = rf[17] * (c[2] * c[20] - rkc[17] * c[4] * c[18]);
r[18] = rf[18] * (c[2] * c[20] - rkc[18] * c[4] * c[19]);
r[19] = rf[19] * (c[2] * c[21] - rkc[19] * c[9] * c[14]);
r[20] = rf[20] * (c[2] * c[22] - rkc[20] * c[1] * c[27]);
r[21] = rf[21] * (c[2] * c[22] - rkc[21] * c[4] * c[21]);
r[22] = rf[22] * (c[2] * c[22] - rkc[22] * c[14] * c[10]);
r[23] = rf[23] * (c[2] * c[23] - rkc[23] * c[1] * c[28]);
r[24] = rf[24] * (c[2] * c[24] - rkc[24] * c[12] * c[16]);
r[25] = rf[25] * (c[2] * c[25] - rkc[25] * c[12] * c[17]);
r[26] = rf[26] * (c[2] * c[26] - rkc[26] * c[4] * c[25]);
r[27] = rf[27] * (c[2] * c[27] - rkc[27] * c[1] * c[14] * c[14]);
r[28] = rf[28] * (c[2] * c[28] - rkc[28] * c[4] * c[27]);
r[29] = rf[29] * (c[2] * c[28] - rkc[29] * c[10] * c[15]);
r[30] = rf[30] * (c[3] * c[14] - rkc[30] * c[2] * c[15]);
r[31] = rf[31] * (c[3] * c[17] - rkc[31] * c[6] * c[16]);
r[32] = rf[32] * (c[1] * c[3] - rkc[32] * c[6]);
r[33] = rf[33] * (c[1] * c[3] * c[3] - rkc[33] * c[6] * c[3]);
r[34] = rf[34] * (c[1] * c[3] * c[5] - rkc[34] * c[6] * c[5]);
r[35] = rf[35] * (c[1] * c[3] * c[47] - rkc[35] * c[6] * c[47]);
r[36] = rf[36] * (c[1] * c[3] * c[48] - rkc[36] * c[6] * c[48]);
r[37] = rf[37] * (c[1] * c[3] - rkc[37] * c[2] * c[4]);
r[38] = rf[38] * (c[1] * c[1] - rkc[38] * c[0]);
r[39] = rf[39] * (c[1] * c[1] * c[0] - rkc[39] * c[0] * c[0]);
r[40] = rf[40] * (c[1] * c[1] * c[5] - rkc[40] * c[0] * c[5]);
r[41] = rf[41] * (c[1] * c[1] * c[15] - rkc[41] * c[0] * c[15]);
r[42] = rf[42] * (c[1] * c[4] - rkc[42] * c[5]);
r[43] = rf[43] * (c[1] * c[6] - rkc[43] * c[2] * c[5]);
r[44] = rf[44] * (c[1] * c[6] - rkc[44] * c[3] * c[0]);
r[45] = rf[45] * (c[1] * c[6] - rkc[45] * c[4] * c[4]);
r[46] = rf[46] * (c[1] * c[7] - rkc[46] * c[6] * c[0]);
r[47] = rf[47] * (c[1] * c[7] - rkc[47] * c[4] * c[5]);
r[48] = rf[48] * (c[1] * c[9] - rkc[48] * c[8] * c[0]);
r[49] = rf[49] * (c[1] * c[10] - rkc[49] * c[12]);
r[50] = rf[50] * (c[1] * c[11] - rkc[50] * c[9] * c[0]);
r[51] = rf[51] * (c[1] * c[12] - rkc[51] * c[13]);
r[52] = rf[52] * (c[1] * c[13] - rkc[52] * c[12] * c[0]);
r[53] = rf[53] * (c[1] * c[16] - rkc[53] * c[17]);
r[54] = rf[54] * (c[1] * c[16] - rkc[54] * c[0] * c[14]);
r[55] = rf[55] * (c[1] * c[17] - rkc[55] * c[18]);
r[56] = rf[56] * (c[1] * c[17] - rkc[56] * c[19]);
r[57] = rf[57] * (c[1] * c[17] - rkc[57] * c[16] * c[0]);
r[58] = rf[58] * (c[1] * c[18] - rkc[58] * c[20]);
r[59] = rf[59] * (c[1] * c[18] - rkc[59] * c[0] * c[17]);
r[60] = rf[60] * (c[1] * c[18] - rkc[60] * c[4] * c[12]);
r[61] = rf[61] * (c[1] * c[18] - rkc[61] * c[11] * c[5]);
r[62] = rf[62] * (c[1] * c[19] - rkc[62] * c[20]);
r[63] = rf[63] * (c[1] * c[19] - rkc[63] * c[1] * c[18]);
r[64] = rf[64] * (c[1] * c[19] - rkc[64] * c[0] * c[17]);
r[65] = rf[65] * (c[1] * c[19] - rkc[65] * c[4] * c[12]);
r[66] = rf[66] * (c[1] * c[19] - rkc[66] * c[11] * c[5]);
r[67] = rf[67] * (c[1] * c[20] - rkc[67] * c[18] * c[0]);
r[68] = rf[68] * (c[1] * c[20] - rkc[68] * c[19] * c[0]);
r[69] = rf[69] * (c[1] * c[21] - rkc[69] * c[22]);
r[70] = rf[70] * (c[1] * c[22] - rkc[70] * c[23]);
r[71] = rf[71] * (c[1] * c[23] - rkc[71] * c[24]);
r[72] = rf[72] * (c[1] * c[23] - rkc[72] * c[0] * c[22]);
r[73] = rf[73] * (c[1] * c[24] - rkc[73] * c[25]);
r[74] = rf[74] * (c[1] * c[24] - rkc[74] * c[23] * c[0]);
r[75] = rf[75] * (c[1] * c[25] - rkc[75] * c[26]);
r[76] = rf[76] * (c[1] * c[25] - rkc[76] * c[0] * c[24]);
r[77] = rf[77] * (c[1] * c[26] - rkc[77] * c[25] * c[0]);
r[78] = rf[78] * (c[1] * c[27] - rkc[78] * c[11] * c[14]);
r[79] = rf[79] * (c[1] * c[28] - rkc[79] * c[27] * c[0]);
r[80] = rf[80] * (c[1] * c[28] - rkc[80] * c[12] * c[14]);
r[81] = rf[81] * (c[1] * c[29] - rkc[81] * c[1] * c[28]);
r[82] = rf[82] * (c[0] * c[14] - rkc[82] * c[17]);
r[83] = rf[83] * (c[4] * c[0] - rkc[83] * c[1] * c[5]);
r[84] = rf[84] * (c[4] * c[4] - rkc[84] * c[7]);
r[85] = rf[85] * (c[4] * c[4] - rkc[85] * c[2] * c[5]);
r[86] = rf[86] * (c[4] * c[6] - rkc[86] * c[3] * c[5]);
r[87] = rf[87] * (c[4] * c[7] - rkc[87] * c[6] * c[5]);
r[88] = rf[88] * (c[4] * c[7] - rkc[88] * c[6] * c[5]);
r[89] = rf[89] * (c[4] * c[8] - rkc[89] * c[1] * c[14]);
r[90] = rf[90] * (c[4] * c[9] - rkc[90] * c[1] * c[16]);
r[91] = rf[91] * (c[4] * c[10] - rkc[91] * c[1] * c[17]);
r[92] = rf[92] * (c[4] * c[10] - rkc[92] * c[9] * c[5]);
r[93] = rf[93] * (c[4] * c[11] - rkc[93] * c[1] * c[17]);
r[94] = rf[94] * (c[4] * c[12] - rkc[94] * c[20]);
r[95] = rf[95] * (c[4] * c[12] - rkc[95] * c[10] * c[5]);
r[96] = rf[96] * (c[4] * c[12] - rkc[96] * c[11] * c[5]);
r[97] = rf[97] * (c[4] * c[13] - rkc[97] * c[12] * c[5]);
r[98] = rf[98] * (c[4] * c[14] - rkc[98] * c[1] * c[15]);
r[99] = rf[99] * (c[4] * c[16] - rkc[99] * c[5] * c[14]);
r[100] = rf[100] * (c[4] * c[17] - rkc[100] * c[16] * c[5]);
r[101] = rf[101] * (c[4] * c[18] - rkc[101] * c[5] * c[17]);
r[102] = rf[102] * (c[4] * c[19] - rkc[102] * c[5] * c[17]);
r[103] = rf[103] * (c[4] * c[20] - rkc[103] * c[18] * c[5]);
r[104] = rf[104] * (c[4] * c[20] - rkc[104] * c[19] * c[5]);
r[105] = rf[105] * (c[4] * c[21] - rkc[105] * c[1] * c[27]);
r[106] = rf[106] * (c[4] * c[22] - rkc[106] * c[1] * c[28]);
r[107] = rf[107] * (c[4] * c[22] - rkc[107] * c[1] * c[29]);
r[108] = rf[108] * (c[4] * c[22] - rkc[108] * c[21] * c[5]);
r[109] = rf[109] * (c[4] * c[22] - rkc[109] * c[12] * c[14]);
r[110] = rf[110] * (c[4] * c[23] - rkc[110] * c[5] * c[22]);
r[111] = rf[111] * (c[4] * c[24] - rkc[111] * c[23] * c[5]);
r[112] = rf[112] * (c[4] * c[26] - rkc[112] * c[25] * c[5]);
r[113] = rf[113] * (c[4] * c[28] - rkc[113] * c[27] * c[5]);
r[114] = rf[114] * (c[6] * c[6] - rkc[114] * c[3] * c[7]);
r[115] = rf[115] * (c[6] * c[6] - rkc[115] * c[3] * c[7]);
r[116] = rf[116] * (c[6] * c[10] - rkc[116] * c[4] * c[17]);
r[117] = rf[117] * (c[6] * c[12] - rkc[117] * c[3] * c[13]);
r[118] = rf[118] * (c[6] * c[12] - rkc[118] * c[4] * c[19]);
r[119] = rf[119] * (c[6] * c[14] - rkc[119] * c[4] * c[15]);
r[120] = rf[120] * (c[6] * c[17] - rkc[120] * c[16] * c[7]);
r[121] = rf[121] * (c[8] * c[3] - rkc[121] * c[2] * c[14]);
r[122] = rf[122] * (c[8] * c[10] - rkc[122] * c[1] * c[21]);
r[123] = rf[123] * (c[8] * c[12] - rkc[123] * c[1] * c[22]);
r[124] = rf[124] * (c[9] * c[3] - rkc[124] * c[2] * c[16]);
r[125] = rf[125] * (c[9] * c[0] - rkc[125] * c[1] * c[10]);
r[126] = rf[126] * (c[9] * c[5] - rkc[126] * c[1] * c[17]);
r[127] = rf[127] * (c[9] * c[10] - rkc[127] * c[1] * c[22]);
r[128] = rf[128] * (c[9] * c[12] - rkc[128] * c[1] * c[23]);
r[129] = rf[129] * (c[9] * c[13] - rkc[129] * c[1] * c[24]);
r[130] = rf[130] * (c[9] * c[14] - rkc[130] * c[27]);
r[131] = rf[131] * (c[9] * c[15] - rkc[131] * c[16] * c[14]);
r[132] = rf[132] * (c[9] * c[17] - rkc[132] * c[1] * c[28]);
r[133] = rf[133] * (c[9] * c[27] - rkc[133] * c[14] * c[22]);
r[134] = rf[134] * (c[10] * c[3]);
r[135] = rf[135] * (c[10] * c[0] - rkc[135] * c[1] * c[12]);
r[136] = rf[136] * (c[10] * c[10] - rkc[136] * c[0] * c[22]);
r[137] = rf[137] * (c[10] * c[12] - rkc[137] * c[1] * c[24]);
r[138] = rf[138] * (c[10] * c[13] - rkc[138] * c[12] * c[12]);
r[139] = rf[139] * (c[10] * c[14] - rkc[139] * c[28]);
r[140] = rf[140] * (c[10] * c[27] - rkc[140] * c[23] * c[14]);
r[141] = rf[141] * (c[11] * c[47] - rkc[141] * c[10] * c[47]);
r[142] = rf[142] * (c[11] * c[48] - rkc[142] * c[10] * c[48]);
r[143] = rf[143] * (c[11] * c[3] - rkc[143] * c[1] * c[4] * c[14]);
r[144] = rf[144] * (c[11] * c[3] - rkc[144] * c[14] * c[5]);
r[145] = rf[145] * (c[11] * c[0] - rkc[145] * c[12] * c[1]);
r[146] = rf[146] * (c[11] * c[5] - rkc[146] * c[20]);
r[147] = rf[147] * (c[11] * c[5] - rkc[147] * c[10] * c[5]);
r[148] = rf[148] * (c[11] * c[12] - rkc[148] * c[1] * c[24]);
r[149] = rf[149] * (c[11] * c[13] - rkc[149] * c[12] * c[12]);
r[150] = rf[150] * (c[11] * c[14] - rkc[150] * c[10] * c[14]);
r[151] = rf[151] * (c[11] * c[15] - rkc[151] * c[10] * c[15]);
r[152] = rf[152] * (c[11] * c[15] - rkc[152] * c[14] * c[17]);
r[153] = rf[153] * (c[11] * c[26] - rkc[153] * c[12] * c[25]);
r[154] = rf[154] * (c[12] * c[3] - rkc[154] * c[2] * c[19]);
r[155] = rf[155] * (c[12] * c[3] - rkc[155] * c[4] * c[17]);
r[156] = rf[156] * (c[12] * c[7] - rkc[156] * c[6] * c[13]);
r[157] = rf[157] * (c[12] * c[12] - rkc[157] * c[26]);
r[158] = rf[158] * (c[12] * c[12] - rkc[158] * c[1] * c[25]);
r[159] = rf[159] * (c[12] * c[16] - rkc[159] * c[13] * c[14]);
r[160] = rf[160] * (c[12] * c[17] - rkc[160] * c[16] * c[13]);
r[161] = rf[161] * (c[12] * c[20] - rkc[161] * c[18] * c[13]);
r[162] = rf[162] * (c[12] * c[20] - rkc[162] * c[19] * c[13]);
r[163] = rf[163] * (c[12] * c[24] - rkc[163] * c[23] * c[13]);
r[164] = rf[164] * (c[12] * c[26] - rkc[164] * c[25] * c[13]);
r[165] = rf[165] * (c[16] * c[5] - rkc[165] * c[1] * c[14] * c[5]);
r[166] = rf[166] * (c[16] - rkc[166] * c[1] * c[14]);
r[167] = rf[167] * (c[16] * c[3] - rkc[167] * c[6] * c[14]);
r[168] = rf[168] * (c[18] * c[3] - rkc[168] * c[6] * c[17]);
r[169] = rf[169] * (c[19] * c[3] - rkc[169] * c[6] * c[17]);
r[170] = rf[170] * (c[21] * c[3] - rkc[170] * c[16] * c[14]);
r[171] = rf[171] * (c[21] * c[0] - rkc[171] * c[1] * c[22]);
r[172] = rf[172] * (c[23] * c[3] - rkc[172] * c[16] * c[17]);
r[173] = rf[173] * (c[24] - rkc[173] * c[0] * c[22]);
r[174] = rf[174] * (c[25] * c[3] - rkc[174] * c[6] * c[24]);
r[175] = rf[175] * (c[27] * c[3] - rkc[175] * c[4] * c[14] * c[14]);
r[176] = rf[176] * (c[27] * c[27] - rkc[176] * c[14] * c[14] * c[22]);
r[177] = rf[177] * (c[30] * c[35] - rkc[177] * c[47] * c[2]);
r[178] = rf[178] * (c[30] * c[3] - rkc[178] * c[35] * c[2]);
r[179] = rf[179] * (c[30] * c[4] - rkc[179] * c[35] * c[1]);
r[180] = rf[180] * (c[37] * c[2] - rkc[180] * c[47] * c[3]);
r[181] = rf[181] * (c[37] * c[2] - rkc[181] * c[35] * c[35]);
r[182] = rf[182] * (c[37] * c[1] - rkc[182] * c[47] * c[4]);
r[183] = rf[183] * (c[37] * c[4] - rkc[183] * c[47] * c[6]);
r[184] = rf[184] * (c[37] - rkc[184] * c[47] * c[2]);
r[185] = rf[185] * (c[6] * c[35] - rkc[185] * c[36] * c[4]);
r[186] = rf[186] * (c[35] * c[2] - rkc[186] * c[36]);
r[187] = rf[187] * (c[36] * c[2] - rkc[187] * c[35] * c[3]);
r[188] = rf[188] * (c[36] * c[1] - rkc[188] * c[35] * c[4]);
r[189] = rf[189] * (c[31] * c[2] - rkc[189] * c[35] * c[1]);
r[190] = rf[190] * (c[31] * c[1] - rkc[190] * c[30] * c[0]);
r[191] = rf[191] * (c[31] * c[4] - rkc[191] * c[38] * c[1]);
r[192] = rf[192] * (c[31] * c[4] - rkc[192] * c[30] * c[5]);
r[193] = rf[193] * (c[31] * c[3] - rkc[193] * c[38] * c[2]);
r[194] = rf[194] * (c[31] * c[3] - rkc[194] * c[35] * c[4]);
r[195] = rf[195] * (c[31] * c[30] - rkc[195] * c[47] * c[1]);
r[196] = rf[196] * (c[31] * c[5] - rkc[196] * c[38] * c[0]);
r[197] = rf[197] * (c[31] * c[35] - rkc[197] * c[47] * c[4]);
r[198] = rf[198] * (c[31] * c[35] - rkc[198] * c[37] * c[1]);
r[199] = rf[199] * (c[32] * c[2] - rkc[199] * c[4] * c[31]);
r[200] = rf[200] * (c[32] * c[2] - rkc[200] * c[1] * c[38]);
r[201] = rf[201] * (c[32] * c[1] - rkc[201] * c[31] * c[0]);
r[202] = rf[202] * (c[32] * c[4] - rkc[202] * c[31] * c[5]);
r[203] = rf[203] * (c[34] - rkc[203] * c[47] * c[1]);
r[204] = rf[204] * (c[34] - rkc[204] * c[47] * c[1]);
r[205] = rf[205] * (c[34] * c[3] - rkc[205] * c[6] * c[47]);
r[206] = rf[206] * (c[34] * c[2] - rkc[206] * c[4] * c[47]);
r[207] = rf[207] * (c[34] * c[2] - rkc[207] * c[31] * c[35]);
r[208] = rf[208] * (c[34] * c[1] - rkc[208] * c[0] * c[47]);
r[209] = rf[209] * (c[34] * c[4] - rkc[209] * c[5] * c[47]);
r[210] = rf[210] * (c[34] * c[12] - rkc[210] * c[13] * c[47]);
r[211] = rf[211] * (c[1] * c[35] - rkc[211] * c[38]);
r[212] = rf[212] * (c[38] * c[2] - rkc[212] * c[35] * c[4]);
r[213] = rf[213] * (c[38] * c[1] - rkc[213] * c[0] * c[35]);
r[214] = rf[214] * (c[38] * c[4] - rkc[214] * c[35] * c[5]);
r[215] = rf[215] * (c[38] * c[3] - rkc[215] * c[6] * c[35]);
r[216] = rf[216] * (c[39] * c[2] - rkc[216] * c[14] * c[30]);
r[217] = rf[217] * (c[39] * c[4] - rkc[217] * c[46] * c[1]);
r[218] = rf[218] * (c[39] * c[5] - rkc[218] * c[40] * c[4]);
r[219] = rf[219] * (c[39] * c[3] - rkc[219] * c[46] * c[2]);
r[220] = rf[220] * (c[39] * c[0] - rkc[220] * c[40] * c[1]);
r[221] = rf[221] * (c[46] * c[2] - rkc[221] * c[35] * c[14]);
r[222] = rf[222] * (c[46] * c[1] - rkc[222] * c[31] * c[14]);
r[223] = rf[223] * (c[46] * c[4] - rkc[223] * c[35] * c[1] * c[14]);
r[224] = rf[224] * (c[46] * c[30] - rkc[224] * c[47] * c[14]);
r[225] = rf[225] * (c[46] * c[3] - rkc[225] * c[35] * c[15]);
r[226] = rf[226] * (c[46] - rkc[226] * c[30] * c[14]);
r[227] = rf[227] * (c[46] * c[35] - rkc[227] * c[37] * c[14]);
r[228] = rf[228] * (c[46] * c[35] - rkc[228] * c[47] * c[15]);
r[229] = rf[229] * (c[40] - rkc[229] * c[1] * c[39]);
r[230] = rf[230] * (c[40] * c[2] - rkc[230] * c[46] * c[1]);
r[231] = rf[231] * (c[40] * c[2] - rkc[231] * c[31] * c[14]);
r[232] = rf[232] * (c[40] * c[2] - rkc[232] * c[39] * c[4]);
r[233] = rf[233] * (c[40] * c[4] - rkc[233] * c[44] * c[1]);
r[234] = rf[234] * (c[40] * c[4] - rkc[234] * c[45] * c[1]);
r[235] = rf[235] * (c[40] * c[4] - rkc[235] * c[32] * c[14]);
r[236] = rf[236] * (c[1] * c[40] - rkc[236] * c[41]);
r[237] = rf[237] * (c[41] * c[30] - rkc[237] * c[47] * c[10]);
r[238] = rf[238] * (c[8] * c[47] - rkc[238] * c[39] * c[30]);
r[239] = rf[239] * (c[9] * c[47] - rkc[239] * c[40] * c[30]);
r[240] = rf[240] * (c[9] * c[47] - rkc[240] * c[42]);
r[241] = rf[241] * (c[10] * c[47] - rkc[241] * c[40] * c[31]);
r[242] = rf[242] * (c[11] * c[47] - rkc[242] * c[31] * c[40]);
r[243] = rf[243] * (c[8] * c[35] - rkc[243] * c[39] * c[2]);
r[244] = rf[244] * (c[8] * c[35] - rkc[244] * c[14] * c[30]);
r[245] = rf[245] * (c[9] * c[35] - rkc[245] * c[40] * c[2]);
r[246] = rf[246] * (c[9] * c[35] - rkc[246] * c[1] * c[46]);
r[247] = rf[247] * (c[9] * c[35] - rkc[247] * c[30] * c[16]);
r[248] = rf[248] * (c[10] * c[35] - rkc[248] * c[1] * c[45]);
r[249] = rf[249] * (c[10] * c[35] - rkc[249] * c[4] * c[40]);
r[250] = rf[250] * (c[10] * c[35] - rkc[250] * c[1] * c[43]);
r[251] = rf[251] * (c[11] * c[35] - rkc[251] * c[1] * c[45]);
r[252] = rf[252] * (c[11] * c[35] - rkc[252] * c[4] * c[40]);
r[253] = rf[253] * (c[11] * c[35] - rkc[253] * c[1] * c[43]);
r[254] = rf[254] * (c[12] * c[35] - rkc[254] * c[40] * c[5]);
r[255] = rf[255] * (c[12] * c[35] - rkc[255] * c[41] * c[4]);
r[256] = rf[256] * (c[42] * c[2] - rkc[256] * c[14] * c[1] * c[47]);
r[257] = rf[257] * (c[42] * c[2] - rkc[257] * c[40] * c[35]);
r[258] = rf[258] * (c[42] * c[3] - rkc[258] * c[2] * c[16] * c[47]);
r[259] = rf[259] * (c[42] * c[4] - rkc[259] * c[1] * c[16] * c[47]);
r[260] = rf[260] * (c[42] * c[1] - rkc[260] * c[10] * c[47]);
r[261] = rf[261] * (c[45] * c[2] - rkc[261] * c[31] * c[15]);
r[262] = rf[262] * (c[45] * c[2] - rkc[262] * c[38] * c[14]);
r[263] = rf[263] * (c[45] * c[2] - rkc[263] * c[46] * c[4]);
r[264] = rf[264] * (c[45] * c[1] - rkc[264] * c[32] * c[14]);
r[265] = rf[265] * (c[45] * c[1] - rkc[265] * c[0] * c[46]);
r[266] = rf[266] * (c[45] * c[4] - rkc[266] * c[46] * c[5]);
r[267] = rf[267] * (c[45] * c[4] - rkc[267] * c[32] * c[15]);
r[268] = rf[268] * (c[45] - rkc[268] * c[31] * c[14]);
r[269] = rf[269] * (c[43] * c[1] - rkc[269] * c[1] * c[45]);
r[270] = rf[270] * (c[43] * c[1] - rkc[270] * c[4] * c[40]);
r[271] = rf[271] * (c[43] * c[1] - rkc[271] * c[32] * c[14]);
r[272] = rf[272] * (c[44] * c[1] - rkc[272] * c[1] * c[45]);
r[273] = rf[273] * (c[27] * c[35] - rkc[273] * c[43] * c[14]);
r[274] = rf[274] * (c[12] * c[30] - rkc[274] * c[41] * c[1]);
r[275] = rf[275] * (c[12] * c[30] - rkc[275] * c[40] * c[0]);
r[276] = rf[276] * (c[33] * c[1] - rkc[276] * c[32] * c[0]);
r[277] = rf[277] * (c[33] * c[4] - rkc[277] * c[32] * c[5]);
r[278] = rf[278] * (c[33] * c[2] - rkc[278] * c[32] * c[4]);
r[279] = rf[279] * (c[31] * c[15] - rkc[279] * c[38] * c[14]);
r[280] = rf[280] * (c[39] * c[36] - rkc[280] * c[46] * c[35]);
r[281] = rf[281] * (c[46] * c[36] - rkc[281] * c[37] * c[15]);
r[282] = rf[282] * (c[30] * c[15] - rkc[282] * c[35] * c[14]);
r[283] = rf[283] * (c[2] * c[12]);
r[284] = rf[284] * (c[2] * c[24] - rkc[284] * c[1] * c[51]);
r[285] = rf[285] * (c[2] * c[25] - rkc[285] * c[1] * c[52]);
r[286] = rf[286] * (c[4] * c[6] - rkc[286] * c[3] * c[5]);
r[287] = rf[287] * (c[4] * c[12]);
r[288] = rf[288] * (c[9] * c[0] - rkc[288] * c[12]);
r[289] = rf[289] * (c[10] * c[3]);
r[290] = rf[290] * (c[10] * c[3] - rkc[290] * c[2] * c[17]);
r[291] = rf[291] * (c[10] * c[10]);
r[292] = rf[292] * (c[11] * c[5]);
r[293] = rf[293] * (c[23] * c[3] - rkc[293] * c[2] * c[51]);
r[294] = rf[294] * (c[23] * c[3] - rkc[294] * c[6] * c[22]);
r[295] = rf[295] * (c[2] * c[52] - rkc[295] * c[4] * c[51]);
r[296] = rf[296] * (c[2] * c[52]);
r[297] = rf[297] * (c[3] * c[52]);
r[298] = rf[298] * (c[1] * c[52] - rkc[298] * c[51] * c[0]);
r[299] = rf[299] * (c[1] * c[52]);
r[300] = rf[300] * (c[4] * c[52]);
r[301] = rf[301] * (c[6] * c[52]);
r[302] = rf[302] * (c[12] * c[52]);
r[303] = rf[303] * (c[1] * c[28] - rkc[303] * c[51]);
r[304] = rf[304] * (c[2] * c[51]);
r[305] = rf[305] * (c[3] * c[51]);
r[306] = rf[306] * (c[3] * c[51]);
r[307] = rf[307] * (c[1] * c[51] - rkc[307] * c[12] * c[16]);
r[308] = rf[308] * (c[1] * c[51] - rkc[308] * c[28] * c[0]);
r[309] = rf[309] * (c[4] * c[51] - rkc[309] * c[5] * c[28]);
r[310] = rf[310] * (c[4] * c[51] - rkc[310] * c[16] * c[18]);
r[311] = rf[311] * (c[12] * c[25] - rkc[311] * c[50]);
r[312] = rf[312] * (c[2] * c[50] - rkc[312] * c[4] * c[49]);
r[313] = rf[313] * (c[1] * c[50] - rkc[313] * c[49] * c[0]);
r[314] = rf[314] * (c[4] * c[50] - rkc[314] * c[49] * c[5]);
r[315] = rf[315] * (c[49] * c[7] - rkc[315] * c[6] * c[50]);
r[316] = rf[316] * (c[12] * c[50] - rkc[316] * c[49] * c[13]);
r[317] = rf[317] * (c[12] * c[24] - rkc[317] * c[49]);
r[318] = rf[318] * (c[2] * c[49] - rkc[318] * c[25] * c[17]);
r[319] = rf[319] * (c[1] * c[49] - rkc[319] * c[50]);
r[320] = rf[320] * (c[1] * c[49] - rkc[320] * c[12] * c[25]);
r[321] = rf[321] * (c[4] * c[49] - rkc[321] * c[25] * c[18]);
r[322] = rf[322] * (c[6] * c[49] - rkc[322] * c[3] * c[50]);
r[323] = rf[323] * (c[6] * c[49]);
r[324] = rf[324] * (c[12] * c[49] - rkc[324] * c[25] * c[25]);
}
}

View file

@ -0,0 +1,50 @@
/**
*
* @file GRI_30_Kinetics.h
*
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_GRI30_KINETICS_H
#define CT_GRI30_KINETICS_H
#include "GasKinetics.h"
namespace Cantera {
const int cGRI_30_Kinetics = cGasKinetics + 1;
/**
* Kinetics manager implementing reaction mechanism GRI-Mech 3.0
*/
class GRI_30_Kinetics : public GasKinetics {
public:
/// Default constructor.
GRI_30_Kinetics(thermo_t* th=0);
/// Destructor.
virtual ~GRI_30_Kinetics(){}
virtual int ID() { return cGRI_30_Kinetics; }
virtual void getNetProductionRates(doublereal* net) {
gri30_updateROP();
get_wdot(&m_kdata->m_ropnet[0], net);
}
private:
void gri30_update_rates_T();
void gri30_updateROP();
void gri30_updateKc();
void get_wdot(const doublereal* rop, doublereal* wdot);
void update_kc(const double* grt, double c0, double* rkc);
void update_rates(double t, double tlog, double* rf);
void eval_ropnet(const double* c, const double* rf, const double* rkc, double* r);
};
}
#endif

View file

@ -0,0 +1,666 @@
/**
* @file GasKinetics.cpp
*
* Homogeneous kinetics in ideal gases
*
*/
// Copyright 2001 California Institute of Technology
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "GasKinetics.h"
#include "ReactionData.h"
#include "Enhanced3BConc.h"
#include "ThirdBodyMgr.h"
#include "RateCoeffMgr.h"
//#include "../user/grirxnstoich.h"
#include <iostream>
using namespace std;
namespace Cantera {
/**
* Construct an empty reaction mechanism.
*/
GasKinetics::
GasKinetics(thermo_t* thermo) :
Kinetics(),
m_kk(0),
m_nfall(0),
m_dt_threshold(0.0), // 1.e-6),
m_nirrev(0),
m_nrev(0),
m_finalized(false)
{
if (thermo != 0) addPhase(*thermo);
m_kdata = new GasKineticsData;
m_kdata->m_temp = 0.0;
m_rxnstoich = new ReactionStoichMgr;
}
GasKinetics::
~GasKinetics() {delete m_kdata; delete m_rxnstoich;}
/**
* Update temperature-dependent portions of reaction rates and
* falloff functions.
*/
void GasKinetics::
update_T() {}
void GasKinetics::
update_C() {}
void GasKinetics::
_update_rates_T() {
doublereal T = thermo().temperature();
m_kdata->m_logStandConc = log(thermo().standardConcentration());
if (fabs(T - m_kdata->m_temp) > 0.0) { // m_dt_threshold) {
doublereal logT = log(T);
//m_kdata->m_logp0 - logT;
m_rates.update(T, logT, &m_kdata->m_rfn[0]);
m_falloff_low_rates.update(T, logT, &m_kdata->m_rfn_low[0]);
m_falloff_high_rates.update(T, logT, &m_kdata->m_rfn_high[0]);
m_falloffn.updateTemp(T, &m_kdata->falloff_work[0]);
m_kdata->m_temp = T;
updateKc();
m_kdata->m_ROP_ok = false;
}
};
/**
* Update properties that depend on concentrations. Currently only
* the enhanced collision partner concentrations are updated here.
*/
void GasKinetics::
_update_rates_C() {
thermo().getActivityConcentrations(&m_conc[0]);
doublereal ctot = thermo().molarDensity();
m_3b_concm.update(m_conc, ctot, &m_kdata->concm_3b_values[0]);
m_falloff_concm.update(m_conc, ctot,
&m_kdata->concm_falloff_values[0]);
m_kdata->m_ROP_ok = false;
}
/**
* Update the equilibrium constants in molar units.
*/
void GasKinetics::updateKc() {
int i, irxn;
vector_fp& m_rkc = m_kdata->m_rkcn;
thermo().getStandardChemPotentials(&m_grt[0]);
fill(m_rkc.begin(), m_rkc.end(), 0.0);
// compute Delta G^0 for all reversible reactions
m_rxnstoich->getRevReactionDelta(m_ii, &m_grt[0], &m_rkc[0]);
doublereal logStandConc = m_kdata->m_logStandConc;
doublereal rrt = 1.0/(GasConstant * thermo().temperature());
for (i = 0; i < m_nrev; i++) {
irxn = m_revindex[i];
m_rkc[irxn] = exp(m_rkc[irxn]*rrt - m_dn[irxn]*logStandConc);
}
for(i = 0; i != m_nirrev; ++i) {
m_rkc[ m_irrev[i] ] = 0.0;
}
}
/**
* Get the equilibrium constants of all reactions, whether
* reversible or not.
*/
void GasKinetics::getEquilibriumConstants(doublereal* kc) {
int i;
_update_rates_T();
vector_fp& rkc = m_kdata->m_rkcn;
//thermo().getGibbs_RT(m_grt.begin());
thermo().getStandardChemPotentials(&m_grt[0]);
fill(rkc.begin(), rkc.end(), 0.0);
// compute Delta G^0 for all reactions
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], &rkc[0]);
doublereal logStandConc = m_kdata->m_logStandConc;
doublereal rrt = 1.0/(GasConstant * thermo().temperature());
for (i = 0; i < m_ii; i++) {
kc[i] = exp(-rkc[i]*rrt + m_dn[i]*logStandConc);
}
// force an update of T-dependent properties, so that m_rkcn will
// be updated before it is used next.
m_kdata->m_temp = 0.0;
}
/**
*
* getDeltaGibbs():
*
* Return the vector of values for the reaction gibbs free energy
* change
* These values depend upon the concentration
* of the ideal gas.
*
* units = J kmol-1
*/
void GasKinetics::getDeltaGibbs(doublereal* deltaG) {
/*
* Get the chemical potentials of the species in the
* ideal gas solution.
*/
thermo().getChemPotentials(&m_grt[0]);
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], deltaG);
}
/**
*
* getDeltaEnthalpy():
*
* Return the vector of values for the reactions change in
* enthalpy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
void GasKinetics::getDeltaEnthalpy(doublereal* deltaH) {
/*
* Get the partial molar enthalpy of all species in the
* ideal gas.
*/
thermo().getPartialMolarEnthalpies(&m_grt[0]);
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], deltaH);
}
/************************************************************************
*
* getDeltaEntropy():
*
* Return the vector of values for the reactions change in
* entropy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
void GasKinetics::getDeltaEntropy( doublereal* deltaS) {
/*
* Get the partial molar entropy of all species in the
* solid solution.
*/
thermo().getPartialMolarEntropies(&m_grt[0]);
/*
* Use the stoichiometric manager to find deltaS for each
* reaction.
*/
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], deltaS);
}
/**
*
* getDeltaSSGibbs():
*
* Return the vector of values for the reaction
* standard state gibbs free energy change.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
void GasKinetics::getDeltaSSGibbs(doublereal* deltaG) {
/*
* Get the standard state chemical potentials of the species.
* This is the array of chemical potentials at unit activity
* We define these here as the chemical potentials of the pure
* species at the temperature and pressure of the solution.
*/
thermo().getStandardChemPotentials(&m_grt[0]);
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], deltaG);
}
/**
*
* getDeltaSSEnthalpy():
*
* Return the vector of values for the change in the
* standard state enthalpies of reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
void GasKinetics::getDeltaSSEnthalpy(doublereal* deltaH) {
/*
* Get the standard state enthalpies of the species.
* This is the array of chemical potentials at unit activity
* We define these here as the enthalpies of the pure
* species at the temperature and pressure of the solution.
*/
thermo().getEnthalpy_RT(&m_grt[0]);
doublereal RT = thermo().temperature() * GasConstant;
for (int k = 0; k < m_kk; k++) {
m_grt[k] *= RT;
}
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], deltaH);
}
/*********************************************************************
*
* getDeltaSSEntropy():
*
* Return the vector of values for the change in the
* standard state entropies for each reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
void GasKinetics::getDeltaSSEntropy(doublereal* deltaS) {
/*
* Get the standard state entropy of the species.
* We define these here as the entropies of the pure
* species at the temperature and pressure of the solution.
*/
thermo().getEntropy_R(&m_grt[0]);
doublereal R = GasConstant;
for (int k = 0; k < m_kk; k++) {
m_grt[k] *= R;
}
/*
* Use the stoichiometric manager to find deltaS for each
* reaction.
*/
m_rxnstoich->getReactionDelta(m_ii, &m_grt[0], deltaS);
}
void GasKinetics::processFalloffReactions() {
int i;
const vector_fp& fc = m_kdata->concm_falloff_values;
const array_fp& m_rf_low = m_kdata->m_rfn_low;
const array_fp& m_rf_high = m_kdata->m_rfn_high;
// use m_ropr for temporary storage of reduced pressure
array_fp& pr = m_kdata->m_ropr;
array_fp& ropf = m_kdata->m_ropf;
for (i = 0; i < m_nfall; i++) {
pr[i] = fc[i] * m_rf_low[i] / m_rf_high[i];
}
m_falloffn.pr_to_falloff( &pr[0], &m_kdata->falloff_work[0] );
for (i = 0; i < m_nfall; i++) {
pr[i] *= m_rf_high[i];
}
scatter_copy(pr.begin(), pr.begin() + m_nfall,
ropf.begin(), m_fallindx.begin());
}
void GasKinetics::updateROP() {
_update_rates_T();
_update_rates_C();
if (m_kdata->m_ROP_ok) return;
const vector_fp& rf = m_kdata->m_rfn;
const vector_fp& m_rkc = m_kdata->m_rkcn;
array_fp& ropf = m_kdata->m_ropf;
array_fp& ropr = m_kdata->m_ropr;
array_fp& ropnet = m_kdata->m_ropnet;
// copy rate coefficients into ropf
copy(rf.begin(), rf.end(), ropf.begin());
// multiply ropf by enhanced 3b conc for all 3b rxns
m_3b_concm.multiply( &ropf[0], &m_kdata->concm_3b_values[0] );
processFalloffReactions();
// multiply by perturbation factor
multiply_each(ropf.begin(), ropf.end(), m_perturb.begin());
// copy the forward rates to the reverse rates
copy(ropf.begin(), ropf.end(), ropr.begin());
// for reverse rates computed from thermochemistry, multiply
// the forward rates copied into m_ropr by the reciprocals of
// the equilibrium constants
multiply_each(ropr.begin(), ropr.end(), m_rkc.begin());
// multiply ropf by concentration products
m_rxnstoich->multiplyReactants(&m_conc[0], &ropf[0]);
//m_reactantStoich.multiply(m_conc.begin(), ropf.begin());
// for reversible reactions, multiply ropr by concentration
// products
m_rxnstoich->multiplyRevProducts(&m_conc[0], &ropr[0]);
//m_revProductStoich.multiply(m_conc.begin(), ropr.begin());
for (int j = 0; j != m_ii; ++j) {
ropnet[j] = ropf[j] - ropr[j];
}
m_kdata->m_ROP_ok = true;
}
/**
*
* getFwdRateConstants():
*
* Update the rate of progress for the reactions.
* This key routine makes sure that the rate of progress vectors
* located in the solid kinetics data class are up to date.
*/
void GasKinetics::
getFwdRateConstants(doublereal *kfwd) {
_update_rates_T();
_update_rates_C();
// copy rate coefficients into ropf
const vector_fp& rf = m_kdata->m_rfn;
array_fp& ropf = m_kdata->m_ropf;
copy(rf.begin(), rf.end(), ropf.begin());
// multiply ropf by enhanced 3b conc for all 3b rxns
m_3b_concm.multiply(&ropf[0], &m_kdata->concm_3b_values[0] );
/*
* This routine is hardcoded to replace some of the values
* of the ropf vector.
*/
processFalloffReactions();
// multiply by perturbation factor
multiply_each(ropf.begin(), ropf.end(), m_perturb.begin());
for (int i = 0; i < m_ii; i++) {
kfwd[i] = ropf[i];
}
}
/**
*
* getRevRateConstants():
*
* Return a vector of the reverse reaction rate constants
*
* Length is the number of reactions. units depends
* on many issues. Note, this routine will return rate constants
* for irreversible reactions if the default for
* doIrreversible is overridden.
*/
void GasKinetics::
getRevRateConstants(doublereal *krev, bool doIrreversible) {
/*
* go get the forward rate constants. -> note, we don't
* really care about speed or redundancy in these
* informational routines.
*/
getFwdRateConstants(krev);
if (doIrreversible) {
doublereal *tmpKc = &m_kdata->m_ropnet[0];
getEquilibriumConstants(tmpKc);
for (int i = 0; i < m_ii; i++) {
krev[i] /= tmpKc[i];
}
} else {
/*
* m_rkc[] is zero for irreversibly reactions
*/
const vector_fp& m_rkc = m_kdata->m_rkcn;
for (int i = 0; i < m_ii; i++) {
krev[i] *= m_rkc[i];
}
}
}
void GasKinetics::
addReaction(const ReactionData& r) {
if (r.reactionType == ELEMENTARY_RXN) addElementaryReaction(r);
else if (r.reactionType == THREE_BODY_RXN) addThreeBodyReaction(r);
else if (r.reactionType == FALLOFF_RXN) addFalloffReaction(r);
// operations common to all reaction types
installReagents( r );
installGroups(reactionNumber(), r.rgroups, r.pgroups);
incrementRxnCount();
m_rxneqn.push_back(r.equation);
}
void GasKinetics::
addFalloffReaction(const ReactionData& r) {
// install high and low rate coeff calculators
int iloc = m_falloff_high_rates.install(m_nfall,
r.rateCoeffType,
r.rateCoeffParameters.size(),
&r.rateCoeffParameters[0] );
m_falloff_low_rates.install( m_nfall,
r.rateCoeffType, r.auxRateCoeffParameters.size(),
DATA_PTR(r.auxRateCoeffParameters) );
// add constant terms to high and low rate
// coeff value vectors
m_kdata->m_rfn_high.push_back(r.rateCoeffParameters[0]);
m_kdata->m_rfn_low.push_back(r.auxRateCoeffParameters[0]);
// add a dummy entry in m_rf, where computed falloff
// rate coeff will be put
m_kdata->m_rfn.push_back(0.0);
// add this reaction number to the list of
// falloff reactions
m_fallindx.push_back( reactionNumber() );
// install the enhanced third-body concentration
// calculator for this reaction
m_falloff_concm.install( m_nfall, r.thirdBodyEfficiencies,
r.default_3b_eff);
// install the falloff function calculator for
// this reaction
m_falloffn.install( m_nfall, r.falloffType, r.falloffParameters );
// forward rxn order equals number of reactants, since rate
// coeff is defined in terms of the high-pressure limit
m_fwdOrder.push_back(r.reactants.size());
// increment the falloff reaction counter
++m_nfall;
registerReaction( reactionNumber(), FALLOFF_RXN, iloc);
}
void GasKinetics::
addElementaryReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
iloc = m_rates.install( reactionNumber(),
r.rateCoeffType, r.rateCoeffParameters.size(),
DATA_PTR(r.rateCoeffParameters) );
// add constant term to rate coeff value vector
m_kdata->m_rfn.push_back(r.rateCoeffParameters[0]);
// forward rxn order equals number of reactants
m_fwdOrder.push_back(r.reactants.size());
registerReaction( reactionNumber(), ELEMENTARY_RXN, iloc);
}
void GasKinetics::
addThreeBodyReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
iloc = m_rates.install( reactionNumber(),
r.rateCoeffType, r.rateCoeffParameters.size(),
DATA_PTR(r.rateCoeffParameters) );
// add constant term to rate coeff value vector
m_kdata->m_rfn.push_back(r.rateCoeffParameters[0]);
// forward rxn order equals number of reactants + 1
m_fwdOrder.push_back(r.reactants.size() + 1);
m_3b_concm.install( reactionNumber(), r.thirdBodyEfficiencies,
r.default_3b_eff );
registerReaction( reactionNumber(), THREE_BODY_RXN, iloc);
}
void GasKinetics::installReagents(const ReactionData& r) {
m_kdata->m_ropf.push_back(0.0); // extend by one for new rxn
m_kdata->m_ropr.push_back(0.0);
m_kdata->m_ropnet.push_back(0.0);
int n, ns, m;
doublereal nsFlt;
doublereal reactantGlobalOrder = 0.0;
doublereal productGlobalOrder = 0.0;
int rnum = reactionNumber();
vector_int rk;
int nr = r.reactants.size();
for (n = 0; n < nr; n++) {
nsFlt = r.rstoich[n];
reactantGlobalOrder += nsFlt;
ns = (int) nsFlt;
if ((doublereal) ns != nsFlt) {
if (ns < 1) {
ns = 1;
}
}
if (r.rstoich[n] != 0.0)
m_rrxn[r.reactants[n]][rnum] += r.rstoich[n];
for (m = 0; m < ns; m++) {
rk.push_back(r.reactants[n]);
}
}
m_reactants.push_back(rk);
vector_int pk;
int np = r.products.size();
for (n = 0; n < np; n++) {
nsFlt = r.pstoich[n];
productGlobalOrder += nsFlt;
ns = (int) nsFlt;
if ((double) ns != nsFlt) {
if (ns < 1) {
ns = 1;
}
}
if (r.pstoich[n] != 0.0)
m_prxn[r.products[n]][rnum] += r.pstoich[n];
for (m = 0; m < ns; m++) {
pk.push_back(r.products[n]);
}
}
m_products.push_back(pk);
m_kdata->m_rkcn.push_back(0.0);
m_rxnstoich->add(reactionNumber(), r);
if (r.reversible) {
m_dn.push_back(productGlobalOrder - reactantGlobalOrder);
m_revindex.push_back(reactionNumber());
m_nrev++;
}
else {
m_dn.push_back(productGlobalOrder - reactantGlobalOrder);
m_irrev.push_back( reactionNumber() );
m_nirrev++;
}
}
void GasKinetics::installGroups(int irxn,
const vector<grouplist_t>& r, const vector<grouplist_t>& p) {
if (!r.empty()) {
writelog("installing groups for reaction "+int2str(reactionNumber()));
m_rgroups[reactionNumber()] = r;
m_pgroups[reactionNumber()] = p;
}
}
void GasKinetics::init() {
m_kk = thermo().nSpecies();
m_rrxn.resize(m_kk);
m_prxn.resize(m_kk);
m_conc.resize(m_kk);
m_grt.resize(m_kk);
m_kdata->m_logp_ref = log(thermo().refPressure()) - log(GasConstant);
}
void GasKinetics::finalize() {
if (!m_finalized) {
// int i, j, nr, np;
m_kdata->falloff_work.resize(
static_cast<size_t>(m_falloffn.workSize()));
m_kdata->concm_3b_values.resize(
static_cast<size_t>(m_3b_concm.workSize()));
m_kdata->concm_falloff_values.resize(
static_cast<size_t>(m_falloff_concm.workSize()));
// for (i = 0; i < m_ii; i++) {
// nr = m_reactants[i].size();
// for (j = 0; j < nr; j++) {
// m_rstoich[i][m_reactants[i][j]]++;
// }
// np = m_products[i].size();
// for (j = 0; j < np; j++) {
// m_pstoich[i][m_products[i][j]]++;
// }
// }
//m_rxnstoich->write("c.cpp");
m_finalized = true;
}
}
bool GasKinetics::ready() const {
return (m_finalized);
}
}

View file

@ -0,0 +1,420 @@
/**
* @file GasKinetics.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_GASKINETICS_H
#define CT_GASKINETICS_H
#include <fstream>
#include <math.h>
#include <map>
#include <stdlib.h>
#include "mix_defs.h"
#include "Kinetics.h"
#include "utilities.h"
#include "ReactionStoichMgr.h"
#include "ThirdBodyMgr.h"
#include "FalloffMgr.h"
#include "RateCoeffMgr.h"
void get_wdot(const doublereal* rop, doublereal* wdot);
namespace Cantera {
// forward references
class Enhanced3BConc;
class ReactionData;
class GasKineticsData;
class Thermo;
/**
* Holds mechanism-specific data.
*/
class GasKineticsData {
public:
GasKineticsData() :
m_logp_ref(0.0),
m_logc_ref(0.0),
m_logStandConc(0.0),
m_ROP_ok(false),
m_temp(0.0)
{}
virtual ~GasKineticsData(){}
doublereal m_logp_ref, m_logc_ref, m_logStandConc;
array_fp m_ropf, m_ropr, m_ropnet;
array_fp m_rfn_low, m_rfn_high;
bool m_ROP_ok;
doublereal m_temp;
vector_fp m_rfn;
vector_fp falloff_work;
vector_fp concm_3b_values;
vector_fp concm_falloff_values;
vector_fp m_rkcn;
};
/**
* Kinetics manager for elementary gas-phase chemistry. This
* kinetics manager implements standard mass-action reaction rate
* expressions for low-density gases.
* @ingroup kinetics
*/
class GasKinetics : public Kinetics {
public:
/**
* @name Constructors and General Information about Mechanism
*/
//@{
/// Constructor.
GasKinetics(thermo_t* thermo = 0);
/// Destructor.
virtual ~GasKinetics();
virtual int ID() { return cGasKinetics; }
virtual doublereal reactantStoichCoeff(int k, int i) const {
return m_rrxn[k][i];
}
virtual doublereal productStoichCoeff(int k, int i) const {
return m_prxn[k][i];
}
//@}
/**
* @name Reaction Rates Of Progress
*/
//@{
/**
* Forward rates of progress.
* Return the forward rates of progress in array fwdROP, which
* must be dimensioned at least as large as the total number
* of reactions.
*/
virtual void getFwdRatesOfProgress(doublereal* fwdROP) {
updateROP();
std::copy(m_kdata->m_ropf.begin(), m_kdata->m_ropf.end(), fwdROP);
}
/**
* Reverse rates of progress.
* Return the reverse rates of progress in array revROP, which
* must be dimensioned at least as large as the total number
* of reactions.
*/
virtual void getRevRatesOfProgress(doublereal* revROP) {
updateROP();
std::copy(m_kdata->m_ropr.begin(), m_kdata->m_ropr.end(), revROP);
}
/**
* Net rates of progress. Return the net (forward - reverse)
* rates of progress in array netROP, which must be
* dimensioned at least as large as the total number of
* reactions.
*/
virtual void getNetRatesOfProgress(doublereal* netROP) {
updateROP();
std::copy(m_kdata->m_ropnet.begin(), m_kdata->m_ropnet.end(), netROP);
}
/**
* Equilibrium constants. Return the equilibrium constants of
* the reactions in concentration units in array kc, which
* must be dimensioned at least as large as the total number
* of reactions.
*/
virtual void getEquilibriumConstants(doublereal* kc);
/**
* Return the vector of values for the reaction gibbs free energy
* change.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaGibbs( doublereal* deltaG);
/**
* Return the vector of values for the reactions change in
* enthalpy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaEnthalpy( doublereal* deltaH);
/**
* Return the vector of values for the reactions change in
* entropy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
virtual void getDeltaEntropy(doublereal* deltaS);
/**
* Return the vector of values for the reaction
* standard state gibbs free energy change.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaSSGibbs(doublereal* deltaG);
/**
* Return the vector of values for the change in the
* standard state enthalpies of reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaSSEnthalpy(doublereal* deltaH);
/**
* Return the vector of values for the change in the
* standard state entropies for each reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
virtual void getDeltaSSEntropy(doublereal* deltaS);
//@}
/**
* @name Species Production Rates
*/
//@{
/**
* Species net production rates [kmol/m^3]. Return the species
* net production rates (creation - destruction) in array
* wdot, which must be dimensioned at least as large as the
* total number of species.
*/
virtual void getNetProductionRates(doublereal* net) {
updateROP();
#ifdef HWMECH
get_wdot(&m_kdata->m_ropnet[0], net);
#else
m_rxnstoich->getNetProductionRates(m_kk, &m_kdata->m_ropnet[0], net);
#endif
}
/**
* Species creation rates [kmol/m^3]. Return the species
* creation rates in array cdot, which must be
* dimensioned at least as large as the total number of
* species.
*
*/
virtual void getCreationRates(doublereal* cdot) {
updateROP();
m_rxnstoich->getCreationRates(m_kk, &m_kdata->m_ropf[0],
&m_kdata->m_ropr[0], cdot);
}
/**
* Species destruction rates [kmol/m^3]. Return the species
* destruction rates in array ddot, which must be
* dimensioned at least as large as the total number of
* species.
*
*/
virtual void getDestructionRates(doublereal* ddot) {
updateROP();
m_rxnstoich->getDestructionRates(m_kk, &m_kdata->m_ropf[0],
&m_kdata->m_ropr[0], ddot);
// fill(ddot, ddot + m_kk, 0.0);
//m_revProductStoich.incrementSpecies(
// m_kdata->m_ropr.begin(), ddot);
//m_reactantStoich.incrementSpecies(
// m_kdata->m_ropf.begin(), ddot);
}
//@}
/**
* @name Reaction Mechanism Informational Query Routines
*/
//@{
/**
* Flag specifying the type of reaction. The legal values and
* their meaning are specific to the particular kinetics
* manager.
*/
virtual int reactionType(int i) const {
return m_index[i].first;
}
virtual std::string reactionString(int i) const {
return m_rxneqn[i];
}
/**
* True if reaction i has been declared to be reversible. If
* isReversible(i) is false, then the reverse rate of progress
* for reaction i is always zero.
*/
virtual bool isReversible(int i) {
if (std::find(m_revindex.begin(), m_revindex.end(), i)
< m_revindex.end()) return true;
else return false;
}
/**
* Return the forward rate constants
*
* length is the number of reactions. units depends
* on many issues.
*/
virtual void getFwdRateConstants(doublereal *kfwd);
/**
* Return the reverse rate constants.
*
* length is the number of reactions. units depends
* on many issues. Note, this routine will return rate constants
* for irreversible reactions if the default for
* doIrreversible is overridden.
*/
virtual void getRevRateConstants(doublereal *krev,
bool doIrreversible = false);
//@}
/**
* @name Reaction Mechanism Setup Routines
*/
//@{
/**
* Set delta T threshold for updating temperature-dependent
* rates.
*/
void setRateUpdateThreshold(doublereal dt) {
m_dt_threshold = dt;
}
virtual void init();
/// Add a reaction to the mechanism.
void addReaction(const ReactionData& r);
virtual void finalize();
virtual bool ready() const;
virtual void update_T();
virtual void update_C();
void updateROP();
const std::vector<grouplist_t>& reactantGroups(int i)
{ return m_rgroups[i]; }
const std::vector<grouplist_t>& productGroups(int i)
{ return m_pgroups[i]; }
void _update_rates_T();
void _update_rates_C();
//@}
protected:
int m_kk, m_nfall;
vector_int m_fallindx;
doublereal m_dt_threshold;
Rate1<Arrhenius> m_falloff_low_rates;
Rate1<Arrhenius> m_falloff_high_rates;
Rate1<Arrhenius> m_rates;
mutable std::map<int, std::pair<int, int> > m_index;
FalloffMgr m_falloffn;
ThirdBodyMgr<Enhanced3BConc> m_3b_concm;
ThirdBodyMgr<Enhanced3BConc> m_falloff_concm;
std::vector<int> m_irrev;
ReactionStoichMgr* m_rxnstoich;
std::vector<int> m_fwdOrder;
int m_nirrev;
int m_nrev;
std::map<int, std::vector<grouplist_t> > m_rgroups;
std::map<int, std::vector<grouplist_t> > m_pgroups;
std::vector<int> m_rxntype;
mutable std::vector<std::map<int, doublereal> > m_rrxn;
mutable std::vector<std::map<int, doublereal> > m_prxn;
/**
* Difference between the input global reactants order
* and the input global products order. Changed to a double
* to account for the fact that we can have real-valued
* stoichiometries.
*/
vector_fp m_dn;
vector_int m_revindex;
std::vector<std::string> m_rxneqn;
GasKineticsData* m_kdata;
vector_fp m_conc;
void processFalloffReactions();
vector_fp m_grt;
private:
int reactionNumber(){ return m_ii;}
std::vector<std::map<int, doublereal> > m_stoich;
void addElementaryReaction(const ReactionData& r);
void addThreeBodyReaction(const ReactionData& r);
void addFalloffReaction(const ReactionData& r);
void installReagents(const ReactionData& r);
void installGroups(int irxn, const std::vector<grouplist_t>& r,
const std::vector<grouplist_t>& p);
void updateKc();
void registerReaction(int rxnNumber, int type, int loc) {
m_index[rxnNumber] = std::pair<int, int>(type, loc);
}
bool m_finalized;
};
}
#endif

View file

@ -0,0 +1,136 @@
/**
* @file GasKineticsWriter.cpp
*
*/
// Copyright 2001 California Institute of Technology
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "ReactionData.h"
#include "GasKineticsWriter.h"
#include "StoichManager.h"
#include "Enhanced3BConc.h"
#include "ThirdBodyMgr.h"
#include "RateCoeffMgr.h"
//#include "ThermoPhase.h"
#include <iostream>
using namespace std;
namespace Cantera {
/**
* Construct an empty reaction mechanism.
*/
GasKineticsWriter::
GasKineticsWriter() : m_kk(0), m_ii(0), m_nfall(0), m_nrev(0), m_nirrev(0),
m_finalized(false) {}
void GasKineticsWriter::
addReaction(const ReactionData& r) {
if (r.reactionType == ELEMENTARY_RXN) addElementaryReaction(r);
else if (r.reactionType == THREE_BODY_RXN) addThreeBodyReaction(r);
else if (r.reactionType == FALLOFF_RXN) addFalloffReaction(r);
// operations common to all reaction types
installReagents( r.reactants, r.products, r.reversible );
m_ii++;
}
void GasKineticsWriter::
addFalloffReaction(const ReactionData& r) {
// install high and low rate coeff calculators
m_falloff_high_rates.install( m_nfall,
r.rateCoeffType, r.rateCoeffParameters.size(),
r.rateCoeffParameters.begin() );
m_falloff_low_rates.install( m_nfall,
r.rateCoeffType, r.auxRateCoeffParameters.size(),
r.auxRateCoeffParameters.begin() );
// add this reaction number to the list of
// falloff reactions
m_fallindx.push_back( reactionNumber() );
// increment the falloff reaction counter
++m_nfall;
}
void GasKineticsWriter::
addElementaryReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
iloc = m_rates.install( reactionNumber(),
r.rateCoeffType, r.rateCoeffParameters.size(),
r.rateCoeffParameters.begin() );
}
void GasKineticsWriter::
addThreeBodyReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
iloc = m_rates.install( reactionNumber(),
r.rateCoeffType, r.rateCoeffParameters.size(),
r.rateCoeffParameters.begin() );
}
void GasKineticsWriter::installReagents(const vector_int& r,
const vector_int& p, bool reversible) {
int nr = r.size();
int rnum = reactionNumber();
int i;
for (i = 0; i < nr; i++) {
m_rrxn[r[i]][rnum] += 1.0;
}
m_reactantWriter.add( reactionNumber(), r);
int np = p.size();
for (i = 0; i < np; i++) {
m_prxn[p[i]][rnum] += 1.0;
}
if (reversible) {
m_revProductWriter.add(reactionNumber(), p);
m_dn.push_back(np - nr);
m_revindex.push_back(reactionNumber());
m_nrev++;
}
else {
m_irrevProductWriter.add(reactionNumber(), p);
m_irrev.push_back( reactionNumber() );
m_nirrev++;
}
}
void GasKineticsWriter::init(int nsp) {
m_rrxn.resize(nsp);
m_prxn.resize(nsp);
}
}

View file

@ -0,0 +1,203 @@
/**
*
* @file GasKineticsWriter.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_GASKINETICSWRITER_H
#define CT_GASKINETICSWRITER_H
#define WRITE_UPDATE
#include <fstream>
#include <math.h>
#include <map>
#include <stdlib.h>
#include "mix_defs.h"
#include "Kinetics.h"
#include "utilities.h"
#include "StoichManager.h"
#include "ThirdBodyMgr.h"
#include "FalloffMgr.h"
#include "RateCoeffMgr.h"
#include "Phase.h"
namespace Cantera {
// forward references
class Enhanced3BConc;
class ReactionData;
//! Class to write a hard-coded version of a mechanism.
/*!
* @ingroup kineticsmgr
*/
class GasKineticsWriter {
public:
/// Default constructor.
GasKineticsWriter();
/// Destructor.
virtual ~GasKineticsWriter(){}
void init(int nsp);
doublereal reactantStoichCoeff(int k, int i) const {
return m_rrxn[k][i];
}
doublereal productStoichCoeff(int k, int i) const {
return m_prxn[k][i];
}
void writeUpdateROP(){}
void writeGetNetProductionRates(ostream& s, int nsp, int nrxns) {
int i, k;
s << "void get_wdot(const double* rop, double* wdot) {" << endl;
for (k = 0; k < nsp; k++) {
s << " wdot[" << k << "] = ";
doublereal net;
bool empty = true;
for (i = 0; i < nrxns; i++) {
net = productStoichCoeff(k,i) - reactantStoichCoeff(k,i);
if (net > 0.0) {
empty = false;
if (net == 1.0)
s << " + rop[" << i << "]";
else
s << " + " << net << "*rop[" << i << "]";
}
else if (net < 0.0) {
empty = false;
if (net == -1.0)
s << " - rop[" << i << "]";
else
s << " - " << -net << "*rop[" << i << "]";
}
}
if (empty) s << "0.0";
s << ";" << endl;
}
s << "}" << endl;
}
void writeUpdateKc(ostream& s, int nsp, int nrxns) {
int i, k, n, nn, ir;
s << "void update_kc(const double* a, "
"double exp_c0, double* rkc) {" << endl;
for (i = 0; i != m_nrev; i++) {
//if (isReversible(i)) {
ir = m_revindex[i];
s << " rkc[" << ir << "] = ";
bool empty = true;
for (k = 0; k < nsp; k++) {
n = int(productStoichCoeff(k,ir));
for (nn = 0; nn != n; nn++) {
if (!empty) s << "*";
s << "a[" << k << "]";
empty = false;
}
}
if (m_dn[i] < 0.0) {
n = -m_dn[i];
for (nn = 0; nn < n; nn++) s << "*exp_c0";
}
s << "/(";
empty = true;
for (k = 0; k < nsp; k++) {
n = int(reactantStoichCoeff(k,ir));
for (nn = 0; nn < n; nn++) {
if (!empty) s << "*";
s << "a[" << k << "]";
empty = false;
}
}
if (m_dn[i] > 0.0) {
n = m_dn[i];
for (nn = 0; nn != n; nn++) s << "*exp_c0";
}
s << ");" << endl;
}
s << "}" << endl;
}
void writeEvalRopnet(ostream& s) {
int i;
s << "void eval_ropnet(const double* c, "
"const double* rf, const double* rkc, double* r) {" << endl;
for (i = 0; i < m_ii; i++) {
s << " r[" << i << "] = rf[" << i << "] * ("
<< m_reactantWriter.mult(i);
if (isReversible(i)) {
s << " - rkc[" << i << "] * "
<< m_revProductWriter.mult(i);
}
s << ");" << endl;
}
s << "}" << endl;
}
void writeUpdateRates(ostream& s) {
s << "void update_rates(double t, double tlog, double* rf) {" << endl;
s << " double rt = 1.0/t;" << endl;
m_rates.writeUpdate(s, "rf");
s << "}" << endl;
}
/// Add a reaction to the mechanism.
void addReaction(const ReactionData& r);
protected:
int m_kk, m_ii, m_nfall, m_nrev, m_nirrev;
vector_int m_fallindx;
Rate1<Arrhenius> m_falloff_low_rates;
Rate1<Arrhenius> m_falloff_high_rates;
Rate1<Arrhenius> m_rates;
vector<int> m_irrev;
StoichWriter m_reactantWriter;
StoichWriter m_revProductWriter;
StoichWriter m_irrevProductWriter;
mutable vector<map<int, doublereal> > m_rrxn;
mutable vector<map<int, doublereal> > m_prxn;
vector_int m_dn;
vector_int m_revindex;
private:
int reactionNumber(){ return m_ii;}
void addElementaryReaction(const ReactionData& r);
void addThreeBodyReaction(const ReactionData& r);
void addFalloffReaction(const ReactionData& r);
void installReagents(const vector_int& r,
const vector_int& p, bool reversible);
virtual bool isReversible(int i) {
if (find(m_revindex.begin(), m_revindex.end(), i)
< m_revindex.end()) return true;
else return false;
}
bool m_finalized;
};
}
#endif

85
Cantera/src/kinetics/Group.cpp Executable file
View file

@ -0,0 +1,85 @@
/**
* @file Group.cpp
*
* Implementation file for the Group class used in reaction path analysis.
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
// reaction path analysis support
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include <algorithm>
#include "Group.h"
#include <math.h>
namespace Cantera {
/**
* A group is 'valid' if all of its nonzero atom numbers have
* the same sign, either positive or negative. This method
* checks for this, and if the group is not valid it sets
* m_sign to -999, and sets all atom numbers to zero.
*/
void Group::validate() {
int n = m_comp.size();
// if already checked and not valid, return
if (m_sign == -999) return;
m_sign = 0;
bool ok = true;
for (int m = 0; m < n; m++)
{
if (m_comp[m] != 0)
{
if (m_sign == 0) {
m_sign = m_comp[m]/abs(m_comp[m]);
}
else if (m_sign * m_comp[m] < 0) {
ok = false; break;
}
}
}
if (!ok) { m_sign = -999; m_comp.resize(n,0); }
}
std::ostream& Group::fmt(std::ostream& s,
const std::vector<std::string>& esymbols) const {
s << "(";
int nm;
bool first = true;
int n = m_comp.size();
for (int m = 0; m < n; m++) {
nm = m_comp[m];
if (nm != 0) {
if (!first) s << "-";
s << esymbols[m];
if (nm != 1) s << nm;
first = false;
}
}
s << ")";
return s;
}
std::ostream& operator<<(std::ostream& s, const Cantera::Group& g) {
if (g.valid()) {
s << g.m_comp;
} else {
s << "<none>";
}
return s;
}
}

131
Cantera/src/kinetics/Group.h Executable file
View file

@ -0,0 +1,131 @@
/**
* @file Group.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_RXNPATH_GROUP
#define CT_RXNPATH_GROUP
#include "ct_defs.h"
//using namespace std;
namespace Cantera {
/**
* Class Group is an internal class used by class ReactionPath. It
* represents some subset of the atoms of a molecule.
*/
class Group {
public:
Group() : m_sign(-999) { }
Group(int n) : m_sign(0) { m_comp.resize(n,0);}
Group(const vector_int& elnumbers) :
m_comp(elnumbers), m_sign(0) {
validate();
}
Group(const Group& g) :
m_comp(g.m_comp), m_sign(g.m_sign) { }
Group& operator=(const Group& g) {
if (&g != this) {
m_comp = g.m_comp;
m_sign = g.m_sign;
}
return *this;
}
virtual ~Group(){}
/**
* Decrement the atom numbers by those in group 'other'.
*/
void operator-=(const Group& other) {
verifyInputs(*this, other);
int n = m_comp.size();
for (int m = 0; m < n; m++)
m_comp[m] -= other.m_comp[m];
validate();
}
void operator+=(const Group& other) {
verifyInputs(*this, other);
int n = m_comp.size();
for (int m = 0; m < n; m++)
m_comp[m] += other.m_comp[m];
validate();
}
void operator*=(int a) {
int n = m_comp.size();
for (int m = 0; m < n; m++)
m_comp[m] *= a;
validate();
}
bool operator==(const Group& other) const {
verifyInputs(*this, other);
int n = m_comp.size();
for (int m = 0; m < n; m++) {
if (m_comp[m] != other.m_comp[m]) return false;
}
return true;
}
friend Group operator-(const Group& g1, const Group& g2) {
verifyInputs(g1, g2);
Group diff(g1);
diff -= g2;
return diff;
}
friend Group operator+(const Group& g1, const Group& g2) {
verifyInputs(g1, g2);
Group sum(g1);
sum += g2;
return sum;
}
friend void verifyInputs(const Group& g1, const Group& g2) {
// if (Debug::on) {
// if (g1.size() != g2.size()) {
// cerr << "Group: size mismatch!" << std::endl;
// cerr << " group 1 = " << g1 << std::endl;
// cerr << " group 2 = " << g2 << std::endl;
// }
// }
}
void validate();
/**
* True if all non-zero atom numbers have the same sign.
*/
bool valid() const { return (m_sign != -999); }
bool operator!() const { return (m_sign == -999); }
int sign() const { return m_sign; }
int size() const { return m_comp.size(); }
/// Number of atoms in the group (>= 0)
int nAtoms() const {
int n = m_comp.size();
int sum = 0;
for (int m = 0; m < n; m++) sum += std::abs(m_comp[m]);
return sum;
}
/// Number of atoms of element m (positive or negative)
int nAtoms(int m) const {
if (m_comp.empty()) return 0;
return m_comp[m];
}
std::ostream& fmt(std::ostream& s, const std::vector<std::string>& esymbols) const;
friend std::ostream& operator<<(std::ostream& s,
const Group& g);
private:
vector_int m_comp;
int m_sign;
};
}
#endif

View file

@ -0,0 +1,89 @@
/**
* @file ImplicitChem.cpp
*/
/* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "ImplicitChem.h"
#include "Integrator.h"
namespace Cantera {
ImplicitChem::ImplicitChem(Kinetics& kin, ThermoPhase& therm)
: FuncEval(), m_kin(&kin), m_thermo(&therm), m_integ(0),
m_atol(1.e-15), m_rtol(1.e-7), m_maxstep(0.0), m_energy(false)
{
m_integ = newIntegrator("CVODE"); //CVodeInt;
//m_mix = &kin.phase();
m_wt = m_thermo->molecularWeights();
// use backward differencing, with a full Jacobian computed
// numerically, and use a Newton linear iterator
m_integ->setMethod(BDF_Method);
m_integ->setProblemType(DENSE + NOJAC);
m_integ->setIterator(Newton_Iter);
m_nsp = m_thermo->nSpecies();
}
// overloaded method of FuncEval. Called by the integrator to
// get the initial conditions.
void ImplicitChem::getInitialConditions(double t0, size_t leny, double* y)
{
m_thermo->getMassFractions(y);
m_h0 = m_thermo->enthalpy_mass();
m_rho = m_thermo->density();
m_press = m_thermo->pressure();
}
/**
* Must be called before calling method 'advance'
*/
void ImplicitChem::initialize(doublereal t0) {
m_integ->setTolerances(m_rtol, m_atol);
// m_integ->setMaxStep(m_maxstep);
m_integ->initialize(t0, *this);
}
void ImplicitChem::updateState(doublereal* y) {
m_thermo->setMassFractions(y);
if (m_energy) {
doublereal delta, temp = m_thermo->temperature();
do {
delta = -(m_thermo->enthalpy_mass() - m_h0)/m_thermo->cp_mass();
temp += delta;
m_thermo->setTemperature(temp);
}
while (fabs(delta) > 1.e-7);
}
m_thermo->setPressure(m_press);
}
/**
* Called by the integrator to evaluate ydot given y at time 'time'.
*/
void ImplicitChem::eval(doublereal time, doublereal* y,
doublereal* ydot, doublereal* p)
{
updateState(y); // synchronize the mixture state with y
m_thermo->setPressure(m_press);
m_kin->getNetProductionRates(ydot); // "omega dot"
int k;
for (k = 0; k < m_nsp; k++) {
ydot[k] *= m_wt[k]/m_rho;
}
}
}

View file

@ -0,0 +1,118 @@
/**
* @file ImplicitChem.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_IMPCHEM_H
#define CT_IMPCHEM_H
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "FuncEval.h"
#include "Integrator.h"
#include "Kinetics.h"
#include "ThermoPhase.h"
namespace Cantera {
/**
* Advances the composition of an associated phase object in time
* by implicitly integrating
* \f[
* \dot Y_k = \frac{\omega_k}{\rho}
* \f]
*/
class ImplicitChem : public FuncEval {
public:
/**
* Constructor.
*/
ImplicitChem(Kinetics& kin, ThermoPhase& therm);
/**
* Destructor. Deletes the integrator.
*/
virtual ~ImplicitChem(){ delete m_integ; }
/**
* Overloads the virtual function
* declared in FuncEval.
*/
virtual void initialize(doublereal t0 = 0.0);
void adiabatic() {
m_energy = true;
}
void isothermal() {
m_energy = false;
}
/**
* Integrate from t0 to t1. The integrator is reinitialized
* first.
*/
void integrate(doublereal t0, doublereal t1) {
m_integ->reinitialize(t0, *this);
m_integ->setMaxStepSize(t1 - t0);
m_rho = m_thermo->density();
m_integ->integrate(t1);
updateState(m_integ->solution());
}
/**
* Integrate from t0 to t1 without reinitializing the
* integrator.
*/
void integrate0(doublereal t0, doublereal t1) {
m_integ->integrate(t1);
updateState(m_integ->solution());
}
// overloaded methods of class FuncEval
virtual int neq() { return m_nsp; }
virtual void eval(doublereal t, doublereal* y, doublereal* ydot,
doublereal* p);
virtual void getInitialConditions(doublereal t0, size_t leny,
doublereal* y);
protected:
/**
* Set the mixture to a state consistent with solution
* vector y.
*/
void updateState(doublereal* y);
//Kinetics::phase_t* m_mix;
Kinetics* m_kin;
ThermoPhase* m_thermo;
int m_nsp;
Integrator* m_integ; // pointer to integrator
doublereal m_atol, m_rtol; // tolerances
doublereal m_maxstep; // max step size
array_fp m_wt;
doublereal m_rho;
bool m_energy;
doublereal m_h0;
doublereal m_press;
private:
};
}
#endif

View file

@ -0,0 +1,114 @@
/**
* @file ImplicitSurfChem.cpp
*
* Implicit integration of surface site density equations
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "ImplicitSurfChem.h"
#include "Integrator.h"
using namespace std;
namespace Cantera {
ImplicitSurfChem::ImplicitSurfChem(vector<InterfaceKinetics*> k)
: FuncEval(), m_nv(0), m_integ(0),
m_atol(1.e-14), m_rtol(1.e-7), m_maxstep(0.0)
{
m_nsurf = static_cast<int>(k.size());
int ns;
int nt, ntmax = 0;
for (int n = 0; n < m_nsurf; n++) {
m_kin.push_back(k[n]);
ns = k[n]->surfacePhaseIndex();
if (ns < 0)
throw CanteraError("ImplicitSurfChem",
"kinetics manager contains no surface phase");
m_surfindex.push_back(ns);
m_surf.push_back((SurfPhase*)&k[n]->thermo(ns));
m_nsp.push_back(m_surf.back()->nSpecies());
m_nv += m_nsp.back();
nt = k[n]->nTotalSpecies();
if (nt > ntmax) ntmax = nt;
}
m_integ = newIntegrator("CVODE");// CVodeInt;
// use backward differencing, with a full Jacobian computed
// numerically, and use a Newton linear iterator
m_integ->setMethod(BDF_Method);
m_integ->setProblemType(DENSE + NOJAC);
m_integ->setIterator(Newton_Iter);
m_work.resize(ntmax);
}
// overloaded method of FuncEval. Called by the integrator to
// get the initial conditions.
void ImplicitSurfChem::getInitialConditions(double t0, size_t lenc,
double* c)
{
int loc = 0;
for (int n = 0; n < m_nsurf; n++) {
m_surf[n]->getCoverages(c + loc);
loc += m_nsp[n];
}
}
/**
* Must be called before calling method 'advance'
*/
void ImplicitSurfChem::initialize(doublereal t0) {
m_integ->setTolerances(m_rtol, m_atol);
m_integ->initialize(t0, *this);
}
void ImplicitSurfChem::updateState(doublereal* c) {
int loc = 0;
for (int n = 0; n < m_nsurf; n++) {
m_surf[n]->setCoverages(c + loc);
loc += m_nsp[n];
}
}
/**
* Called by the integrator to evaluate ydot given y at time 'time'.
*/
void ImplicitSurfChem::eval(doublereal time, doublereal* y,
doublereal* ydot, doublereal* p)
{
int n;
updateState(y); // synchronize the surface state(s) with y
doublereal rs0, sum;
int loc, k, kstart;
for (n = 0; n < m_nsurf; n++) {
rs0 = 1.0/m_surf[n]->siteDensity();
m_kin[n]->getNetProductionRates(DATA_PTR(m_work));
kstart = m_kin[n]->kineticsSpeciesIndex(0,m_surfindex[n]);
sum = 0.0;
loc = 0;
for (k = 1; k < m_nsp[n]; k++) {
ydot[k + loc] = m_work[kstart + k] * rs0 * m_surf[n]->size(k);
sum -= ydot[k];
}
ydot[loc] = sum;
loc += m_nsp[n];
}
}
}

View file

@ -0,0 +1,117 @@
/**
* @file ImplicitSurfChem.h
*
* Implicit integration of surface site density equations.
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_IMPSURFCHEM_H
#define CT_IMPSURFCHEM_H
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "FuncEval.h"
#include "Integrator.h"
#include "InterfaceKinetics.h"
#include "SurfPhase.h"
namespace Cantera {
/**
* Advances the surface coverages of an associated SurfacePhase
* object in time by implicitly integrating \f[ \dot \theta_k =
* \dot s_k (\sigma_k / s_0)\f]
*/
class ImplicitSurfChem : public FuncEval {
public:
/**
* Constructor.
*/
//ImplicitSurfChem(InterfaceKinetics& kin);
/**
* Constructor for multiple surfaces.
*/
ImplicitSurfChem(std::vector<InterfaceKinetics*> k);
/**
* Destructor. Deletes the integrator.
*/
virtual ~ImplicitSurfChem(){ delete m_integ; }
/**
* Overloads the virtual function
* declared in FuncEval.
*/
virtual void initialize(doublereal t0 = 0.0);
/**
* Integrate from t0 to t1. The integrator is reinitialized
* first.
*/
void integrate(doublereal t0, doublereal t1) {
m_integ->initialize(t0, *this);
m_integ->setMaxStepSize(t1 - t0);
m_integ->integrate(t1);
updateState(m_integ->solution());
}
/**
* Integrate from t0 to t1 without reinitializing the
* integrator. Use when the coverages have not changed from
* their values on return from the last call to integrate or
* integrate0.
*/
void integrate0(doublereal t0, doublereal t1) {
m_integ->integrate(t1);
updateState(m_integ->solution());
}
// overloaded methods of class FuncEval
virtual int neq() { return m_nv; }
virtual void eval(doublereal t, doublereal* y, doublereal* ydot,
doublereal* p);
virtual void getInitialConditions(doublereal t0,
size_t leny, doublereal* y);
protected:
/**
* Set the mixture to a state consistent with solution
* vector y.
*/
void updateState(doublereal* y);
std::vector<SurfPhase*> m_surf;
std::vector<InterfaceKinetics*> m_kin;
vector_int m_nsp;
vector_int m_surfindex;
int m_nsurf;
int m_nv;
//int m_nsp, m_surfindex;
Integrator* m_integ; // pointer to integrator
doublereal m_atol, m_rtol; // tolerances
doublereal m_maxstep; // max step size
vector_fp m_work;
private:
};
}
#endif

View file

@ -0,0 +1,836 @@
/**
* @file InterfaceKinetics.cpp
*
*/
// Copyright 2002 California Institute of Technology
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "InterfaceKinetics.h"
#include "SurfPhase.h"
#include "ReactionData.h"
#include "RateCoeffMgr.h"
#include "ImplicitSurfChem.h"
using namespace std;
namespace Cantera {
//////////////////////////////////////////////////////////////////
/**
* Construct an empty InterfaceKinetics reaction mechanism.
* @param thermo This is an optional parameter that may be
* used to initialize the inherited Kinetics class with
* one ThermoPhase class object -> in other words it's
* useful for initialization of homogeneous kinetics
* mechanisms.
*/
InterfaceKinetics::
InterfaceKinetics(thermo_t* thermo) :
Kinetics(),
m_kk(0),
m_redo_rates(false),
m_nirrev(0),
m_nrev(0),
m_surf(0),
m_integrator(0),
m_finalized(false),
m_has_coverage_dependence(false)
{
if (thermo != 0) addPhase(*thermo);
m_kdata = new InterfaceKineticsData;
m_kdata->m_temp = 0.0;
}
/**
* Destructor
*/
InterfaceKinetics::
~InterfaceKinetics(){
delete m_kdata;
delete m_integrator;
}
/**
* Update properties that depend on temperature
*
*/
void InterfaceKinetics::
_update_rates_T() {
_update_rates_phi();
if (m_has_coverage_dependence) {
m_surf->getCoverages(DATA_PTR(m_conc));
m_rates.update_C(DATA_PTR(m_conc));
m_redo_rates = true;
}
doublereal T = thermo(surfacePhaseIndex()).temperature();
if (T != m_kdata->m_temp || m_redo_rates) {
m_kdata->m_logtemp = log(T);
m_rates.update(T, m_kdata->m_logtemp, DATA_PTR(m_kdata->m_rfn));
applyButlerVolmerCorrection(DATA_PTR(m_kdata->m_rfn));
m_kdata->m_temp = T;
updateKc();
m_kdata->m_ROP_ok = false;
m_redo_rates = false;
}
}
void InterfaceKinetics::
_update_rates_phi() {
int np = nPhases();
for (int n = 0; n < np; n++) {
if (thermo(n).electricPotential() != m_phi[n]) {
m_phi[n] = thermo(n).electricPotential();
m_redo_rates = true;
}
}
}
/**
* Update properties that depend on concentrations. This method
* fills out the array of generalized concentrations by calling
* method getActivityConcentrations for each phase, which classes
* representing phases should overload to return the appropriate
* quantities.
*/
void InterfaceKinetics::
_update_rates_C() {
int n;
int np = nPhases();
for (n = 0; n < np; n++) {
/*
* We call the getActivityConcentrations function of each
* ThermoPhase class that makes up this kinetics object to
* obtain the generalized concentrations for species within that
* class. This is collected in the vector m_conc. m_start[]
* are integer indecises for that vector denoting the start of the
* species for each phase.
*/
thermo(n).getActivityConcentrations(DATA_PTR(m_conc) + m_start[n]);
}
m_kdata->m_ROP_ok = false;
}
/**
* Update the equilibrium constants in molar units for all
* reversible reactions. Irreversible reactions have their
* equilibrium constant set to zero.
*/
void InterfaceKinetics::updateKc() {
int i, irxn;
vector_fp& m_rkc = m_kdata->m_rkcn;
fill(m_rkc.begin(), m_rkc.end(), 0.0);
//static vector_fp mu(nTotalSpecies());
if (m_nrev > 0) {
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
for (n = 0; n < np; n++) {
thermo(n).getStandardChemPotentials(DATA_PTR(m_mu0) + m_start[n]);
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
m_mu0[ik] -= rt*thermo(n).logStandardConc(k);
m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
ik++;
}
}
// compute Delta mu^0 for all reversible reactions
//m_reactantStoich.decrementReactions(m_mu0.begin(), m_rkc.begin());
//m_revProductStoich.incrementReactions(m_mu0.begin(), m_rkc.begin());
m_rxnstoich.getRevReactionDelta(m_ii, DATA_PTR(m_mu0),
DATA_PTR(m_rkc));
for (i = 0; i < m_nrev; i++) {
irxn = m_revindex[i];
if (irxn < 0 || irxn >= nReactions()) {
throw CanteraError("InterfaceKinetics","illegal value: irxn = "+int2str(irxn));
}
m_rkc[irxn] = exp(m_rkc[irxn]*rrt);
}
for (i = 0; i != m_nirrev; ++i) {
m_rkc[ m_irrev[i] ] = 0.0;
}
}
}
void InterfaceKinetics::checkPartialEquil() {
int i, irxn;
vector_fp dmu(nTotalSpecies(), 0.0);
vector_fp rmu(nReactions(), 0.0);
vector_fp frop(nReactions(), 0.0);
vector_fp rrop(nReactions(), 0.0);
vector_fp netrop(nReactions(), 0.0);
if (m_nrev > 0) {
doublereal rt = GasConstant*thermo(0).temperature();
cout << "T = " << thermo(0).temperature() << " " << rt << endl;
int n, nsp, k, ik=0;
//doublereal rt = GasConstant*thermo(0).temperature();
// doublereal rrt = 1.0/rt;
int np = nPhases();
doublereal delta;
for (n = 0; n < np; n++) {
thermo(n).getChemPotentials(DATA_PTR(dmu) + m_start[n]);
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
delta = Faraday * m_phi[n] * thermo(n).charge(k);
cout << thermo(n).speciesName(k) << " " << (delta+dmu[ik])/rt << " " << dmu[ik]/rt << endl;
dmu[ik] += delta;
ik++;
}
}
// compute Delta mu^ for all reversible reactions
m_rxnstoich.getRevReactionDelta(m_ii, DATA_PTR(dmu), DATA_PTR(rmu));
getFwdRatesOfProgress(DATA_PTR(frop));
getRevRatesOfProgress(DATA_PTR(rrop));
getNetRatesOfProgress(DATA_PTR(netrop));
for (i = 0; i < m_nrev; i++) {
irxn = m_revindex[i];
cout << "Reaction " << reactionString(irxn)
<< " " << rmu[irxn]/rt << endl;
printf("%12.6e %12.6e %12.6e %12.6e \n",
frop[irxn], rrop[irxn], netrop[irxn],
netrop[irxn]/(frop[irxn] + rrop[irxn]));
}
}
}
/**
* Get the equilibrium constants of all reactions, whether
* reversible or not.
*/
void InterfaceKinetics::getEquilibriumConstants(doublereal* kc) {
int i;
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
for (n = 0; n < np; n++) {
thermo(n).getStandardChemPotentials(DATA_PTR(m_mu0) + m_start[n]);
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
m_mu0[ik] -= rt*thermo(n).logStandardConc(k);
m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
ik++;
}
}
fill(kc, kc + m_ii, 0.0);
//m_reactantStoich.decrementReactions(m_mu0.begin(), kc);
//m_revProductStoich.incrementReactions(m_mu0.begin(), kc);
//m_irrevProductStoich.incrementReactions(m_mu0.begin(), kc);
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_mu0), kc);
for (i = 0; i < m_ii; i++) {
kc[i] = exp(-kc[i]*rrt);
}
}
/**
* For reactions that transfer charge across a potential difference,
* the activation energies are modified by the potential difference.
* (see, for example, ...). This method applies this correction.
*/
void InterfaceKinetics::applyButlerVolmerCorrection(doublereal* kf) {
int i;
int n, nsp, k, ik=0;
doublereal rt = GasConstant*thermo(0).temperature();
doublereal rrt = 1.0/rt;
int np = nPhases();
// compute the electrical potential energy of each species
for (n = 0; n < np; n++) {
nsp = thermo(n).nSpecies();
for (k = 0; k < nsp; k++) {
m_pot[ik] = Faraday*thermo(n).charge(k)*m_phi[n];
ik++;
}
}
// compute the change in electrical potential energy for each
// reaction. This will only be non-zero if a potential
// difference is present.
//fill(m_rwork.begin(), m_rwork.begin() + m_ii, 0.0);
//m_reactantStoich.decrementReactions(m_pot.begin(), m_rwork.begin());
//m_revProductStoich.incrementReactions(m_pot.begin(), m_rwork.begin());
//m_irrevProductStoich.incrementReactions(m_pot.begin(), m_rwork.begin());
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_pot),
DATA_PTR(m_rwork));
// modify the reaction rates. Only modify those with a
// non-zero activation energy, and do not decrease the
// activation energy below zero.
doublereal ea, eamod;
for (i = 0; i < m_ii; i++) {
eamod = 0.5*m_rwork[i];
if (eamod != 0.0 && m_E[i] != 0.0) {
ea = GasConstant * m_E[i];
if (eamod + ea < 0.0) {
eamod = -ea;
writelog("warning: modified E < 0.\n");
}
kf[i] *= exp(-eamod*rrt);
// if (kf[i] == 0.0) {
// for (n = 0; n < np; n++) {
// cout << "phi " << n << " " << thermo(n).electricPotential() << " " << m_phi[n] << endl;
// }
// cout << "Zero rate coeff." << endl;
// cout << "eamod = " << eamod << " " << eamod*rrt << endl;
// cout << eamod/Faraday << endl;
// }
}
}
}
/**
* Update the rates of progress of the reactions in the reaciton
* mechanism. This routine operates on internal data.
*/
void InterfaceKinetics::getFwdRateConstants(doublereal* kfwd) {
_update_rates_T();
_update_rates_C();
const vector_fp& rf = m_kdata->m_rfn;
// copy rate coefficients into kfwd
copy(rf.begin(), rf.end(), kfwd);
// multiply by perturbation factor
multiply_each(kfwd, kfwd + nReactions(), m_perturb.begin());
}
/**
* Update the rates of progress of the reactions in the reaciton
* mechanism. This routine operates on internal data.
*/
void InterfaceKinetics::getRevRateConstants(doublereal* krev, bool doIrreversible) {
getFwdRateConstants(krev);
if (doIrreversible) {
doublereal *tmpKc = DATA_PTR(m_kdata->m_ropnet);
getEquilibriumConstants(tmpKc);
for (int i = 0; i < m_ii; i++) {
krev[i] /= tmpKc[i];
}
}
else {
const vector_fp& rkc = m_kdata->m_rkcn;
multiply_each(krev, krev + nReactions(), rkc.begin());
}
}
void InterfaceKinetics::getActivationEnergies(doublereal *E) {
copy(m_E.begin(), m_E.end(), E);
}
/**
* Update the rates of progress of the reactions in the reaciton
* mechanism. This routine operates on internal data.
*/
void InterfaceKinetics::updateROP() {
_update_rates_T();
_update_rates_C();
if (m_kdata->m_ROP_ok) return;
const vector_fp& rf = m_kdata->m_rfn;
const vector_fp& m_rkc = m_kdata->m_rkcn;
array_fp& ropf = m_kdata->m_ropf;
array_fp& ropr = m_kdata->m_ropr;
array_fp& ropnet = m_kdata->m_ropnet;
// copy rate coefficients into ropf
copy(rf.begin(), rf.end(), ropf.begin());
// multiply by perturbation factor
multiply_each(ropf.begin(), ropf.end(), m_perturb.begin());
// copy the forward rates to the reverse rates
copy(ropf.begin(), ropf.end(), ropr.begin());
// for reverse rates computed from thermochemistry, multiply
// the forward rates copied into m_ropr by the reciprocals of
// the equilibrium constants
multiply_each(ropr.begin(), ropr.end(), m_rkc.begin());
// multiply ropf by concentration products
m_rxnstoich.multiplyReactants(DATA_PTR(m_conc), DATA_PTR(ropf));
//m_reactantStoich.multiply(m_conc.begin(), ropf.begin());
// for reversible reactions, multiply ropr by concentration
// products
m_rxnstoich.multiplyRevProducts(DATA_PTR(m_conc),
DATA_PTR(ropr));
//m_revProductStoich.multiply(m_conc.begin(), ropr.begin());
// do global reactions
//m_globalReactantStoich.power(m_conc.begin(), ropf.begin());
for (int j = 0; j != m_ii; ++j) {
ropnet[j] = ropf[j] - ropr[j];
}
m_kdata->m_ROP_ok = true;
}
/**
*
* getDeltaGibbs():
*
* Return the vector of values for the reaction gibbs free energy
* change
* These values depend upon the concentration
* of the ideal gas.
*
* units = J kmol-1
*/
void InterfaceKinetics::getDeltaGibbs(doublereal* deltaG) {
/*
* Get the chemical potentials of the species in the
* ideal gas solution.
*/
int np = nPhases();
int n;
for (n = 0; n < np; n++) {
thermo(n).getChemPotentials(DATA_PTR(m_grt) + m_start[n]);
}
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_grt), deltaG);
}
/**
*
* getDeltaEnthalpy():
*
* Return the vector of values for the reactions change in
* enthalpy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
void InterfaceKinetics::getDeltaEnthalpy(doublereal* deltaH) {
/*
* Get the partial molar enthalpy of all species in the
* ideal gas.
*/
int np = nPhases();
int n;
for (n = 0; n < np; n++) {
thermo(n).getPartialMolarEnthalpies(DATA_PTR(m_grt) + m_start[n]);
}
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_grt), deltaH);
}
/************************************************************************
*
* getDeltaEntropy():
*
* Return the vector of values for the reactions change in
* entropy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
void InterfaceKinetics::getDeltaEntropy( doublereal* deltaS) {
/*
* Get the partial molar entropy of all species in the
* solid solution.
*/
int np = nPhases();
int n;
for (n = 0; n < np; n++) {
thermo(n).getPartialMolarEntropies(DATA_PTR(m_grt) + m_start[n]);
}
/*
* Use the stoichiometric manager to find deltaS for each
* reaction.
*/
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_grt), deltaS);
}
/**
*
* getDeltaSSGibbs():
*
* Return the vector of values for the reaction
* standard state gibbs free energy change.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
void InterfaceKinetics::getDeltaSSGibbs(doublereal* deltaG) {
/*
* Get the standard state chemical potentials of the species.
* This is the array of chemical potentials at unit activity
* We define these here as the chemical potentials of the pure
* species at the temperature and pressure of the solution.
*/
int np = nPhases();
int n;
for (n = 0; n < np; n++) {
thermo(n).getStandardChemPotentials(DATA_PTR(m_grt) + m_start[n]);
}
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_grt), deltaG);
}
/**
*
* getDeltaSSEnthalpy():
*
* Return the vector of values for the change in the
* standard state enthalpies of reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
void InterfaceKinetics::getDeltaSSEnthalpy(doublereal* deltaH) {
/*
* Get the standard state enthalpies of the species.
* This is the array of chemical potentials at unit activity
* We define these here as the enthalpies of the pure
* species at the temperature and pressure of the solution.
*/
int np = nPhases();
int n;
for (n = 0; n < np; n++) {
thermo(n).getEnthalpy_RT(DATA_PTR(m_grt) + m_start[n]);
}
doublereal RT = thermo().temperature() * GasConstant;
for (int k = 0; k < m_kk; k++) {
m_grt[k] *= RT;
}
/*
* Use the stoichiometric manager to find deltaG for each
* reaction.
*/
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_grt), deltaH);
}
/*********************************************************************
*
* getDeltaSSEntropy():
*
* Return the vector of values for the change in the
* standard state entropies for each reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
void InterfaceKinetics::getDeltaSSEntropy(doublereal* deltaS) {
/*
* Get the standard state entropy of the species.
* We define these here as the entropies of the pure
* species at the temperature and pressure of the solution.
*/
int np = nPhases();
int n;
for (n = 0; n < np; n++) {
thermo(n).getEntropy_R(DATA_PTR(m_grt) + m_start[n]);
}
doublereal R = GasConstant;
for (int k = 0; k < m_kk; k++) {
m_grt[k] *= R;
}
/*
* Use the stoichiometric manager to find deltaS for each
* reaction.
*/
m_rxnstoich.getReactionDelta(m_ii, DATA_PTR(m_grt), deltaS);
}
/**
* Add a single reaction to the mechanism. This routine
* must be called after init() and before finalize().
* This function branches on the types of reactions allowed
* by the interfaceKinetics manager in order to install
* the reaction correctly in the manager.
* The manager allows the following reaction types
* Elementary
* Surface
* Global
* There is no difference between elementary and surface
* reactions.
*/
void InterfaceKinetics::
addReaction(const ReactionData& r) {
addElementaryReaction(r);
// operations common to all reaction types
installReagents( r );
//installGroups(reactionNumber(), r.rgroups, r.pgroups);
incrementRxnCount();
m_rxneqn.push_back(r.equation);
}
void InterfaceKinetics::
addElementaryReaction(const ReactionData& r) {
int iloc;
// install rate coeff calculator
vector_fp rp = r.rateCoeffParameters;
int ncov = r.cov.size();
if (ncov > 3) {
m_has_coverage_dependence = true;
}
for (int m = 0; m < ncov; m++) rp.push_back(r.cov[m]);
iloc = m_rates.install( reactionNumber(),
r.rateCoeffType, rp.size(),
DATA_PTR(rp) );
// store activation energy
m_E.push_back(r.rateCoeffParameters[2]);
// add constant term to rate coeff value vector
m_kdata->m_rfn.push_back(r.rateCoeffParameters[0]);
registerReaction( reactionNumber(), ELEMENTARY_RXN, iloc);
}
// void InterfaceKinetics::
// addGlobalReaction(const ReactionData& r) {
// int iloc;
// // install rate coeff calculator
// vector_fp rp = r.rateCoeffParameters;
// int ncov = r.cov.size();
// for (int m = 0; m < ncov; m++) rp.push_back(r.cov[m]);
// iloc = m_rates.install( reactionNumber(),
// r.rateCoeffType, rp.size(),
// rp.begin() );
// // store activation energy
// m_E.push_back(r.rateCoeffParameters[2]);
// // add constant term to rate coeff value vector
// m_kdata->m_rfn.push_back(r.rateCoeffParameters[0]);
// int nr = r.order.size();
// vector_fp ordr(nr);
// for (int n = 0; n < nr; n++) {
// ordr[n] = r.order[n] - r.rstoich[n];
// }
// m_globalReactantStoich.add( reactionNumber(),
// r.reactants, ordr);
// registerReaction( reactionNumber(), GLOBAL_RXN, iloc);
// }
void InterfaceKinetics::installReagents(const ReactionData& r) {
int n, ns, m;
doublereal nsFlt;
/*
* extend temporary storage by one for this rxn.
*/
m_kdata->m_ropf.push_back(0.0);
m_kdata->m_ropr.push_back(0.0);
m_kdata->m_ropnet.push_back(0.0);
m_kdata->m_rkcn.push_back(0.0);
/*
* Obtain the current reaction index for the reaction that we
* are adding. The first reaction is labeled 0.
*/
int rnum = reactionNumber();
// vectors rk and pk are lists of species numbers, with
// repeated entries for species with stoichiometric
// coefficients > 1. This allows the reaction to be defined
// with unity reaction order for each reactant, and so the
// faster method 'multiply' can be used to compute the rate of
// progress instead of 'power'.
vector_int rk;
int nr = r.reactants.size();
for (n = 0; n < nr; n++) {
nsFlt = r.rstoich[n];
ns = (int) nsFlt;
if ((doublereal) ns != nsFlt) {
if (ns < 1) ns = 1;
}
/*
* Add to m_rrxn. m_rrxn is a vector of maps. m_rrxn has a length
* equal to the total number of species for each species, there
* exists a map, with the reaction number being the key, and the
* reactant stoichiometric coefficient being the value.
*/
m_rrxn[r.reactants[n]][rnum] = ns;
for (m = 0; m < ns; m++) {
rk.push_back(r.reactants[n]);
}
}
/*
* Now that we have rk[], we add it into the vector<vector_int> m_reactants
* in the rnum index spot. Thus m_reactants[rnum] yields a vector
* of reactants for the rnum'th reaction
*/
m_reactants.push_back(rk);
vector_int pk;
int np = r.products.size();
for (n = 0; n < np; n++) {
nsFlt = r.pstoich[n];
ns = (int) nsFlt;
if ((doublereal) ns != nsFlt) {
if (ns < 1) ns = 1;
}
/*
* Add to m_prxn. m_prxn is a vector of maps. m_prxn has a length
* equal to the total number of species for each species, there
* exists a map, with the reaction number being the key, and the
* product stoichiometric coefficient being the value.
*/
m_prxn[r.products[n]][rnum] = ns;
for (m = 0; m < ns; m++) {
pk.push_back(r.products[n]);
}
}
/*
* Now that we have pk[], we add it into the vector<vector_int> m_products
* in the rnum index spot. Thus m_products[rnum] yields a vector
* of products for the rnum'th reaction
*/
m_products.push_back(pk);
/*
* Add this reaction to the stoichiometric coefficient manager. This
* calculates rates of species production from reaction rates of
* progress.
*/
m_rxnstoich.add( reactionNumber(), r);
/*
* register reaction in lists of reversible and irreversible rxns.
*/
if (r.reversible) {
m_revindex.push_back(reactionNumber());
m_nrev++;
} else {
m_irrev.push_back( reactionNumber() );
m_nirrev++;
}
}
//void InterfaceKinetics::installGroups(int irxn,
// const vector<grouplist_t>& r, const vector<grouplist_t>& p) {
// if (!r.empty()) {
// m_rgroups[reactionNumber()] = r;
// m_pgroups[reactionNumber()] = p;
// }
//}
/**
* Prepare the class for the addition of reactions. This function
* must be called after instantiation of the class, but before
* any reactions are actually added to the mechanism.
* This function calculates m_kk the number of species in all
* phases participating in the reaction mechanism. We don't know
* m_kk previously, before all phases have been added.
*/
void InterfaceKinetics::init() {
int n;
m_kk = 0;
int np = nPhases();
for (n = 0; n < np; n++) {
m_kk += thermo(n).nSpecies();
}
m_rrxn.resize(m_kk);
m_prxn.resize(m_kk);
m_conc.resize(m_kk);
m_mu0.resize(m_kk);
m_grt.resize(m_kk);
m_pot.resize(m_kk, 0.0);
m_phi.resize(np, 0.0);
}
/**
* Finish adding reactions and prepare for use. This function
* must be called after all reactions are entered into the mechanism
* and before the mechanism is used to calculate reaction rates.
*
* Here, we resize work arrays based on the number of reactions,
* since we don't know this number up to now.
*/
void InterfaceKinetics::finalize() {
m_rwork.resize(nReactions());
int ks = surfacePhaseIndex();
if (ks < 0) throw CanteraError("InterfaceKinetics::finalize",
"no surface phase is present.");
m_surf = (SurfPhase*)&thermo(ks);
m_finalized = true;
}
bool InterfaceKinetics::ready() const {
return (m_finalized);
}
void InterfaceKinetics::
advanceCoverages(doublereal tstep) {
if (m_integrator == 0) {
vector<InterfaceKinetics*> k;
k.push_back(this);
m_integrator = new ImplicitSurfChem(k);
m_integrator->initialize();
}
m_integrator->integrate(0.0, tstep);
delete m_integrator;
m_integrator = 0;
}
}

View file

@ -0,0 +1,419 @@
/**
* @file InterfaceKinetics.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_IFACEKINETICS_H
#define CT_IFACEKINETICS_H
#include <fstream>
#include <math.h>
#include <map>
#include <stdlib.h>
#include "mix_defs.h"
#include "Kinetics.h"
#include "utilities.h"
#include "RateCoeffMgr.h"
#include "ReactionStoichMgr.h"
namespace Cantera {
// forward references
class ReactionData;
class InterfaceKineticsData;
class ThermoPhase;
class SurfPhase;
class ImplicitSurfChem;
/**
* Holds mechanism-specific data.
*/
class InterfaceKineticsData {
public:
InterfaceKineticsData() :
m_ROP_ok(false),
m_temp(0.0), m_logtemp(0.0)
{}
virtual ~InterfaceKineticsData(){}
doublereal m_logp0, m_logc0;
array_fp m_ropf, m_ropr, m_ropnet;
//array_fp m_rfn_low, m_rfn_high;
bool m_ROP_ok;
doublereal m_temp, m_logtemp;
vector_fp m_rfn;
vector_fp m_rkcn;
};
///
/// A kinetics manager for heterogeneous reaction mechanisms. The
/// reactions are assumed to occur at a 2D interface between two
/// 3D phases.
///
class InterfaceKinetics : public Kinetics {
public:
/**
* Constructor
*
* @param thermo The optional parameter may be used to initialize
* the object with one ThermoPhase object.
* HKM Note -> Since the interface kinetics
* object will probably require multiple thermophase
* objects, this is probably not a good idea
* to have this parameter.
*/
InterfaceKinetics(thermo_t* thermo = 0);
/// Destructor.
virtual ~InterfaceKinetics();
virtual int ID() { return cInterfaceKinetics; }
virtual int type() { return cInterfaceKinetics; }
///
/// @name Reaction Rates Of Progress
///
//@{
virtual void getFwdRatesOfProgress(doublereal* fwdROP) {
updateROP();
std::copy(m_kdata->m_ropf.begin(), m_kdata->m_ropf.end(), fwdROP);
}
virtual void getRevRatesOfProgress(doublereal* revROP) {
updateROP();
std::copy(m_kdata->m_ropr.begin(), m_kdata->m_ropr.end(), revROP);
}
virtual void getNetRatesOfProgress(doublereal* netROP) {
updateROP();
std::copy(m_kdata->m_ropnet.begin(), m_kdata->m_ropnet.end(), netROP);
}
virtual void getEquilibriumConstants(doublereal* kc);
virtual void getDeltaGibbs( doublereal* deltaG);
/**
* Return the vector of values for the reactions change in
* enthalpy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaEnthalpy( doublereal* deltaH);
/**
* Return the vector of values for the reactions change in
* entropy.
* These values depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
virtual void getDeltaEntropy(doublereal* deltaS);
/**
* Return the vector of values for the reaction
* standard state gibbs free energy change.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaSSGibbs(doublereal* deltaG);
/**
* Return the vector of values for the change in the
* standard state enthalpies of reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1
*/
virtual void getDeltaSSEnthalpy(doublereal* deltaH);
/**
* Return the vector of values for the change in the
* standard state entropies for each reaction.
* These values don't depend upon the concentration
* of the solution.
*
* units = J kmol-1 Kelvin-1
*/
virtual void getDeltaSSEntropy(doublereal* deltaS);
//@}
/**
* @name Species Production Rates
*/
//@{
/**
* Species creation rates [kmol/m^2/s]. Return the species
* creation rates in array cdot, which must be
* dimensioned at least as large as the total number of
* species in all phases of the kinetics
* model
*
*/
virtual void getCreationRates(doublereal* cdot) {
updateROP();
m_rxnstoich.getCreationRates(m_kk, &m_kdata->m_ropf[0],
&m_kdata->m_ropr[0], cdot);
}
/**
* Species destruction rates [kmol/m^2/s]. Return the species
* destruction rates in array ddot, which must be
* dimensioned at least as large as the total number of
* species in all phases of the kinetics
* model
*
*/
virtual void getDestructionRates(doublereal* ddot) {
updateROP();
m_rxnstoich.getDestructionRates(m_kk, &m_kdata->m_ropf[0],
&m_kdata->m_ropr[0], ddot);
}
/**
* Species net production rates [kmol/m^2/s]. Return the species
* net production rates (creation - destruction) in array
* wdot, which must be dimensioned at least as large as the
* total number of species in all phases of the kinetics
* model
*/
virtual void getNetProductionRates(doublereal* net) {
updateROP();
m_rxnstoich.getNetProductionRates(m_kk,
&m_kdata->m_ropnet[0],
net);
}
//@}
/**
* @name Reaction Mechanism Informational Query Routines
*/
//@{
/**
* Stoichiometric coefficient of species k as a reactant in
* reaction i.
*/
virtual doublereal reactantStoichCoeff(int k, int i) const {
return m_rrxn[k][i];
}
/**
* Stoichiometric coefficient of species k as a product in
* reaction i.
*/
virtual doublereal productStoichCoeff(int k, int i) const {
return m_prxn[k][i];
}
/**
* Flag specifying the type of reaction. The legal values and
* their meaning are specific to the particular kinetics
* manager.
*/
virtual int reactionType(int i) const {
return m_index[i].first;
}
/**
* True if reaction i has been declared to be reversible. If
* isReversible(i) is false, then the reverse rate of progress
* for reaction i is always zero.
*/
virtual bool isReversible(int i) {
if (std::find(m_revindex.begin(), m_revindex.end(), i)
< m_revindex.end()) return true;
else return false;
}
/**
* Return a string representing the reaction.
*/
virtual std::string reactionString(int i) const {
return m_rxneqn[i];
}
virtual void getFwdRateConstants(doublereal* kfwd);
virtual void getRevRateConstants(doublereal* krev,
bool doIrreversible = false);
virtual void getActivationEnergies(doublereal *E);
//@}
/**
* @name Reaction Mechanism Construction
*/
//@{
/**
* Prepare the class for the addition of reactions. This function
* must be called after instantiation of the class, but before
* any reactions are actually added to the mechanism.
* This function calculates m_kk the number of species in all
* phases participating in the reaction mechanism. We don't know
* m_kk previously, before all phases have been added.
*/
virtual void init();
/**
* Add a single reaction to the mechanism.
*/
virtual void addReaction(const ReactionData& r);
/**
* Finish adding reactions and prepare for use. This function
* must be called after all reactions are entered into the mechanism
* and before the mechanism is used to calculate reaction rates.
*/
virtual void finalize();
virtual bool ready() const;
void updateROP();
//const std::vector<grouplist_t>& reactantGroups(int i)
// { return m_rgroups[i]; }
//const std::vector<grouplist_t>& productGroups(int i)
// { return m_pgroups[i]; }
void _update_rates_T();
void _update_rates_phi();
void _update_rates_C();
void advanceCoverages(doublereal tstep);
void checkPartialEquil();
vector_fp m_grt;
protected:
/**
* m_kk here is the number of species in all of the phases
* that participate in the kinetics mechanism.
*/
int m_kk;
vector_int m_revindex;
Rate1<SurfaceArrhenius> m_rates;
bool m_redo_rates;
/**
* Vector of information about reactions in the
* mechanism.
* The key is the reaction index (0 < i < m_ii).
* The first pair is the reactionType of the reaction.
* The second pair is ...
*/
mutable std::map<int, std::pair<int, int> > m_index;
std::vector<int> m_irrev;
ReactionStoichMgr m_rxnstoich;
int m_nirrev;
/**
* Number of reversible reactions in the mechanism
*/
int m_nrev;
std::vector<int> m_rxntype;
/**
* m_rrxn is a vector of maps. m_rrxn has a length
* equal to the total number of species in the kinetics
* object. For each species, there exists a map, with the
* reaction number being the key, and the
* reactant stoichiometric coefficient being the value.
* HKM -> mutable because search sometimes creates extra
* entries. To be fixed in future...
*/
mutable std::vector<std::map<int, doublereal> > m_rrxn;
/**
* m_rrxn is a vector of maps. m_rrxn has a length
* equal to the total number of species in the kinetics
* object. For each species, there exists a map, with the
* reaction number being the key, and the
* product stoichiometric coefficient being the value.
*/
mutable std::vector<std::map<int, doublereal> > m_prxn;
std::vector<std::string> m_rxneqn;
/**
* Temporary data storage used in calculating the rates of
* of reactions.
*/
InterfaceKineticsData* m_kdata;
/**
* An array of generalized concentrations
* \f$ C_k \f$ that are defined such that \f$ a_k = C_k /
* C^0_k, \f$ where \f$ C^0_k \f$ is a standard concentration/
* These generalized concentrations are used
* by this kinetics manager class to compute the forward and
* reverse rates of elementary reactions. The "units" for the
* concentrations of each phase depend upon the implementation
* of kinetics within that phase.
* The order of the species within the vector is based on
* the order of listed ThermoPhase objects in the class, and the
* order of the species within each ThermoPhase class.
*/
vector_fp m_conc;
vector_fp m_mu0;
vector_fp m_phi;
vector_fp m_pot;
vector_fp m_rwork;
vector_fp m_E;
SurfPhase* m_surf;
ImplicitSurfChem* m_integrator;
private:
int reactionNumber(){ return m_ii;}
void addElementaryReaction(const ReactionData& r);
void addGlobalReaction(const ReactionData& r);
void installReagents(const ReactionData& r);
void updateKc();
void registerReaction(int rxnNumber, int type, int loc) {
m_index[rxnNumber] = std::pair<int, int>(type, loc);
}
void applyButlerVolmerCorrection(doublereal* kf);
bool m_finalized;
bool m_has_coverage_dependence;
};
}
#endif

View file

@ -0,0 +1,234 @@
/**
* @file Kinetics.cpp
* Declarations for the base class for kinetics
* managers (see \ref kineticsmgr and class
* \link Cantera::Kinetics Kinetics\endlink).
*
* Kinetics managers calculate rates of progress of species due to homogeneous or heterogeneous kinetics.
*/
// Copyright 2001-2004 California Institute of Technology
#include "InterfaceKinetics.h"
#include "SurfPhase.h"
#include "ReactionData.h"
#include "StoichManager.h"
#include "RateCoeffMgr.h"
#include "ImplicitSurfChem.h"
#include <iostream>
using namespace std;
namespace Cantera {
Kinetics::Kinetics() : m_ii(0), m_thermo(0),
m_index(-1), m_surfphase(-1), m_rxnphase(-1),
m_mindim(4) {}
/*
Kinetics::Kinetics(thermo_t* thermo) :
m_ii(0),
m_index(-1),
m_surfphase(-1) ,
m_rxnphase(0), m_mindim(4)
{
if (thermo) {
addPhase(*thermo);
}
deprecatedMethod("Kinetics","Kinetics(thermo_t*)","Kinetics()");
removeAtVersion("Kinetics(thermo_t*)","1.6.0");
}
*/
Kinetics::~Kinetics(){}
/**
* Takes as input an array of properties for all species in the
* mechanism and copies those values beloning to a particular
* phase to the output array.
* @param data Input data array.
* @param phase Pointer to one of the phase objects participating
* in this reaction mechanism
* @param phase_data Output array where the values for the the
* specified phase are to be written.
*/
void Kinetics::selectPhase(const doublereal* data, const thermo_t* phase,
doublereal* phase_data) {
int n, nsp, np = nPhases();
for (n = 0; n < np; n++) {
if (phase == m_thermo[n]) {
nsp = phase->nSpecies();
copy(data + m_start[n],
data + m_start[n] + nsp, phase_data);
return;
}
}
throw CanteraError("Kinetics::selectPhase", "Phase not found.");
}
/**
* kineticsSpeciesName():
*
* Return the string name of the kth species in the kinetics
* manager. k is an integer from 0 to ktot - 1, where ktot is
* the number of species in the kinetics manager, which is the
* sum of the number of species in all phases participating in
* the kinetics manager. If k is out of bounds, the string
* "<unknown>" is returned.
*/
string Kinetics::kineticsSpeciesName(int k) const {
int np = m_start.size();
for (int n = np-1; n >= 0; n--) {
if (k >= m_start[n]) {
return thermo(n).speciesName(k - m_start[n]);
}
}
return "<unknown>";
}
/**
* kineticsSpeciesIndex():
*
* This routine will look up a species number based on
* the input string nm. The lookup of species will
* occur for all phases listed in the kinetics object,
* unless the string ph refers to a specific phase of
* the object.
*
* return
* - If a match is found, the position in the species list
* is returned.
* - If a specific phase is specified and no match is found,
* the value -1 is returned.
* - If no match is found in any phase, the value -2 is returned.
*/
int Kinetics::kineticsSpeciesIndex(std::string nm, std::string ph) const {
int np = static_cast<int>(m_thermo.size());
int k;
string id;
for (int n = 0; n < np; n++) {
id = thermo(n).id();
if (ph == id) {
k = thermo(n).speciesIndex(nm);
if (k < 0) return -1;
return k + m_start[n];
}
else if (ph == "<any>") {
/*
* Call the speciesIndex() member function of the
* ThermoPhase object to find a match.
*/
k = thermo(n).speciesIndex(nm);
if (k >= 0) return k + m_start[n];
}
}
return -2;
}
/**
* This function looks up the string name of a species and
* returns a reference to the ThermoPhase object of the
* phase where the species resides.
* Will throw an error if the species string doesn't match.
*/
thermo_t& Kinetics::speciesPhase(std::string nm) {
int np = static_cast<int>(m_thermo.size());
int k;
string id;
for (int n = 0; n < np; n++) {
k = thermo(n).speciesIndex(nm);
if (k >= 0) return thermo(n);
}
throw CanteraError("speciesPhase", "unknown species "+nm);
}
/**
* This function takes as an argument the kineticsSpecies index
* (i.e., the list index in the list of species in the kinetics
* manager) and returns the index of the phase owning the
* species.
*/
int Kinetics::speciesPhaseIndex(int k) {
int np = m_start.size();
for (int n = np-1; n >= 0; n--) {
if (k >= m_start[n]) {
return n;
}
}
throw CanteraError("speciesPhaseIndex",
"illegal species index: "+int2str(k));
}
/**
* Add a phase to the kinetics manager object. This must
* be done before the function init() is called or
* before any reactions are input.
* The following fields are updated:
* m_start -> vector of integers, containing the
* starting position of the species for
* each phase in the kinetics mechanism.
* m_surfphase -> index of the surface phase.
* m_thermo -> vector of pointers to ThermoPhase phases
* that participate in the kinetics
* mechanism.
* m_phaseindex -> map containing the string id of each
* ThermoPhase phase as a key and the
* index of the phase within the kinetics
* manager object as the value.
*/
void Kinetics::addPhase(thermo_t& thermo) {
// if not the first thermo object, set the start position
// to that of the last object added + the number of its species
if (m_thermo.size() > 0) {
m_start.push_back(m_start.back()
+ m_thermo.back()->nSpecies());
}
// otherwise start at 0
else {
m_start.push_back(0);
}
// the phase with lowest dimensionality is assumed to be the
// phase/interface at which reactions take place
if (thermo.nDim() <= m_mindim) {
m_mindim = thermo.nDim();
m_rxnphase = nPhases();
}
// there should only be one surface phase
int ptype = -100;
if (type() == cEdgeKinetics) ptype = cEdge;
else if (type() == cInterfaceKinetics) ptype = cSurf;
if (thermo.eosType() == ptype) {
// if (m_surfphase >= 0) {
// throw CanteraError("Kinetics::addPhase",
// "cannot add more than one surface phase");
// }
m_surfphase = nPhases();
m_rxnphase = nPhases();
}
m_thermo.push_back(&thermo);
m_phaseindex[m_thermo.back()->id()] = nPhases();
}
//! Private function of the class Kinetics, indicating that a function
//! inherited from the base class hasn't had a definition assigned to it
/*!
* @param m String message
*/
void Kinetics::err(std::string m) const {
throw CanteraError("Kinetics::" + m,
"The default Base class method was called, when "
"the inherited class's method should "
"have been called");
}
}

956
Cantera/src/kinetics/Kinetics.h Executable file
View file

@ -0,0 +1,956 @@
/**
* @file Kinetics.h
* Base class for kinetics managers and also contains the kineticsmgr
* module documentation (see \ref kineticsmgr and class
* \link Cantera::Kinetics Kinetics\endlink).
*
* $Author$
* $Date$
* $Revision$
*/
// Copyright 2001-2004 California Institute of Technology
#ifndef CT_KINETICS_H
#define CT_KINETICS_H
#include "ctexceptions.h"
#include "ThermoPhase.h"
#include "mix_defs.h"
namespace Cantera {
// forward references
class ReactionData;
/// @defgroup kineticsmgr Kinetics Managers
/// @section kinmodman Models and Managers
///
/// A kinetics manager is a C++ class that implements a kinetics
/// model; a kinetics model is a set of mathematical equation
/// describing how various kinetic quanities are to be computed --
/// reaction rates, species production rates, etc. Many different
/// kinetics models might be defined to handle different types of
/// kinetic processes. For example, one kinetics model might use
/// expressions valid for elementary reactions in ideal gas
/// mixtures. It might, for example, require the reaction orders
/// to be integral and equal to the forward stoichiometric
/// coefficients, require that each reaction be reversible with a
/// reverse rate satisfying detailed balance, include
/// pressure-dependent unimolecular reactions, etc. Another
/// kinetics model might be designed for heterogeneous chemistry
/// at interfaces, and might allow empirical reaction orders,
/// coverage-dependent activation energies, irreversible
/// reactions, and include effects of potential differences across
/// the interface on reaction rates.
///
/// A kinetics manager implements a kinetics model. Since the
/// model equations may be complex and expensive to evaluate, a
/// kinetics manager may adopt various strategies to 'manage' the
/// computation and evaluate the expressions efficiently. For
/// example, if there are rate coefficients or other quantities
/// that depend only on temperature, a manager class may choose to
/// store these quantities internally, and re-evaluate them only
/// when the temperature has actually changed. Or a manager
/// designed for use with reaction mechanisms with a few repeated
/// activation energies might precompute the terms \f$ exp(-E/RT)
/// \f$, instead of evaluating the exponential repeatedly for each
/// reaction. There are many other possible 'management styles',
/// each of which might be better suited to some reaction
/// mechanisms than others.
///
/// But however a manager structures the internal computation, the
/// tasks the manager class must perform are, for the most part,
/// the same. It must be able to compute reaction rates, species
/// production rates, equilibrium constants, etc. Therefore, all
/// kinetics manager classes should have a common set of public
/// methods, but differ in how they implement these methods.
///
/// A kinetics manager computes reaction rates of progress,
/// species production rates, equilibrium constants, and similar
/// quantities for a reaction mechanism. All kinetics manager
/// classes derive from class Kinetics, which defines a common
/// public interface for all kinetics managers. Each derived class
/// overloads the virtual methods of Kinetics to implement a
/// particular kinetics model.
///
/// For example, class GasKinetics implements reaction rate
/// expressions appropriate for homogeneous reactions in ideal gas
/// mixtures, and class InterfaceKinetics implements expressions
/// appropriate for heterogeneous mechanisms at interfaces,
/// including how to handle reactions involving charged species of
/// phases with different electric potentials --- something that
/// class GasKinetics doesn't deal with at all.
///
/// Kinetics managers may be also created that hard-wire a
/// particular reaction mechanism in C++ code. This can often
/// result in faster performance. An example of this is the
/// kinetics manager GRI30_Kinetics that hard-wires the rate
/// expressions for the natural gas combustion mechanism GRI-3.0.
///
/// Many of the methods of class Kinetics write into arrays the
/// values of some quantity for each species, for example the net
/// production rate. These methods always write the results into
/// flat arrays, ordered by phase in the order the phase was
/// added, and within a phase in the order the species were added
/// to the phase (which is the same ordering as in the input
/// file). Example: suppose a heterogeneous mechanism involves
/// three phases -- a bulk phase 'a', another bulk phase 'b', and
/// the surface phase 'a:b' at the a/b interface. Phase 'a'
/// contains 12 species, phase 'b' contains 3, and at the
/// interface there are 5 adsorbed species defined in phase
/// 'a:b'. Then methods like getNetProductionRates(doublereal* net)
/// will write and output array of length 20, beginning at the location
/// pointed to by 'net'. The first 12 values will be the net production
/// rates for all 12 species of phase 'a' (even if some do not participate
/// in the reactions), the next 3 will be for phase 'b', and finally the
/// net production rates for the surface species will occupy the last
/// 5 locations.
//! Public interface for kinetics managers.
/*!
* This class serves as a
* base class to derive 'kinetics managers', which are classes
* that manage homogeneous chemistry within one phase, or
* heterogeneous chemistry at one interface. The virtual methods
* of this class are meant to be overloaded in subclasses. The
* non-virtual methods perform generic functions and are
* implemented in Kinetics. They should not be overloaded. Only
* those methods required by a subclass need to be overloaded;
* the rest will throw exceptions if called. @ingroup kinetics
* @ingroup kineticsmgr
*/
class Kinetics {
public:
//! typedef for ThermoPhase
typedef ThermoPhase thermo_t;
/**
* @name Constructors and General Information about Mechanism
*/
//@{
/// Default constructor.
Kinetics();
/// This constructor initializes with a starting phase.
/// @deprecated
// Kinetics(thermo_t* thermo);
/// Destructor.
virtual ~Kinetics();
/// Identifies the kinetics manager type. Each class derived
/// from Kinetics should overload this method to return a
/// unique integer. Standard values are defined in file
/// mix_defs.h.
virtual int type() { return 0; }
/// Number of reactions in the reaction mechanism.
int nReactions() const {return m_ii;}
//@}
/**
* @name Information/Lookup Functions about Phases and Species
*/
//@{
/**
* The number of phases participating in the reaction
* mechanism. For a homogeneous reaction mechanism, this will
* always return 1, but for a heterogeneous mechanism it will
* return the total number of phases in the mechanism.
*/
int nPhases() const { return static_cast<int>(m_thermo.size()); }
/**
* Return the phase index of a phase in the list of phases
* defined within the object.
*
* @param ph std::string name of the phase
*
* If a -1 is returned, then the phase is not defined in
* the Kinetics object.
*/
int phaseIndex(std::string ph) {
if (m_phaseindex.find(ph) == m_phaseindex.end()) {
return -1;
}
else {
return m_phaseindex[ph] - 1;
}
}
/**
* This returns the integer index of the phase which has
* ThermoPhase type cSurf. For heterogeneous mechanisms, this
* identifies the one surface phase. For homogeneous
* mechanisms, this reurns -1.
*/
int surfacePhaseIndex() { return m_surfphase; }
/**
* Phase where the reactions occur. For heterogeneous
* mechanisms, one of the phases in the list of phases
* represents the 2D interface or 1D edge at which the
* reactions take place. This method returns the index of the
* phase with the smallest spatial dimension (1, 2, or 3)
* among the list of phases. If there is more than one, the
* index of the first one is returned. For homogeneous
* mechanisms, the value 0 is returned.
*/
int reactionPhaseIndex() { return m_rxnphase; }
/**
* This method returns a reference to the nth ThermoPhase
* object defined in this kinetics mechanism. It is typically
* used so that member functions of the ThermoPhase object may
* be called. For homogeneous mechanisms, there is only one
* object, and this method can be called without an argument
* to access it.
*
* @param n Index of the ThermoPhase being sought.
*/
thermo_t& thermo(int n=0) { return *m_thermo[n]; }
const thermo_t& thermo(int n=0) const { return *m_thermo[n]; }
/**
* This method returns a reference to the nth ThermoPhase
* defined in this kinetics mechanism.
* It is typically used so that member functions of the
* ThermoPhase may be called. @deprecated This method is redundant.
*
* @param n Index of the ThermoPhase being sought.
*/
thermo_t& phase(int n=0) {
deprecatedMethod("Kinetics","phase","thermo");
return *m_thermo[n];
}
/**
* This method returns a reference to the nth ThermoPhase
* defined in this kinetics mechanism.
* It is typically used so that member functions of the
* ThermoPhase may be called. @deprecated This method is redundant.
*
* @param n Index of the ThermoPhase being sought.
*/
const thermo_t& phase(int n=0) const {
deprecatedMethod("Kinetics","phase","thermo");
return *m_thermo[n];
}
/**
* The total number of species in all phases participating in
* the kinetics mechanism. This is useful to dimension arrays
* for use in calls to methods that return the species
* production rates, for example.
*/
int nTotalSpecies() const {
int n=0, np;
np = nPhases();
for (int p = 0; p < np; p++) n += thermo(p).nSpecies();
return n;
}
/**
* Returns the starting index of the species in the nth phase
* associated with the reaction mechanism.
*
* @param n Return the index of first species in the nth phase
* associated with the reaction mechanism.
*/
int start(int n) {
deprecatedMethod("Kinetics","start","kineticsSpeciesIndex(0,n)");
return m_start[n];
}
/**
* The location of species k of phase n in species arrays.
* Kinetics manager classes return species production rates in
* flat arrays, with the species of each phases following one
* another, in the order the phases were added. This method
* is useful to find the value for a particular species of a
* particular phase in arrrays returned from methods like
* getCreationRates that return an array of species-specific
* quantities.
*
* Example: suppose a heterogeneous mechanism involves three
* phases. The first contains 12 species, the second 26, and
* the third 3. Then species arrays must have size at least
* 41, and positions 0 - 11 are the values for the species in
* the first phase, positions 12 - 37 are the values for the
* species in the second phase, etc. Then
* kineticsSpeciesIndex(7, 0) = 7, kineticsSpeciesIndex(4, 1)
* = 16, and kineticsSpeciesIndex(2, 2) = 40.
*
* @param k species index
* @param n phase index for the species
*/
int kineticsSpeciesIndex(int k, int n) const {
return m_start[n] + k;
}
/**
* Return the std::string name of the kth species in the kinetics
* manager. k is an integer from 0 to ktot - 1, where ktot is
* the number of species in the kinetics manager, which is the
* sum of the number of species in all phases participating in
* the kinetics manager. If k is out of bounds, the std::string
* "<unknown>" is returned.
*
* @param k species index
*/
std::string kineticsSpeciesName(int k) const;
/**
* This routine will look up a species number based on
* the input std::string nm. The lookup of species will
* occur for all phases listed in the kinetics object,
* unless the std::string ph refers to a specific phase of
* the object.
*
* return
* - If a match is found, the position in the species list
* is returned.
* - If a specific phase is specified and no match is found,
* the value -1 is returned.
* - If no match is found in any phase, the value -2 is returned.
*
* @param nm Input string name of the species
* @param ph Input string name of the phase. Defaults to "<any>"
*/
int kineticsSpeciesIndex(std::string nm, std::string ph = "<any>") const;
/**
* This function looks up the std::string name of a species and
* returns a reference to the ThermoPhase object of the
* phase where the species resides.
* Will throw an error if the species std::string doesn't match.
*
* @param nm String containing the name of the species.
*/
thermo_t& speciesPhase(std::string nm);
/**
* This function takes as an argument the kineticsSpecies index
* (i.e., the list index in the list of species in the kinetics
* manager) and returns the species' owning ThermoPhase object.
*
* @param k Species index
*/
thermo_t& speciesPhase(int k) {
return thermo(speciesPhaseIndex(k));
}
/**
* This function takes as an argument the kineticsSpecies index
* (i.e., the list index in the list of species in the kinetics
* manager) and returns the index of the phase owning the
* species.
*
* @param k Species index
*/
int speciesPhaseIndex(int k);
//@}
/**
* @name Reaction Rates Of Progress
*/
//@{
//! Return the forward rates of progress of the reactions
/*!
* Forward rates of progress. Return the forward rates of
* progress in array fwdROP, which must be dimensioned at
* least as large as the total number of reactions.
*
* @param fwdROP Output vector containing forward rates
* of progress of the reactions. Length: m_ii.
*/
virtual void getFwdRatesOfProgress(doublereal* fwdROP) {
err("getFwdRatesOfProgress");
}
//! Return the Reverse rates of progress of the reactions
/*!
* Return the reverse rates of
* progress in array revROP, which must be dimensioned at
* least as large as the total number of reactions.
*
* @param revROP Output vector containing reverse rates
* of progress of the reactions. Length: m_ii.
*/
virtual void getRevRatesOfProgress(doublereal* revROP) {
err("getRevRatesOfProgress");
}
/**
* Net rates of progress. Return the net (forward - reverse)
* rates of progress in array netROP, which must be
* dimensioned at least as large as the total number of
* reactions.
*
* @param netROP Output vector of the net ROP. Length: m_ii.
*/
virtual void getNetRatesOfProgress(doublereal* netROP) {
err("getNetRatesOfProgress");
}
//! Return a vector of Equilibrium constants.
/*!
* Return the equilibrium constants of
* the reactions in concentration units in array kc, which
* must be dimensioned at least as large as the total number
* of reactions.
*
* @param kc Output vector containing the equilibrium constants.
* Length: m_ii.
*/
virtual void getEquilibriumConstants(doublereal* kc) {
err("getEquilibriumConstants");
}
/**
* Change in species properties. Given an array of molar species
* property values \f$ z_k, k = 1, \dots, K \f$, return the
* array of reaction values
* \f[
* \Delta Z_i = \sum_k \nu_{k,i} z_k, i = 1, \dots, I.
* \f]
* For example, if this method is called with the array of
* standard-state molar Gibbs free energies for the species,
* then the values returned in array \c deltaProperty would be
* the standard-state Gibbs free energies of reaction for each
* reaction.
*
* @param property Input vector of property value. Length: m_kk.
* @param deltaProperty Output vector of deltaRxn. Length: m_ii.
*/
virtual void getReactionDelta(const doublereal* property,
doublereal* deltaProperty) {
err("getReactionDelta");
}
/**
* Return the vector of values for the reaction gibbs free
* energy change. These values depend upon the concentration
* of the solution.
*
* units = J kmol-1
*
* @param deltaG Output vector of deltaG's for reactions
* Length: m_ii.
*/
virtual void getDeltaGibbs( doublereal* deltaG) {
err("getDeltaGibbs");
}
/**
* Return the vector of values for the reactions change in
* enthalpy. These values depend upon the concentration of
* the solution.
*
* units = J kmol-1
*
* @param deltaH Output vector of deltaH's for reactions
* Length: m_ii.
*/
virtual void getDeltaEnthalpy( doublereal* deltaH) {
err("getDeltaEnthalpy");
}
/**
* Return the vector of values for the reactions change in
* entropy. These values depend upon the concentration of the
* solution.
*
* units = J kmol-1 Kelvin-1
*
* @param deltaS Output vector of deltaS's for reactions
* Length: m_ii.
*/
virtual void getDeltaEntropy( doublereal* deltaS) {
err("getDeltaEntropy");
}
/**
* Return the vector of values for the reaction standard state
* gibbs free energy change. These values don't depend upon
* the concentration of the solution.
*
* units = J kmol-1
*
* @param deltaG Output vector of ss deltaG's for reactions
* Length: m_ii.
*/
virtual void getDeltaSSGibbs( doublereal* deltaG) {
err("getDeltaSSGibbs");
}
/**
* Return the vector of values for the change in the standard
* state enthalpies of reaction. These values don't depend
* upon the concentration of the solution.
*
* units = J kmol-1
*
* @param deltaH Output vector of ss deltaH's for reactions
* Length: m_ii.
*/
virtual void getDeltaSSEnthalpy( doublereal* deltaH) {
err("getDeltaSSEnthalpy");
}
/**
* Return the vector of values for the change in the standard
* state entropies for each reaction. These values don't
* depend upon the concentration of the solution.
*
* units = J kmol-1 Kelvin-1
*
* @param deltaS Output vector of ss deltaS's for reactions
* Length: m_ii.
*/
virtual void getDeltaSSEntropy( doublereal* deltaS) {
err("getDeltaSSEntropy");
}
//@}
/**
* @name Species Production Rates
*/
//@{
/**
* Species creation rates [kmol/m^3/s or kmol/m^2/s]. Return the
* species creation rates in array cdot, which must be
* dimensioned at least as large as the total number of
* species in all phases. @see nTotalSpecies.
*
* @param cdot Output vector of creation rates.
* Length: m_kk.
*/
virtual void getCreationRates(doublereal* cdot) {
err("getCreationRates");
}
/**
* Species destruction rates [kmol/m^3/s or kmol/m^2/s]. Return
* the species destruction rates in array ddot, which must be
* dimensioned at least as large as the total number of
* species. @see nTotalSpecies.
*
* @param ddot Output vector of destruction rates.
* Length: m_kk.
*/
virtual void getDestructionRates(doublereal* ddot) {
err("getDestructionRates");
}
/**
* Species net production rates [kmol/m^3/s or kmol/m^2/s]. Return
* the species net production rates (creation - destruction)
* in array wdot, which must be dimensioned at least as large
* as the total number of species. @see nTotalSpecies.
*
* @param wdot Output vector of net production rates.
* Length: m_kk.
*/
virtual void getNetProductionRates(doublereal* wdot) {
err("getNetProductionRates");
}
//@}
/**
* @name Reaction Mechanism Informational Query Routines
*/
//@{
/**
* Stoichiometric coefficient of species k as a reactant in
* reaction i.
*
* @param k species index
* @param i reaction index
*/
virtual doublereal reactantStoichCoeff(int k, int i) const {
err("reactantStoichCoeff");
return -1.0;
}
/**
* Stoichiometric coefficient of species k as a product in
* reaction i.
*
* @param k species index
* @param i reaction index
*/
virtual doublereal productStoichCoeff(int k, int i) const {
err("productStoichCoeff");
return -1.0;
}
/**
* reactant Order of species k in reaction i.
*
* @param k species index
* @param i reaction index
*/
virtual doublereal reactantOrder(int k, int i) const {
err("reactantOrder");
return -1.0;
}
/**
* Returns a read-only reference to the vector of reactant
* index numbers for reaction i.
*
* @param i reaction index
*/
virtual const vector_int& reactants(int i) const {
return m_reactants[i];
}
/**
* Returns a read-only reference to the vector of product
* index numbers for reaction i.
*
* @param i reaction index
*/
virtual const vector_int& products(int i) const {
return m_products[i];
}
/**
* Flag specifying the type of reaction. The legal values and
* their meaning are specific to the particular kinetics
* manager.
*
* @param i reaction index
*/
virtual int reactionType(int i) const {
err("reactionType");
return -1;
}
/**
* True if reaction i has been declared to be reversible. If
* isReversible(i) is false, then the reverse rate of progress
* for reaction i is always zero.
*
* @param i reaction index
*/
virtual bool isReversible(int i){
err("isReversible");
return false;
}
/**
* Return a std::string representing the reaction.
*
* @param i reaction index
*/
virtual std::string reactionString(int i) const {
err("reactionStd::String"); return "<null>";
}
/**
* Return the forward rate constants
*
* length is the number of reactions. units depends
* on many issues. @todo DGG: recommend changing name to
* getFwdRateCoefficients.
*
* @param kfwd Output vector containing the foward reaction rate constants.
* Length: m_ii.
*/
virtual void getFwdRateConstants(doublereal *kfwd) {
err("getFwdRateConstants");
}
/**
* Return the reverse rate constants.
*
* length is the number of reactions. units depends
* on many issues. Note, this routine will return rate constants
* for irreversible reactions if the default for
* doIrreversible is overridden. @todo DGG: recommend changing name to
* getRevRateCoefficients.
*
* @param krev Output vector of reverse rate constants.
* @param doIrreversible boolean indicating whether irreversible reactions
* should be included.
*/
virtual void getRevRateConstants(doublereal *krev,
bool doIrreversible = false) {
err("getFwdRateConstants");
}
/**
* Return the activation energies in Kelvin.
*
* length is the number of reactions
*
* @param E Ouptut vector of activation energies.
* Length: m_ii.
*/
virtual void getActivationEnergies(doublereal *E) {
err("getActivationEnergies");
}
//@}
/**
* @name Reaction Mechanism Construction
*/
//@{
/**
* Add a phase to the kinetics manager object. This must
* be done before the function init() is called or
* before any reactions are input.
* The following fields are updated:
* m_start -> vector of integers, containing the
* starting position of the species for
* each phase in the kinetics mechanism.
* m_surfphase -> index of the surface phase.
* m_thermo -> vector of pointers to ThermoPhase phases
* that participate in the kinetics
* mechanism.
* m_phaseindex -> map containing the std::string id of each
* ThermoPhase phase as a key and the
* index of the phase within the kinetics
* manager object as the value.
*
* @param thermo Reference to the ThermoPhase to be added.
*/
void addPhase(thermo_t& thermo);
/**
* Prepare the class for the addition of reactions. This
* method is called by function importKinetics after all
* phases have been added but before any reactions have
* been. The base class method does nothing, but derived
* classes may use this to perform any initialization
* (allocating arrays, etc.) that requires knowing the phases
* and species, but before any reactions are added.
*/
virtual void init() {}
/**
* Finish adding reactions and prepare for use. This method is
* called by function importKinetics after all reactions have
* been entered into the mechanism and before the mechanism is
* used to calculate reaction rates. The base class method
* does nothing, but derived classes may use this to perform
* any initialization (allocating arrays, etc.) that must be
* done after the reactions are entered.
*/
virtual void finalize() {}
/**
* Add a single reaction to the mechanism. This routine
* must be called after init() and before finalize().
*
* @param r Reference to the ReactionRate object for the reaction
* to be added.
*/
virtual void addReaction(const ReactionData& r) {
err("addReaction");
}
virtual const std::vector<grouplist_t>& reactantGroups(int i) {
//err("reactantGroups");
return m_dummygroups;
}
virtual const std::vector<grouplist_t>& productGroups(int i) {
//err("productGroups");
return m_dummygroups;
}
//@}
/**
* @name Altering Reaction Rates
*
* These methods alter reaction rates. They are designed
* primarily for carrying out sensitivity analysis, but may be
* used for any purpose requiring dynamic alteration of rate
* constants. For each reaction, a real-valued multiplier may
* be defined that multiplies the reaction rate
* coefficient. The multiplier may be set to zero to
* completely remove a reaction from the mechanism.
*/
//@{
/// The current value of the multiplier for reaction i.
/*!
* @param i index of the reaction
*/
doublereal multiplier(int i) const {return m_perturb[i];}
/// Set the multiplier for reaction i to f.
/*!
* @param i index of the reaction
* @param f value of the multiplier.
*/
void setMultiplier(int i, doublereal f) {m_perturb[i] = f;}
//@}
/**
* Increment the number of reactions in the mechanism by one.
* @todo Should be protected?
*/
void incrementRxnCount() { m_ii++; m_perturb.push_back(1.0); }
/**
* Returns true if the kinetics manager has been properly
* initialized and finalized.
*/
virtual bool ready() const {
return false;
}
/**
* Extract from array \c data the portion pertaining to phase \c phase.
*
* @param data data
* @param phase phase
* @param phase_data phase_data
*/
void selectPhase(const doublereal* data, const thermo_t* phase,
doublereal* phase_data);
/// For internal use. May be removed in a future release.
int index(){ return m_index; }
//! Set the index of the Kinetics Manager
/*!
* @param index input index
*/
void setIndex(int index) { m_index = index; }
protected:
//! Number of reactions in the mechanism
int m_ii;
/// Vector of perturbation factors for each reaction's rate of
/// progress vector. It is initialized to one.
///
vector_fp m_perturb;
/**
* This is a vector of vectors containing the reactants for
* each reaction. The outer vector is over the number of
* reactions, m_ii. The inner vector is a list of species
* indices. If the stoichiometric coefficient for a reactant
* is greater than one, then the reactant is listed
* contiguously in the vector a number of times equal to its
* stoichiometric coefficient.
* NOTE: These vectors will be wrong if there are real
* stoichiometric coefficients in the expression.
*/
std::vector<vector_int> m_reactants;
/**
* This is a vector of vectors containing the products for
* each reaction. The outer vector is over the number of
* reactions, m_ii. The inner vector is a list of species
* indeces. If the stoichiometric coefficient for a product is
* greater than one, then the reactant is listed contiguously
* in the vector a number of times equal to its stoichiometric
* coefficient.
* NOTE: These vectors will be wrong if there are real
* stoichiometric coefficients in the expression.
*/
std::vector<vector_int> m_products;
/**
* m_thermo is a vector of pointers to ThermoPhase
* objects. For homogeneous kinetics applications, this vector
* will only have one entry. For interfacial reactions, this
* vector will consist of multiple entries; some of them will
* be surface phases, and the other ones will be bulk phases.
* The order that the objects are listed determines the order
* in which the species comprising each phase are listed in
* the source term vector, originating from the reaction
* mechanism.
*/
std::vector<thermo_t*> m_thermo;
/**
* m_start is a vector of integers specifying the beginning position
* for the species vector for the n'th phase in the kinetics
* class.
*/
vector_int m_start;
/**
* Mapping of the phase id, i.e., the id attribute in the xml
* phase element to the position of the phase within the
* kinetics object. Positions start with the value of 1. The
* member function, phaseIndex() decrements by one before
* returning the index value, so that missing phases return
* -1.
*/
std::map<std::string, int> m_phaseindex;
//! Index of the Kinetics Manager
int m_index;
/**
* Index in the list of phases of the one surface phase.
*/
int m_surfphase;
/**
* Index in the list of phases of the one phase where the reactions
* occur.
*/
int m_rxnphase;
/// number of spatial dimensions of lowest-dimensional phase.
int m_mindim;
private:
//! Vector of group lists
std::vector<grouplist_t> m_dummygroups;
//! Function for unhandled situations
/*!
* @param m String error message
*/
void err(std::string m) const;
};
//! typedef for the kinetics base class
typedef Kinetics kinetics_t;
}
#endif

View file

@ -0,0 +1,152 @@
/**
* @file KineticsFactory.cpp
*/
/*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifdef WIN32
#pragma warning(disable:4786)
#endif
#include "KineticsFactory.h"
#include "GasKinetics.h"
#include "GRI_30_Kinetics.h"
#include "InterfaceKinetics.h"
#include "EdgeKinetics.h"
#include "importKinetics.h"
using namespace std;
namespace Cantera {
KineticsFactory* KineticsFactory::s_factory = 0;
static int ntypes = 5;
static string _types[] = {"none", "GasKinetics", "GRI30", "Interface", "Edge"};
static int _itypes[] = {0, cGasKinetics, cGRI30, cInterfaceKinetics, cEdgeKinetics};
/**
* Return a new kinetics manager that implements a reaction
* mechanism specified in a CTML file. In other words, the
* kinetics manager, given the rate constants and formulation of the
* reactions that make up a kinetics mechanism, is responsible for
* calculating the rates of progress of the reactions and for
* calculating the source terms for species.
*
* Input
* ------
* phaseData = This is an XML_Node that contains the xml data
* describing the phase. Of particular note to this
* routine is the child xml element called "kinetics".
* The element has one attribute called "model",
* with a string value. The value of this string
* is used to decide which kinetics manager is used
* to calculate the reacton mechanism.
*
* Return
* ---------
* Pointer to the new kinetics manager.
*/
Kinetics* KineticsFactory::
newKinetics(XML_Node& phaseData, vector<ThermoPhase*> th) {
/*
* Look for a child of the xml element phase called
* "kinetics". It has an attribute name "model".
* Store the value of that attribute in the variable kintype
*/
string kintype = phaseData.child("kinetics")["model"];
/*
* look up the string kintype in the list of known
* kinetics managers (list is kept at the top of this file).
* Translate it to an integer value, ikin.
*/
int ikin=-1;
int n;
for (n = 0; n < ntypes; n++) {
if (kintype == _types[n]) ikin = _itypes[n];
}
/*
* Assign the kinetics manager based on the value of ikin.
* Kinetics managers are classes derived from the base
* Kinetics class. Unknown kinetics managers will throw a
* CanteraError here.
*/
Kinetics* k=0;
switch (ikin) {
case 0:
k = new Kinetics;
break;
case cGasKinetics:
k = new GasKinetics;
break;
case cGRI30:
k = new GRI_30_Kinetics;
break;
case cInterfaceKinetics:
k = new InterfaceKinetics;
break;
case cEdgeKinetics:
k = new EdgeKinetics;
break;
default:
throw UnknownKineticsModel("KineticsFactory::newKinetics",
kintype);
}
// Now that we have the kinetics manager, we can
// import the reaction mechanism into it.
importKinetics(phaseData, th, k);
// Return the pointer to the kinetics manager
return k;
}
/**
* Return a new, empty kinetics manager.
*/
Kinetics* KineticsFactory::newKinetics(string model) {
int ikin = -1;
int n;
for (n = 0; n < ntypes; n++) {
if (model == _types[n]) ikin = _itypes[n];
}
Kinetics* k=0;
switch (ikin) {
case cGasKinetics:
k = new GasKinetics;
break;
case cGRI30:
k = new GRI_30_Kinetics;
break;
case cInterfaceKinetics:
k = new InterfaceKinetics;
break;
default:
throw UnknownKineticsModel("KineticsFactory::newKinetics",
model);
}
return k;
}
}

View file

@ -0,0 +1,91 @@
/**
* @file KineticsFactory.h
*/
/*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef KINETICS_FACTORY_H
#define KINETICS_FACTORY_H
#include "Kinetics.h"
#include "xml.h"
namespace Cantera {
class UnknownKineticsModel : public CanteraError {
public:
UnknownKineticsModel(std::string proc, std::string kineticsModel) :
CanteraError(proc, "Specified Kinetics model "
+ kineticsModel +
" does not match any known type.") {}
virtual ~UnknownKineticsModel() {}
};
/**
* Factory for kinetics managers.
*/
class KineticsFactory {
public:
static KineticsFactory* factory() {
if (!s_factory) s_factory = new KineticsFactory;
return s_factory;
}
virtual ~KineticsFactory() {
delete s_factory;
s_factory = 0;
}
/**
* Create a new kinetics manager.
*/
virtual Kinetics* newKinetics(XML_Node& phase,
std::vector<ThermoPhase*> th);
virtual Kinetics* newKinetics(std::string model);
private:
static KineticsFactory* s_factory;
KineticsFactory(){}
};
/**
* Create a new kinetics manager.
*/
inline Kinetics* newKineticsMgr(XML_Node& phase,
std::vector<ThermoPhase*> th, KineticsFactory* f=0) {
if (f == 0) {
f = KineticsFactory::factory();
}
Kinetics* kin = f->newKinetics(phase, th);
return kin;
}
/**
* Create a new kinetics manager.
*/
inline Kinetics* newKineticsMgr(std::string model, KineticsFactory* f=0) {
if (f == 0) {
f = KineticsFactory::factory();
}
Kinetics* kin = f->newKinetics(model);
return kin;
}
}
#endif

View file

@ -0,0 +1,164 @@
/**
* @file RateCoeffMgr.h
*/
/*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_RATECOEFF_MGR_H
#define CT_RATECOEFF_MGR_H
#include "utilities.h"
#include "RxnRates.h"
#include "ct_defs.h"
#include "ctexceptions.h"
namespace Cantera {
/**
* This rate coefficient manager supports one parameterization of
* the rate constant of any type.
*/
template<class R>
class Rate1 {
public:
Rate1(){}
virtual ~Rate1(){}
/**
* Install a rate coefficient calculator.
* @param rxnNumber the reaction number
* @param rateType the rate type
* @param m length of coefficient array
* @param coefficients
*/
int install( int rxnNumber, int rateType, int m,
const doublereal* c ) {
/*
* Check to see if the current reaction rate type
* is the same as the type of this class. If not,
* throw an error condition.
*/
if (rateType != R::type())
throw CanteraError("Rate1::install",
"incorrect rate coefficient type: "+int2str(rateType));
// if any coefficient other than the first is non-zero, or
// if alwaysComputeRate() is true, install a rate
// calculator and return the index of the calculator.
for (int i = 1; i < m; i++) {
if (c[i] != 0.0 || R::alwaysComputeRate() ) {
m_rxn.push_back(rxnNumber);
m_rates.push_back(R(m, c));
return static_cast<int>(m_rates.size()) - 1;
}
}
return -1;
}
/**
* Return a reference to the nth rate coefficient calculator.
* Note that this is not the same as the calculator for
* reaction n, since reactions with constant rate coefficients
* do not have a calculator.
*/
const R& rateCoeff(int loc) const { return m_rates[loc]; }
/**
* Update the concentration-dependent parts of the rate
* coefficient, if any. Used by class SurfaceArrhenius to
* compute coverage-dependent * modifications to the Arrhenius
* parameters. The array c should contain whatever data the
* particular rate coefficient class needs to update its
* rates. Note that this method does not return anything. To
* get the updated rates, method update must be called after
* the call to update_C.
*/
void update_C(const doublereal* c) {
TYPENAME_KEYWORD std::vector<R>::iterator b = m_rates.begin();
TYPENAME_KEYWORD std::vector<R>::iterator e = m_rates.end();
int i = 0;
for (; b != e; ++b, ++i) {
b->update_C(c);
}
}
/**
* Write the rate coefficients into array values. Each
* calculator writes one entry in values, at the location
* specified by the reaction number when it was
* installed. Note that nothing will be done for reactions
* that have constant rates. The array values should be
* preloaded with the constant rate coefficients.
*/
void update(doublereal T, doublereal logT, doublereal* values) {
TYPENAME_KEYWORD std::vector<R>::const_iterator b = m_rates.begin();
TYPENAME_KEYWORD std::vector<R>::const_iterator e = m_rates.end();
doublereal recipT = 1.0/T;
int i = 0;
for (; b != e; ++b, ++i) {
// values[m_rxn[i]] = exp(b->update(logT, recipT));
values[m_rxn[i]] = b->updateRC(logT, recipT);
}
}
void writeUpdate(std::ostream & output1, std::string key) {
output1 << key;
}
protected:
std::vector<R> m_rates;
std::vector<int> m_rxn;
array_fp m_const; // not used
};
/**
* This rate coefficient manager supports two parameterizations of
* any type.
*/
template<class R1, class R2>
class Rate2 {
public:
Rate2(){}
virtual ~Rate2(){}
int install( int rxnNumber, int rateType, int m,
const doublereal* c) {
if (rateType == R1::type())
return m_r1.install(rxnNumber, rateType, m, c);
else if (rateType == R2::type())
return m_r2.install(rxnNumber, rateType, m, c);
else
throw CanteraError("Rate2::install",
"unknown rate coefficient type");
return -1;
}
void update(doublereal T, doublereal logT,
doublereal* values) {
m_r1.update(T, logT, values);
m_r2.update(T, logT, values);
}
protected:
Rate1<R1> m_r1;
Rate1<R2> m_r2;
};
}
#endif

View file

@ -0,0 +1,61 @@
/**
* @file ReactionData.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_REACTION_DATA_H
#define CT_REACTION_DATA_H
#include "reaction_defs.h"
namespace Cantera {
class ReactionData {
public:
ReactionData() {
reactionType = ELEMENTARY_RXN;
number = 0;
rxn_number = 0;
reversible = true;
rateCoeffType = ARRHENIUS;
falloffType = NONE;
error = 0;
equation = "";
default_3b_eff = 1.0;
global = false;
beta = 0.0;
}
~ReactionData(){}
int reactionType;
int number, rxn_number;
vector_int reactants;
vector_int products;
vector_fp order;
vector_fp rstoich;
vector_fp pstoich;
std::vector<grouplist_t> rgroups;
std::vector<grouplist_t> pgroups;
std::map<int, doublereal> thirdBodyEfficiencies;
bool reversible;
int rateCoeffType;
vector_fp rateCoeffParameters;
vector_fp auxRateCoeffParameters;
int falloffType;
vector_fp falloffParameters;
int error;
std::string equation;
doublereal default_3b_eff;
vector_fp cov;
bool global;
doublereal beta; // for electrochemical reactions
};
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,278 @@
/**
* @file ReactionPath.h
*
* Classes for reaction path analysis.
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_RXNPATH_H
#define CT_RXNPATH_H
// Cantera includes
#include "ct_defs.h"
#include "DenseMatrix.h"
#include "Group.h"
#include "Kinetics.h"
namespace Cantera {
enum flow_t { NetFlow, OneWayFlow };
Group parseGroupString(std::string str, std::vector<std::string>& esyms);
// forward references
class Path;
/**
* Nodes in reaction path graphs.
*/
class SpeciesNode {
public:
typedef std::vector<Path*> path_list;
/// Default constructor
SpeciesNode() : number(-1), name(""), value(0.0),
visible(false), m_in(0.0), m_out(0.0) {}
/// Destructor
virtual ~SpeciesNode() {}
// public attributes
int number; ///< Species number
std::string name; ///< Label on graph
doublereal value; ///< May be used to set node appearance
bool visible; ///< Visible on graph;
// public methods
/**
* @name References.
* Return a reference to a path object connecting this node
* to another node.
*/
//@{
Path* path(int n) { return m_paths[n]; }
const Path* path(int n) const { return m_paths[n]; }
//@}
/// Total number of paths to or from this node
int nPaths() const { return static_cast<int>(m_paths.size()); }
/// add a path to or from this node
void addPath(Path* path);
double outflow() {return m_out;}
double inflow() {return m_in;}
double netOutflow() {return m_out - m_in;}
void printPaths();
protected:
double m_in, m_out;
path_list m_paths;
};
class Path {
public:
typedef std::map<int, doublereal> rxn_path_map;
/**
* Constructor. Construct a one-way path from
* \c begin to \c end.
*/
Path(SpeciesNode* begin, SpeciesNode* end);
/// Destructor
virtual ~Path() {}
void addReaction(int rxnNumber, doublereal value, std::string label = "");
/// Upstream node.
const SpeciesNode* begin() const { return m_a; }
SpeciesNode* begin() { return m_a; }
/// Downstream node.
const SpeciesNode* end() const { return m_b; }
SpeciesNode* end() { return m_b; }
/**
* If \c n is one of the nodes this path connects, then
* the other node is returned. Otherwise zero is returned.
*/
SpeciesNode* otherNode(SpeciesNode* n) {
return (n == m_a ? m_b : (n == m_b ? m_a : 0));
}
/// The total flow in this path
doublereal flow() { return m_total; }
void setFlow(doublereal v) { m_total = v; }
/// Number of reactions contributing to this path
int nReactions() {
return static_cast<int>(m_rxn.size());
}
/// Map from reaction number to flow from that reaction in this path.
const rxn_path_map& reactionMap() { return m_rxn; }
void writeLabel(std::ostream& s, doublereal threshold = 0.005);
protected:
std::map<std::string, doublereal> m_label;
SpeciesNode *m_a, *m_b;
rxn_path_map m_rxn;
doublereal m_total;
};
/**
* Reaction path diagrams (graphs).
*/
class ReactionPathDiagram {
public:
ReactionPathDiagram();
virtual ~ReactionPathDiagram();
/// The largest one-way flow value in any path
doublereal maxFlow() { return m_flxmax; }
/// The net flow from node \c k1 to node \c k2
doublereal netFlow(int k1, int k2) {
return flow(k1, k2) - flow(k2, k1);
}
/// The one-way flow from node \c k1 to node \c k2
doublereal flow(int k1, int k2) {
return (m_paths[k1][k2] ? m_paths[k1][k2]->flow() : 0.0);
}
/// True if a node for species k exists
bool hasNode(int k) {
return (m_nodes[k] != 0);
}
void writeData(std::ostream& s);
void exportToDot(std::ostream& s);
void add(ReactionPathDiagram& d);
SpeciesNode* node(int k) { return m_nodes[k]; }
Path* path(int k1, int k2) { return m_paths[k1][k2]; }
Path* path(int n) { return m_pathlist[n]; }
int nPaths() { return static_cast<int>(m_pathlist.size()); }
int nNodes() { return static_cast<int>(m_nodes.size()); }
void addNode(int k, std::string nm, doublereal x = 0.0);
void displayOnly(int k=-1) { m_local = k; }
void linkNodes(int k1, int k2, int rxn, doublereal value,
std::string legend = "");
void include(std::string aaname) { m_include.push_back(aaname); }
void exclude(std::string aaname) { m_exclude.push_back(aaname); }
void include(std::vector<std::string>& names) {
int n = static_cast<int>(names.size());
for (int i = 0; i < n; i++) m_include.push_back(names[i]);
}
void exclude(std::vector<std::string>& names) {
int n = static_cast<int>(names.size());
for (int i = 0; i < n; i++) m_exclude.push_back(names[i]);
}
std::vector<std::string>& included() { return m_include; }
std::vector<std::string>& excluded() { return m_exclude; }
vector_int species();
vector_int reactions();
void findMajorPaths(doublereal threshold, int lda, doublereal* a);
void setFont(std::string font) {
m_font = font;
}
// public attributes
std::string title;
std::string bold_color;
std::string normal_color;
std::string dashed_color;
std::string element;
std::string m_font;
doublereal threshold,
bold_min, dashed_max, label_min;
doublereal x_size, y_size;
std::string name, dot_options;
flow_t flow_type;
double scale;
double arrow_width;
bool show_details;
double arrow_hue;
protected:
doublereal m_flxmax;
std::map<int, std::map<int, Path*> > m_paths;
std::map<int, SpeciesNode*> m_nodes;
std::vector<Path*> m_pathlist;
std::vector<std::string> m_include;
std::vector<std::string> m_exclude;
vector_int m_speciesNumber;
std::map<int, int> m_rxns;
int m_local;
};
class ReactionPathBuilder {
public:
ReactionPathBuilder() {}
virtual ~ReactionPathBuilder() {}
int init(std::ostream& logfile, Kinetics& s);
int build(Kinetics& s, std::string element, std::ostream& output,
ReactionPathDiagram& r, bool quiet=false);
int findGroups(std::ostream& logfile, Kinetics& s);
void writeGroup(std::ostream& out, const Group& g);
protected:
void findElements(Kinetics& kin);
int m_nr;
int m_ns;
int m_nel;
vector_fp m_ropf;
vector_fp m_ropr;
array_fp m_x;
std::vector<vector_int> m_reac;
std::vector<vector_int> m_prod;
DenseMatrix m_elatoms;
std::vector<std::vector<int> > m_groups;
std::vector<Group> m_sgroup;
std::vector<std::string> m_elementSymbols;
// std::map<int, int> m_warn;
std::map<int, std::map<int, std::map<int, Group> > > m_transfer;
std::vector<bool> m_determinate;
Array2D m_atoms;
std::map<std::string,int> m_enamemap;
};
}
#endif

View file

@ -0,0 +1,241 @@
/**
* @file ReactionStoichMgr.h
*
* Header file declaring class ReactionStoichMgr.
*/
/*
* $Author$
* $Revision$
* $Date$
*/
#ifndef CT_RXN_STOICH
#define CT_RXN_STOICH
#include "ct_defs.h"
namespace Cantera {
class StoichManagerN;
class ReactionData;
/**
* Reaction mechanism stoichiometry manager. This is an internal class used
* by kinetics manager classes, and is not meant for direct use in
* user programs.
*
* Class ReactionStoichMgr handles the calculation of quantities involving
* the stoichiometry of a set of reactions. The reactions must have integer
* stoichiometric coefficients. Specifically, its methods compute
* - species creation rates
* - species destruction rates
* - species net production rates
* - the change in molar species properties in the reactions
* - concentration products
*
* To use this class, method 'add' is first used to add each reaction.
* Once all reactions have been added, the methods that compute various
* quantities may be called.
*
* The nomenclature used below to document the methods is as follows.
*
* - \f$ N_r \f$
* Integer reactant stoichiometric coefficient matrix. The (k,i)
* element of this matrix is the stoichiometric coefficient of
* species \i k as a reactant in reaction \i i.
* - \f$ N_p \f$
* Integer product stoichiometric coefficient matrix. The (k,i)
* element of this matrix is the stoichiometric coefficient of
* species \i k as a product in reaction \i i.
* - \f$ Q_{\rm fwd} \f$
* Vector of length I of forward rates of progress.
* - \f$ Q_{\rm rev} \f$
* Vector of length I of reverse rates of progress.
* - \f$ C \f$
* Vector of K species creation rates.
* - \f$ D \f$
* Vector of K species destruction rates.
* - \f$ W = C - D \f$
* Vector of K species net production rates.
*
*/
class ReactionStoichMgr {
public:
/// Constructor.
ReactionStoichMgr();
/// Destructor.
virtual ~ReactionStoichMgr();
/**
* Add a reaction with mass-action kinetics. Vectors
* 'reactants' and 'products' contain the integer species
* indices of the reactants and products, respectively. Note
* that if more than one molecule of a given species is
* involved in the reaction, then its index is repeated.
*
* For example, suppose a reaction mechanism involves the
* species N2, O2, O, N, NO. N2 is assigned index number 0, O2
* number 1, and so on through NO with number 4. Then the
* representation of the following reactions is as shown here.
*
* - N + O = NO
* - reactants: (3, 2)
* - products: (4)
*
* - O + O = O2
* - reactants: (2, 2) [ note repeated index ]
* - products: (1)
*
* @param rxn Reaction number. This number will be used as the index
* into the rate of progess vector in the methods below.
* @param reactants vector of integer reactant indices
* @param products vector of integer product indices
* @param reversible true if the reaction is reversible, false otherwise
*/
virtual void add(int rxn, const vector_int& reactants, const vector_int& products,
bool reversible);
/**
* Add a reaction with specified, possibly non-integral, reaction orders.
* @param rxn Reaction number
* @param reactants vector of integer reactant indices
* @param products vector of integer product indices
* @param reversible true if the reaction is reversible, false otherwise.
* If the reaction is reversible, its reverse rate will be computed from
* the reaction stoichiometry.
* @param fwdOrder reaction orders for the reactants. This vector must
* be the same length as 'reactants,' and the reaction orders are for the
* species with index in the corresponding location in 'reactants.'
*
*/
// void add(int rxn, const vector_int& reactants, const vector_int& products,
// bool reversible, const vector_fp& fwdOrder);
virtual void add(int rxn, const ReactionData& r);
/**
* Species creation rates.
* Given the arrays of the forward and reverse rates of
* progress for all reactions, compute the species creation
* rates, given by
* \f[
* C = N_p Q_f + N_r Q_r.
* \f]
*/
virtual void getCreationRates(int nSpecies,
const doublereal* fwdRatesOfProgress,
const doublereal* revRatesOfProgress,
doublereal* creationRates);
/**
* Species destruction rates.
* Given the arrays of the forward and reverse rates of
* progress for all reactions, compute the species destruction
* rates, given by
* \f[
* D = N_r Q_f + N_p Q_r,
* \f]
* Note that the stoichiometric coefficient matrices are very sparse, integer
* matrices.
*/
virtual void getDestructionRates(int nSpecies,
const doublereal* fwdRatesOfProgress,
const doublereal* revRatesOfProgress,
doublereal* destructionRates);
/**
* Given the array of the net rates of progress for all
* reactions, compute the species net production rates and
* return them in array w.
*/
/**
* Species net production rates.
* Given the array of the net rates of
* progress for all reactions, compute the species net production
* rates, given by
* \f[
* W = (N_r - N_p) Q_{\rm net},
* \f]
*/
virtual void getNetProductionRates(int nsp, const doublereal* ropnet, doublereal* w);
/**
* Change of a molar species property in a reaction. Given an
* array of species properties 'g', return in array 'dg' the
* change in this quantity in the reactions. Array 'g' must
* have a length at least as great as the number of species,
* and array 'dg' must have a length as great as the total
* number of reactions.
*/
virtual void getReactionDelta(int nReactions,
const doublereal* g,
doublereal* dg);
/**
* Given an array of species properties 'g', return in array
* 'dg' the change in this quantity in the reversible
* reactions. Array 'g' must have a length at least as great
* as the number of species, and array 'dg' must have a length
* as great as the total number of reactions. This method
* only computes 'dg' for the reversible reactions, and the
* entries of 'dg' for the irreversible reactions are
* unaltered. This is primarily designed for use in
* calculating reveerse rate coefficients from thermochemistry
* for reversible reactions.
*/
virtual void getRevReactionDelta(int nr, const doublereal* g, doublereal* dg);
/**
* Given an array of concentrations C, multiply the entries in array R by
* the concentration products for the reactants:
* \f[
* R_i = R_i * \prod_k C_k^{o_{k,i}}
* \f]
* Here \f$ o_{k,i} \f$ is the reaction order of species k in reaction i.
*/
virtual void multiplyReactants(const doublereal* C, doublereal* R);
/**
* Given an array of concentrations C, multiply the entries in array R by
* the concentration products for the products:
* \f[
* R_i = R_i * \prod_k C_k^{\nu^{(p)}_{k,i}}
* \f]
* Here \f$ \nu^{(p)}_{k,i} \f$ is the product stoichiometric coefficient
* of species k in reaction i.
*/
virtual void multiplyRevProducts(const doublereal* c, doublereal* r);
virtual void write(std::string filename);
protected:
void writeCreationRates(std::ostream& f);
void writeDestructionRates(std::ostream& f);
void writeNetProductionRates(std::ostream& f);
void writeMultiplyReactants(std::ostream& f);
void writeMultiplyRevProducts(std::ostream& f);
StoichManagerN* m_reactants;
StoichManagerN* m_revproducts;
StoichManagerN* m_irrevproducts;
vector_fp m_dummy;
#ifdef INCL_STOICH_WRITER
StoichWriter* m_rwriter;
#endif
};
}
#endif

372
Cantera/src/kinetics/RxnRates.h Executable file
View file

@ -0,0 +1,372 @@
/**
* @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 {
/**
* A rate coefficient of the form
* \f[
* A T^b \exp (-E/RT)
* \f]
*/
class Arrhenius {
public:
/// return the rate coefficient type.
static int type(){ return ARRHENIUS; }
/// 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; }
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<Arrhenius> m_terms;
vector_int m_sign;
int m_nterms;
};
/**
* An Arrhenius rate with coverage-dependent terms.
*/
class SurfaceArrhenius {
public:
static int type(){ return ARRHENIUS; }
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 {
double 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
}
// 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

View file

@ -0,0 +1,824 @@
/**
* @file StoichManager.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_STOICH_MGR_H
#define CT_STOICH_MGR_H
#include "stringUtils.h"
namespace Cantera {
/**
* @defgroup Stoichiometry Stoichiometry
*
* Note: these classes are designed for internal use in class
* ReactionStoichManager.
*
* The classes defined here implement simple operations that are
* used by class ReactionStoichManager to compute things like
* rates of progress, species production rates, etc. In general, a
* reaction mechanism may involve many species and many reactions,
* but any given reaction typically only involves a few species as
* reactants, and a few as products. Therefore, the matrix of
* stoichiometric coefficients is very sparse. Not only is it
* sparse, but the non-zero matrix elements often have the value
* 1, and in many cases no more than three coefficients are
* non-zero for the reactants and/or the products.
*
* For the present purposes, we will consider each direction of a
* reversible reaction to be a separate reaction. We often need to
* compute quantities that can formally be written as a matrix
* product of a stoichiometric coefficient matrix and a vector of
* reaction rates. For example, the species creation rates are
* given by
* \f[
* \dot C_k = \sum_k \nu^{(p)}_{k,i} R_i
* \f]
* where \f$ \nu^{(p)_{k,i}} \f$ is the product-side stoichiometric
* coefficient of species \a k in reaction \a i.
* This could be done be straightforward matrix multiplication, but would be inefficient, since most of the matrix elements of \f$ \nu^{(p)}_{k,i} \f$ are zero. We could do better by using sparse-matrix algorithms to compute this product.
If the reactions are general ones, with non-integral stoichiometric
coefficients, this is about as good as we can do. But we are
particularly concerned here with the performance for very large
reaction mechanisms, which are usually composed of elementary
reactions, which have integral stoichiometric
coefficients. Furthermore, very few elementary reactions involve more
than 3 product or reactant molecules. This means that instead of
But we can do even better if we take account of the special structure
of this matrix for elementary reactions.
involve three or fewer product molecules (or reactant molecules).
* To take advantage of this structure, reactions are divided int
These classes are
* designed to take advantage of this sparse structure when
* computing quantities that can be written as matrix multiplies
They are designed to explicitly unroll loops over species or reactions for
* Operations on reactions that require knowing the reaction
* stoichiometry.
* This module consists of class StoichManager, and
* classes C1, C2, and C3. Classes C1, C2, and C3 handle operations
* involving one, two, or three species, respectively, in a
* reaction. Instances are instantiated with a reaction number, and n
* species numbers (n = 1 for C1, etc.). All three classes have the
* same interface.
*
* These classes are designed for use by StoichManager, and the
* operations implemented are those needed to efficiently compute
* quantities such as rates of progress, species production rates,
* reaction thermochemistry, etc. The compiler will inline these
* methods into the body of the corresponding StoichManager method,
* and so there is no performance penalty (unless inlining is turned
* off).
*
* To describe the methods, consider class C3 and suppose an instance
* is created with reaction number irxn and species numbers k0, k1,
* and k2.
*
* - multiply(in, out) : out[irxn] is multiplied by
* in[k0] * in[k1] * in[k2]
*
* - power(in, out) : out[irxn] is multiplied by
* (in[k0]^order0) * (in[k1]^order1) * (in[k2]^order2)
*
* - incrementReaction(in, out) : out[irxn] is incremented by
* in[k0] + in[k1] + in[k2]
*
* - decrementReaction(in, out) : out[irxn] is decremented by
* in[k0] + in[k1] + in[k2]
*
* - incrementSpecies(in, out) : out[k0], out[k1], and out[k2]
* are all incremented by in[irxn]
*
* - decrementSpecies(in, out) : out[k0], out[k1], and out[k2]
* are all decremented by in[irxn]
*
* The function multiply() is usually used when evaluating the
* forward and reverse rates of progress of reactions.
* The rate constants are usually loaded into out[]. Then
* multply() is called to add in the dependence of the
* species concentrations to yield a forward and reverse rop.
*
* The function incrementSpecies() and its cousin decrementSpecies()
* is used to translate from rates of progress to species production
* rates. The vector in[] is preloaed with the rates of progess of
* all reactions. Then incrementSpecies() is called to
* increment the species production vector, out[], with the rates
* of progress.
*
* The functions incrementReaction() and decrementReaction() are
* used to find the standard state equilibrium constant for
* a reaction. Here, output[] is a vector of length
* number of reactions, usually the standard gibbs free energies
* of reaction, while input, usually the standard state
* gibbs free energies of species, is a vector of length number of
* species.
*
* Note the stoichiometric coefficient for a species in a reaction
* is handled by always assuming it is equal to one and then
* treating reactants and products for a reaction separately.
* Bimolecular reactions involving the identical species are
* treated as involving separate species.
*
* @internal This class should be upgraded to include cases where
* real stoichiometric coefficients are used. Shouldn't be that
* hard to do, and they occur in engineering simulations with some
* regularity.
*
*/
static doublereal ppow(doublereal x, doublereal order) {
if (x > 0.0)
return std::pow(x, order);
else
return 0.0;
}
inline static std::string fmt(std::string r, int n) { return r + "[" + int2str(n) + "]"; }
/**
* Handles one species in a reaction.
* @ingroup Stoichiometry
* @internal
*/
class C1 {
public:
C1( int rxn = 0, int ic0 = 0)
: m_rxn (rxn), m_ic0 (ic0) {}
int data(std::vector<int>& ic) {
ic.resize(1);
ic[0] = m_ic0;
return m_rxn;
}
void incrementSpecies(const doublereal* R, doublereal* S) const {
S[m_ic0] += R[m_rxn];
}
void decrementSpecies(const doublereal* R, doublereal* S) const {
S[m_ic0] -= R[m_rxn];
}
void multiply(const doublereal* S, doublereal* R) const {
R[m_rxn] *= S[m_ic0];
}
void incrementReaction(const doublereal* S, doublereal* R) const {
R[m_rxn] += S[m_ic0];
}
void decrementReaction(const doublereal* S, doublereal* R) const {
R[m_rxn] -= S[m_ic0];
}
int rxnNumber() const { return m_rxn; }
int speciesIndex(int n) const { return m_ic0; }
int nSpecies() { return 1;}
void writeMultiply(std::string r, std::map<int, std::string>& out) {
out[m_rxn] = fmt(r, m_ic0);
}
void writeIncrementReaction(std::string r, std::map<int, std::string>& out) {
out[m_rxn] += " + "+fmt(r, m_ic0);
}
void writeDecrementReaction(std::string r, std::map<int, std::string>& out) {
out[m_rxn] += " - "+fmt(r, m_ic0);
}
void writeIncrementSpecies(std::string r, std::map<int, std::string>& out) {
out[m_ic0] += " + "+fmt(r, m_rxn);
}
void writeDecrementSpecies(std::string r, std::map<int, std::string>& out) {
out[m_ic0] += " - "+fmt(r, m_rxn);
}
private:
int m_rxn, m_ic0;
};
/**
* Handles two species in a single reaction.
* @ingroup Stoichiometry
*/
class C2 {
public:
C2( int rxn = 0, int ic0 = 0, int ic1 = 0)
: m_rxn (rxn), m_ic0 (ic0), m_ic1 (ic1) {}
int data(std::vector<int>& ic) {
ic.resize(2);
ic[0] = m_ic0;
ic[1] = m_ic1;
return m_rxn;
}
void incrementSpecies(const doublereal* R, doublereal* S) const {
S[m_ic0] += R[m_rxn];
S[m_ic1] += R[m_rxn];
}
void decrementSpecies(const doublereal* R, doublereal* S) const {
S[m_ic0] -= R[m_rxn];
S[m_ic1] -= R[m_rxn];
}
void multiply(const doublereal* S, doublereal* R) const {
R[m_rxn] *= S[m_ic0] * S[m_ic1];
}
void incrementReaction(const doublereal* S, doublereal* R) const {
R[m_rxn] += S[m_ic0] + S[m_ic1];
}
void decrementReaction(const doublereal* S, doublereal* R) const {
R[m_rxn] -= (S[m_ic0] + S[m_ic1]);
}
int rxnNumber() const { return m_rxn; }
int speciesIndex(int n) const { return (n == 0 ? m_ic0 : m_ic1); }
int nSpecies() { return 2;}
void writeMultiply(std::string r, std::map<int, std::string>& out) {
out[m_rxn] = fmt(r, m_ic0) + " * " + fmt(r, m_ic1);
}
void writeIncrementReaction(std::string r, std::map<int, std::string>& out) {
out[m_rxn] += " + "+fmt(r, m_ic0)+" + "+fmt(r, m_ic1);
}
void writeDecrementReaction(std::string r, std::map<int, std::string>& out) {
out[m_rxn] += " - "+fmt(r, m_ic0)+" - "+fmt(r, m_ic1);
}
void writeIncrementSpecies(std::string r, std::map<int, std::string>& out) {
std::string s = " + "+fmt(r, m_rxn);
out[m_ic0] += s;
out[m_ic1] += s;
}
void writeDecrementSpecies(std::string r, std::map<int, std::string>& out) {
std::string s = " - "+fmt(r, m_rxn);
out[m_ic0] += s;
out[m_ic1] += s;
}
private:
/**
* Reaction index -> index into the ROP vector
*/
int m_rxn;
/**
* Species indecise -> index into the species vector for the
* two species.
*/
int m_ic0, m_ic1;
};
/**
* Handles three species in a reaction.
* @ingroup Stoichiometry
*/
class C3 {
public:
C3( int rxn = 0, int ic0 = 0, int ic1 = 0, int ic2 = 0)
: m_rxn (rxn), m_ic0 (ic0), m_ic1 (ic1), m_ic2 (ic2) {}
int data(std::vector<int>& ic) {
ic.resize(3);
ic[0] = m_ic0;
ic[1] = m_ic1;
ic[2] = m_ic2;
return m_rxn;
}
void incrementSpecies(const doublereal* R, doublereal* S) const {
S[m_ic0] += R[m_rxn];
S[m_ic1] += R[m_rxn];
S[m_ic2] += R[m_rxn];
}
void decrementSpecies(const doublereal* R, doublereal* S) const {
S[m_ic0] -= R[m_rxn];
S[m_ic1] -= R[m_rxn];
S[m_ic2] -= R[m_rxn];
}
void multiply(const doublereal* S, doublereal* R) const {
R[m_rxn] *= S[m_ic0] * S[m_ic1] * S[m_ic2];
}
void incrementReaction(const doublereal* S, doublereal* R) const {
R[m_rxn] += S[m_ic0] + S[m_ic1] + S[m_ic2];
}
void decrementReaction(const doublereal* S, doublereal* R) const {
R[m_rxn] -= (S[m_ic0] + S[m_ic1] + S[m_ic2]);
}
int rxnNumber() const { return m_rxn; }
int speciesIndex(int n) const { return (n == 0 ? m_ic0 : (n == 1 ? m_ic1 : m_ic2)); }
int nSpecies() { return 3;}
void writeMultiply(std::string r, std::map<int, std::string>& out) {
out[m_rxn] = fmt(r, m_ic0) + " * " + fmt(r, m_ic1) + " * " + fmt(r, m_ic2);
}
void writeIncrementReaction(std::string r, std::map<int, std::string>& out) {
out[m_rxn] += " + "+fmt(r, m_ic0)+" + "+fmt(r, m_ic1)+" + "+fmt(r, m_ic2);
}
void writeDecrementReaction(std::string r, std::map<int, std::string>& out) {
out[m_rxn] += " - "+fmt(r, m_ic0)+" - "+fmt(r, m_ic1)+" - "+fmt(r, m_ic2);
}
void writeIncrementSpecies(std::string r, std::map<int, std::string>& out) {
std::string s = " + "+fmt(r, m_rxn);
out[m_ic0] += s;
out[m_ic1] += s;
out[m_ic2] += s;
}
void writeDecrementSpecies(std::string r, std::map<int, std::string>& out) {
std::string s = " - "+fmt(r, m_rxn);
out[m_ic0] += s;
out[m_ic1] += s;
out[m_ic2] += s;
}
private:
int m_rxn, m_ic0, m_ic1, m_ic2;
};
/**
* Handles any number of species in a reaction, including fractional
* stoichiometric coefficients, and arbitrary reaction orders.
* @ingroup Stoichiometry
*/
class C_AnyN {
public:
C_AnyN() : m_rxn (-1) {}
C_AnyN( int rxn, const vector_int& ic, const vector_fp& order,
const vector_fp& stoich)
: m_rxn (rxn) {
m_n = ic.size();
m_ic.resize(m_n);
m_order.resize(m_n);
m_stoich.resize(m_n);
for (int n = 0; n < m_n; n++) {
m_ic[n] = ic[n];
m_order[n] = order[n];
m_stoich[n] = stoich[n];
}
}
int data(std::vector<int>& ic) {
ic.resize(m_n);
int n;
for (n = 0; n < m_n; n++) ic[n] = m_ic[n];
return m_rxn;
}
doublereal order(int n) const {return m_order[n];}
doublereal stoich(int n) const {return m_stoich[n];}
int speciesIndex(int n) const {return m_ic[n];}
void multiply(const doublereal* input, doublereal* output) const {
for (int n = 0; n < m_n; n++) {
output[m_rxn] *=
ppow(input[m_ic[n]],m_order[n]);
}
}
void incrementSpecies(const doublereal* input,
doublereal* output) const {
doublereal x = input[m_rxn];
for (int n = 0; n < m_n; n++) output[m_ic[n]] += m_stoich[n]*x;
}
void decrementSpecies(const doublereal* input,
doublereal* output) const {
doublereal x = input[m_rxn];
for (int n = 0; n < m_n; n++) output[m_ic[n]] -= m_stoich[n]*x;
}
void incrementReaction(const doublereal* input,
doublereal* output) const {
for (int n = 0; n < m_n; n++) output[m_rxn]
+= m_stoich[n]*input[m_ic[n]];
}
void decrementReaction(const doublereal* input,
doublereal* output) const {
for (int n = 0; n < m_n; n++) output[m_rxn]
-= m_stoich[n]*input[m_ic[n]];
}
void writeMultiply(std::string r, std::map<int, std::string>& out) {
int n;
out[m_rxn] = "";
for (n = 0; n < m_n; n++) {
if (m_order[n] == 1.0)
out[m_rxn] += fmt(r, m_ic[n]);
else
out[m_rxn] += "pow("+fmt(r, m_ic[n])+","+fp2str(m_order[n])+")";
if (n < m_n-1)
out[m_rxn] += " * ";
}
}
void writeIncrementReaction(std::string r, std::map<int, std::string>& out) {
int n;
for (n = 0; n < m_n; n++) {
out[m_rxn] += " + "+fp2str(m_stoich[n]) + "*" + fmt(r, m_ic[n]);
}
}
void writeDecrementReaction(std::string r, std::map<int, std::string>& out) {
int n;
for (n = 0; n < m_n; n++) {
out[m_rxn] += " - "+fp2str(m_stoich[n]) + "*" + fmt(r, m_ic[n]);
}
}
void writeIncrementSpecies(std::string r, std::map<int, std::string>& out) {
std::string s = fmt(r, m_rxn);
int n;
for (n = 0; n < m_n; n++) {
out[m_ic[n]] += " + "+fp2str(m_stoich[n]) + "*" + s;
}
}
void writeDecrementSpecies(std::string r, std::map<int, std::string>& out) {
std::string s = fmt(r, m_rxn);
int n;
for (n = 0; n < m_n; n++) {
out[m_ic[n]] += " - "+fp2str(m_stoich[n]) + "*" + s;
}
}
private:
int m_n, m_rxn;
vector_int m_ic;
vector_fp m_order;
vector_fp m_stoich;
};
template<class InputIter, class Vec1, class Vec2>
inline static void _multiply(InputIter begin, InputIter end,
const Vec1& input, Vec2& output) {
for (; begin != end; ++begin)
begin->multiply(input, output);
}
template<class InputIter, class Vec1, class Vec2>
inline static void _incrementSpecies(InputIter begin,
InputIter end, const Vec1& input, Vec2& output) {
for (; begin != end; ++begin)
begin->incrementSpecies(input, output);
}
template<class InputIter, class Vec1, class Vec2>
inline static void _decrementSpecies(InputIter begin,
InputIter end, const Vec1& input, Vec2& output) {
for (; begin != end; ++begin)
begin->decrementSpecies(input, output);
}
template<class InputIter, class Vec1, class Vec2>
inline static void _incrementReactions(InputIter begin,
InputIter end, const Vec1& input, Vec2& output) {
for (; begin != end; ++begin)
begin->incrementReaction(input, output);
}
template<class InputIter, class Vec1, class Vec2>
inline static void _decrementReactions(InputIter begin,
InputIter end, const Vec1& input, Vec2& output) {
for (; begin != end; ++begin)
begin->decrementReaction(input, output);
}
template<class InputIter>
inline static void _writeIncrementSpecies(InputIter begin, InputIter end, std::string r,
std::map<int, std::string>& out) {
for (; begin != end; ++begin) begin->writeIncrementSpecies(r, out);
}
template<class InputIter>
inline static void _writeDecrementSpecies(InputIter begin, InputIter end, std::string r,
std::map<int, std::string>& out) {
for (; begin != end; ++begin) begin->writeDecrementSpecies(r, out);
}
template<class InputIter>
inline static void _writeIncrementReaction(InputIter begin, InputIter end, std::string r,
std::map<int, std::string>& out) {
for (; begin != end; ++begin) begin->writeIncrementReaction(r, out);
}
template<class InputIter>
inline static void _writeDecrementReaction(InputIter begin, InputIter end, std::string r,
std::map<int, std::string>& out) {
for (; begin != end; ++begin) begin->writeDecrementReaction(r, out);
}
template<class InputIter>
inline static void _writeMultiply(InputIter begin, InputIter end, std::string r,
std::map<int, std::string>& out) {
for (; begin != end; ++begin) begin->writeMultiply(r, out);
}
/*
* This class handles operations involving the stoichiometric
* coefficients on one side of a reaction (reactant or product) for
* a set of reactions comprising a reaction mechanism. This class is
* used by class ReactionStoichMgr, which contains three instances
* of this class (one to handle operations on the reactions, one for
* the products of reversible reactions, and one for the products of
* irreversible reactions).
*
* This class is designed for use with elementary reactions, or at
* least ones with integral stoichiometric coefficients. Let \f$ M(i) \f$
* be the number of molecules on the product or reactant side of
* reaction number i.
* \f[
* r_i = \sum_m^{M_i} s_{k_{m,i}}
* \f]
* To understand the operations performed by this class, let
* \f$ N_{k,i}\f$ denote the stoichiometric coefficient of species k on
* one side (reactant or product) in reaction i. Then \b N is a sparse
* K by I matrix of stoichiometric coefficients.
*
* The following matrix operations may be carried out with a vector
* S of length K, and a vector R of length I:
*
* - \f$ S = S + N R\f$ (incrementSpecies)
* - \f$ S = S - N R\f$ (decrementSpecies)
* - \f$ R = R + N^T S \f$ (incrementReaction)
* - \f$ R = R - N^T S \f$ (deccrementReaction)
*
* The actual implementation, however, does not compute these
* quantities by matrix multiplication. A faster algorithm is used
* that makes use of the fact that the \b integer-valued N matrix is
* very sparse, and the non-zero terms are small positive integers.
* \f[
* S_k = R_{i1} + \dots + R_{iM}
* \f]
* where M is the number of molecules, and $\f i(m) \f$ is the
* @ingroup Stoichiometry
*/
class StoichManagerN {
public:
/**
* Constructor for the StoichManagerN class.
*
* @internal Consider adding defaulted entries here that supply
* the total number of reactions in the mechanism and the total
* number of species in the species list. Then, we could use those
* numbers to provide error checks during the construction of the
* object. Those numbers would also provide some clarity to the
* purpose and utility of this class.
*
* DGG - the problem is that the number of reactions and species
* are not known initially.
*/
StoichManagerN() {}
/**
* Add a single reaction to the list of reactions that this
* stoichiometric manager object handles.
*
* This function is the same as the add() function below. However,
* the order of each species in the power list expression is
* set to one automatically.
*/
void add(int rxn, const vector_int& k) {
vector_fp order(k.size(), 1.0);
vector_fp stoich(k.size(), 1.0);
add(rxn, k, order, stoich);
}
void add(int rxn, const vector_int& k, const vector_fp& order) {
vector_fp stoich(k.size(), 1.0);
add(rxn, k, order, stoich);
}
/**
* Add a single reaction to the list of reactions that this
* stoichiometric manager object handles.
*
* @param rxn Reaction index of the current reaction. This is used
* as an index into vectors which have length n_total_rxn.
* @param k This is a vector of integer values specifying the
* species indecises. The length of this vector species
* the number of different species in the description.
* The value of the entries are the species indices.
* These are used as indexes into vectors which have
* length n_total_species.
* @param order This is a vector of the same length as vector k.
* The order is used for the routine power(), which produces
* a power law expression involving the species vector.
* @param stoich This is used to handle fractional stoichiometric coefficients
* on the product side of irreversible reactions.
*/
void add(int rxn, const vector_int& k, const vector_fp& order,
const vector_fp& stoich) {
m_n[rxn] = static_cast<int>(k.size());
int ns = stoich.size();
int n;
bool frac = false;
for (n = 0; n < ns; n++) {
if (stoich[n] != 1.0) frac = true;
}
if (frac) {
m_loc[rxn] = static_cast<int>(m_cn_list.size());
m_cn_list.push_back(C_AnyN(rxn, k, order, stoich));
}
else {
switch (k.size()) {
case 1:
m_loc[rxn] = static_cast<int>(m_c1_list.size());
m_c1_list.push_back(C1(rxn, k[0]));
break;
case 2:
m_loc[rxn] = static_cast<int>(m_c2_list.size());
m_c2_list.push_back(C2(rxn, k[0], k[1]));
break;
case 3:
m_loc[rxn] = static_cast<int>(m_c3_list.size());
m_c3_list.push_back(C3(rxn, k[0], k[1], k[2]));
break;
default:
m_loc[rxn] = static_cast<int>(m_cn_list.size());
m_cn_list.push_back(C_AnyN(rxn, k, order, stoich));
}
}
}
void multiply(const doublereal* input, doublereal* output) const {
_multiply(m_c1_list.begin(), m_c1_list.end(), input, output);
_multiply(m_c2_list.begin(), m_c2_list.end(), input, output);
_multiply(m_c3_list.begin(), m_c3_list.end(), input, output);
_multiply(m_cn_list.begin(), m_cn_list.end(), input, output);
}
void incrementSpecies(const doublereal* input, doublereal* output) const {
_incrementSpecies(m_c1_list.begin(), m_c1_list.end(), input, output);
_incrementSpecies(m_c2_list.begin(), m_c2_list.end(), input, output);
_incrementSpecies(m_c3_list.begin(), m_c3_list.end(), input, output);
_incrementSpecies(m_cn_list.begin(), m_cn_list.end(), input, output);
}
void decrementSpecies(const doublereal* input, doublereal* output) const {
_decrementSpecies(m_c1_list.begin(), m_c1_list.end(), input, output);
_decrementSpecies(m_c2_list.begin(), m_c2_list.end(), input, output);
_decrementSpecies(m_c3_list.begin(), m_c3_list.end(), input, output);
_decrementSpecies(m_cn_list.begin(), m_cn_list.end(), input, output);
}
void incrementReactions(const doublereal* input, doublereal* output) const {
_incrementReactions(m_c1_list.begin(), m_c1_list.end(), input, output);
_incrementReactions(m_c2_list.begin(), m_c2_list.end(), input, output);
_incrementReactions(m_c3_list.begin(), m_c3_list.end(), input, output);
_incrementReactions(m_cn_list.begin(), m_cn_list.end(), input, output);
}
void decrementReactions(const doublereal* input, doublereal* output) const {
_decrementReactions(m_c1_list.begin(), m_c1_list.end(), input, output);
_decrementReactions(m_c2_list.begin(), m_c2_list.end(), input, output);
_decrementReactions(m_c3_list.begin(), m_c3_list.end(), input, output);
_decrementReactions(m_cn_list.begin(), m_cn_list.end(), input, output);
}
void writeIncrementSpecies(std::string r, std::map<int, std::string>& out) {
_writeIncrementSpecies(m_c1_list.begin(), m_c1_list.end(), r, out);
_writeIncrementSpecies(m_c2_list.begin(), m_c2_list.end(), r, out);
_writeIncrementSpecies(m_c3_list.begin(), m_c3_list.end(), r, out);
_writeIncrementSpecies(m_cn_list.begin(), m_cn_list.end(), r, out);
}
void writeDecrementSpecies(std::string r, std::map<int, std::string>& out) {
_writeDecrementSpecies(m_c1_list.begin(), m_c1_list.end(), r, out);
_writeDecrementSpecies(m_c2_list.begin(), m_c2_list.end(), r, out);
_writeDecrementSpecies(m_c3_list.begin(), m_c3_list.end(), r, out);
_writeDecrementSpecies(m_cn_list.begin(), m_cn_list.end(), r, out);
}
void writeIncrementReaction(std::string r, std::map<int, std::string>& out) {
_writeIncrementReaction(m_c1_list.begin(), m_c1_list.end(), r, out);
_writeIncrementReaction(m_c2_list.begin(), m_c2_list.end(), r, out);
_writeIncrementReaction(m_c3_list.begin(), m_c3_list.end(), r, out);
_writeIncrementReaction(m_cn_list.begin(), m_cn_list.end(), r, out);
}
void writeDecrementReaction(std::string r, std::map<int, std::string>& out) {
_writeDecrementReaction(m_c1_list.begin(), m_c1_list.end(), r, out);
_writeDecrementReaction(m_c2_list.begin(), m_c2_list.end(), r, out);
_writeDecrementReaction(m_c3_list.begin(), m_c3_list.end(), r, out);
_writeDecrementReaction(m_cn_list.begin(), m_cn_list.end(), r, out);
}
void writeMultiply(std::string r, std::map<int, std::string>& out) {
_writeMultiply(m_c1_list.begin(), m_c1_list.end(), r, out);
_writeMultiply(m_c2_list.begin(), m_c2_list.end(), r, out);
_writeMultiply(m_c3_list.begin(), m_c3_list.end(), r, out);
_writeMultiply(m_cn_list.begin(), m_cn_list.end(), r, out);
}
private:
std::vector<C1> m_c1_list;
std::vector<C2> m_c2_list;
std::vector<C3> m_c3_list;
std::vector<C_AnyN> m_cn_list;
/**
* Std::Mapping with the Reaction Number as key and the Number of species
* as the value.
*/
std::map<int, int> m_n;
/**
* Std::Mapping with the Reaction Number as key and the placement in the
* vector of reactions list( i.e., m_c1_list[]) as key
*/
std::map<int, int> m_loc;
};
#undef INCL_STOICH_WRITER
#ifdef INCL_STOICH_WRITER
class StoichWriter {
public:
StoichWriter() {}
void add(int rxn, const vector_int& k) {
int n, nn = k.size();
for (n = 0; n < nn; n++) {
if (m_mult[rxn] != "") m_mult[rxn] += " * ";
m_mult[rxn] += "c[" + int2str(k[n]) + "]";
m_is[k[n]] += " + rop[" + int2str(rxn) + "]";
m_ds[k[n]] += " - rop[" + int2str(rxn) + "]";
m_ir[rxn] += " + grt[" + int2str(k[n]) + "]";
m_dr[rxn] += " - grt[" + int2str(k[n]) + "]";
}
}
void add(int rxn, const vector_int& k, const vector_fp& order,
const vector_fp& stoich) {
int n, nn = k.size();
std::string s;
for (n = 0; n < nn; n++) {
if (order[n] == 1.0)
m_mult[rxn] += "*c[" + int2str(k[n]) + "]";
else
m_mult[rxn] += "*pow(c[" _ int2str(k[n]) + "],"+fp2str(order[n])+")";
if (stoich[n] == 1.0) {
m_is[k[n]] += " + r[" + int2str(rxn) + "]";
m_ds[k[n]] += " - r[" + int2str(rxn) + "]";
m_ir[rxn] += " + g[" + int2str(k[n]) + "]";
m_dr[rxn] += " - g[" + int2str(k[n]) + "]";
}
else {
s = fp2str(stoich[n]);
m_is[k[n]] += " + "+s+"*r[" + int2str(rxn) + "]";
m_ds[k[n]] += " - "+s+"*r[" + int2str(rxn) + "]";
m_ir[rxn] += " + "+s+"*g[" + int2str(k[n]) + "]";
m_dr[rxn] += " - "+s+"*g[" + int2str(k[n]) + "]";
}
}
}
std::string mult(int rxn) { return m_mult[rxn]; }
std::string incrSpec(int k, std::string) { return m_is[k]; }
std::string decrSpec(int k) { return m_ds[k]; }
std::string incrRxn(int rxn) { return m_ir[rxn]; }
std::string decrRxn(int rxn) { return m_dr[rxn]; }
private:
std::map<int, std::string> m_mult, m_ir, m_dr, m_is, m_ds;
};
#endif
}
#endif

View file

@ -0,0 +1,187 @@
/**
* @file ThirdBodyMgr.h
*
* $Author$
* $Revision$
* $Date$
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_THIRDBODY_MGR_H
#define CT_THIRDBODY_MGR_H
#include <algorithm>
#include "ct_defs.h"
#include "utilities.h"
#include "Enhanced3BConc.h"
namespace Cantera {
template<class _E>
class ThirdBodyMgr{
public:
ThirdBodyMgr<_E>() : m_n(0) {}
void install( int rxnNumber, const std::map<int, doublereal>& enhanced,
doublereal dflt=1.0) {
m_n++;
m_reaction_index.push_back( rxnNumber );
m_concm.push_back( _E(static_cast<int>(enhanced.size()),
enhanced, dflt ) );
}
void update(const vector_fp& conc, doublereal ctot, workPtr work) {
TYPENAME_KEYWORD std::vector<_E>::const_iterator b = m_concm.begin();
//doublereal* v = m_values.begin();
for (; b != m_concm.end(); ++b, ++work)
*work = b->update(conc, ctot);
}
void multiply(doublereal* output, const_workPtr work) {
scatter_mult(work, work + m_n,
output, m_reaction_index.begin());
}
size_t workSize() { return m_concm.size(); }
bool contains(int rxnNumber) {
return (find(m_reaction_index.begin(),
m_reaction_index.end(), rxnNumber)
!= m_reaction_index.end());
}
protected:
int m_n;
vector_int m_reaction_index;
std::vector<_E> m_concm;
};
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,217 @@
/**
* @file importKinetics.h
* Definitions of global routines for the importing
* of data from XML files (see \ref inputfiles).
*
* This file contains routines which are global routines, i.e.,
* not part of any object. These routine take as input, ctml
* pointers to data, and pointers to %Cantera objects. The purpose
* of these routines is to intialize the %Cantera objects with data
* from the ctml tree structures.
*/
/*
* $Author$
* $Revision$
* $Date$
*
*/
// Copyright 2002 California Institute of Technology
#ifndef CT_IMPORTCTML_H
#define CT_IMPORTCTML_H
#include <string>
#include "ThermoPhase.h"
#include "Kinetics.h"
namespace Cantera {
class Kinetics;
class SpeciesThermoFactory;
class XML_Node;
//!This function returns a ratio if two reactions are duplicates of
//!one another, and 0.0 otherwise.
/*!
* The input arguments are two
* maps from species number to stoichiometric coefficient, one for
* each reaction. The reactions are considered duplicates if their
* stoichiometric coefficients have the same ratio for all
* species.
*
* @param r1 map 1
* @param r2 map 2
*
* @return
* Returns 0.0 if the reactions are not the same.
* If the reactions are the same, it returns the ratio of the
* stoichiometric coefficients.
*
* @ingroup kineticsmgr
*/
doublereal isDuplicateReaction(std::map<int, doublereal>& r1,
std::map<int, doublereal>& r2);
//! This function will check a specific reaction to see if the elements balance.
/*!
* @param kin Kinetics object
* @param rdata Object containing the information about one reaction
* @param errorTolerance double containing the error tolerance.
*
* @ingroup kineticsmgr
*/
void checkRxnElementBalance(Kinetics& kin,
const ReactionData &rdata,
doublereal errorTolerance = 1.0e-3);
//! Read the rate coefficient data from the XML file.
/*!
* Extract the rate coefficient for a reaction from the xml node, kf.
* kf should point to a XML element named "rateCoeff".
* rdata is the partially filled ReactionData object for the reaction.
* This function will fill in more fields in the ReactionData object.
*
* @param kf XML_Node containing information about the rate coefficients.
* @param kin kinetics manager
* @param rdata ReactionData referece
* @param negA Boolean indicating whether negative A's are ok.
*
* Trigger anexception for negative A unless specifically authorized.
*
* @ingroup kineticsmgr
*/
void getRateCoefficient(const XML_Node& kf, kinetics_t& kin,
ReactionData& rdata, int negA);
//! Create a new ThermoPhase object and initializes it according to the XML tree database.
//! Install information about reactions into the kinetics object, kin.
/*!
* At this point, parent usually refers to the phase xml element.
* One of the children of this element is reactionArray,
* the element which determines where in the xml file to
* look up the reaction rate data.
*
* This is a wrapper routine around the static function installReaction()
*
* @param p parent XML phase element
* @param kin Kinetics object to install reactions into
* @param default_phase The default_phase is the default phase to assume when
* looking up species.
* @param check_for_duplicates Check for reactions with exactly the same
* reactants and products.
*
* @return
* On return, if reaction instantiation goes correctly, return true.
* If there is a problem, return false.
*
* @ingroup kineticsmgr
*/
bool installReactionArrays(const XML_Node& p, Kinetics& kin,
std::string default_phase,
bool check_for_duplicates = false);
//! Import a reaction mechanism for a phase or an interface.
/*!
* This routine will import a reaction mechanism into a
* kinetics object. The reaction
* mechanism may either be homogeneous or heterogeneous,
* involving multiple ThermoPhase objects.
* The hosting phase should be included as the first argument.
* For example, if phase I is an interface phase between bulk
* phases A and B. Then, the XML_Node for phase I should be
* the first argument.
* The vector of %ThermoPhase objects should be consist of pointers
* to phases I, A, and B.
*
* @param phase This is an xml node containing a description
* of a phase. Within the phase is a XML element
* called reactionArray containing the location
* of the description of the reactions that make
* up the kinetics object.
* Also within the phase is an XML element called
* phaseArray containing a listing of other phases
* that participate in the kinetics mechanism.
*
* @param th This is a list of ThermoPhase pointers containing
* the phases that participate in the kinetics
* reactions. All of the phases must have already
* been initialized and formed within Cantera.
* However, their pointers should not have been
* added to the Kinetics object; this addition
* is carried out here.
*
* @param kin This is a pointer to a bare kinetics manager class
* that will be initialized with the kinetics
* mechanism.
*
* @ingroup kineticsmgr
*
*/
bool importKinetics(const XML_Node& phase, std::vector<ThermoPhase*> th,
Kinetics* kin);
//!Build a single-phase ThermoPhase object with associated kinetics mechanism.
/*!
* In a single call, this routine initializes a ThermoPhase object and a
* homogenous kinetics object for a phase.
*
* @param root pointer to the XML tree which will be searched to find the
* XML phase element.
*
* @param id Name of the phase to be searched for.
* @param nm Name of the XML element. Should be "phase"
* @param th Pointer to a bare ThermoPhase object, which will be initialized
* by this operaton.
* @param k Pointer to a bare Kinetics object, which will be initialized
* by this operation to a homogeneous kinetics manager
*
* @return
* Returns true if all went well. If there are errors, it will return false.
*
* For Example
*
* @code
* ThermoPhase *th = new ThermoPhase();
* Kinetics *k = new Kinetics();
* XML_Node *root = get_XML_File("gri30.xml");
* ok = buildSolutionFromXML(root, "gri30_mix", "phase", th, k)
* @endcode
*
* @ingroup inputfiles
* @see importKinetics()
*/
bool buildSolutionFromXML(XML_Node& root, std::string id, std::string nm,
ThermoPhase* th, Kinetics* k);
//! Search an XML tree for species data.
/*!
*
* This utility routine will search the XML tree for the species
* named by the string, kname. It will return the XML_Node
* pointer.
* Failures of any kind return the null pointer.
*
* @param kname species Name
* @param phaseSpeciesData Pointer to the phase XML node pertaining to the
* species database for the phase to be found
*
* @return
* Returns a pointer to teh XML node containing the species data.
*
* @ingroup inputfiles
*/
//const XML_Node *speciesXML_Node(std::string kname,
// const XML_Node *phaseSpeciesData);
}
#endif

View file

@ -0,0 +1,111 @@
/**
* @file reaction_defs.h
* This file defines some constants used to specify reaction types.
*/
/*
* $Author$
* $Date$
* $Revision$
*
*/
// Copyright 2001 California Institute of Technology
#ifndef CT_RXN_DEFS_H
#define CT_RXN_DEFS_H
#include "ct_defs.h"
namespace Cantera {
const int NONE = 0;
/// @name Reaction Types
//@{
/**
* A reaction with a rate coefficient that depends only on
* temperature. Example: O + OH <-> O2 + H
*/
const int ELEMENTARY_RXN = 1;
/**
* A reaction that requires a third-body collision partner. Example:
* O2 + M <-> O + O + M
*/
const int THREE_BODY_RXN = 2;
/**
* The general form for an association or dissociation reaction, with a
* pressure-dependent rate. Example: CH3 + H (+M) <-> CH4 (+M)
*/
const int FALLOFF_RXN = 4;
/**
* A chemical activation reaction. For these reactions, the rate falls
* off as the pressure increases, due to collisional stabilization of
* a reaction intermediate. Example: Si + SiH4 (+M) <-> Si2H2 + H2
* (+M), which competes with Si + SiH4 (+M) <-> Si2H4 (+M).
* @todo Implement chemical activation reactions.
*/
const int CHEMACT_RXN = 8;
/**
* A reaction occurring on a surface.
*/
const int SURFACE_RXN = 20;
/**
* A reaction occurring at a one-dimensional interface between two
* surface phases.
*/
const int EDGE_RXN = 22;
/**
* A global reaction. These may have non-integral reaction orders,
* and are not allowed to be reversible.
*/
const int GLOBAL_RXN = 30;
//@}
/** @name Rate Coefficient Types
* These types define the supported rate coefficient types for
* elementary reactions. Any of these may also be used as the high and
* low-pressure limits of falloff and chemical activation reactions.
*
* Note that not all of these are currently implemented!
* @todo Finish implementing reaction rate types.
*/
//@{
const int ARRHENIUS = 1;
const int LANDAUTELLER = 2;
const int TSTRATE = 3;
const int SURF_ARRHENIUS = 4;
const int ARRHENIUS_SUM = 5;
//@}
/** @name Falloff Function Types
*/
//@{
const int SIMPLE_FALLOFF = 100;
const int TROE3_FALLOFF = 110;
const int TROE4_FALLOFF = 111;
const int SRI3_FALLOFF = 112;
const int SRI5_FALLOFF = 113;
const int WF_FALLOFF = 114;
//@}
// error flags
const int NO_ERROR = 0;
const int UNKNOWN_REACTION_TYPE = -100;
const int UNKNOWN_RATE_COEFF_TYPE = -200;
const int NOT_YET_IMPLEMENTED = -300;
}
#endif