|
[Sponsors] |
understanding reverse rate calculation for chemical reactions |
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
March 10, 2020, 07:41 |
understanding reverse rate calculation for chemical reactions
|
#1 |
Senior Member
Michael Alletto
Join Date: Jun 2018
Location: Bremen
Posts: 615
Rep Power: 15 |
Hello all,
I'm trying to understand how the reverse rate is calculated. Following the manual of chemkin (https://www3.nd.edu/~powers/ame.60636/chemkin2000.pdf) the reverse rate of the ith reaction is calculated as follows: the equilibrium constant is calculated as follows: being the sum of the stoichiometric coefficient of the ith reaction. Furthermore being are the enthalpy and entropy of the species k. the source code for the calculation of k_ri can be found in $FOAM_SRC/thermophysicalModels/specie/reaction/Reactions/ReversibleReaction/ReversibleReaction.C: Code:
template < template<class> class ReactionType, class ReactionThermo, class ReactionRate > Foam::scalar Foam::ReversibleReaction < ReactionType, ReactionThermo, ReactionRate >::kr ( const scalar kfwd, const scalar p, const scalar T, const scalarField& c ) const { return kfwd/max(this->Kc(p, T), 1e-6); } Code:
template<class Thermo, template<class> class Type> inline Foam::scalar Foam::species::thermo<Thermo, Type>::K(const scalar p, const scalar T) const { scalar arg = -this->Y()*this->G(Pstd, T)/(RR*T); if (arg < 600) { return exp(arg); } else { return VGREAT; } } template<class Thermo, template<class> class Type> inline Foam::scalar Foam::species::thermo<Thermo, Type>::Kp(const scalar p, const scalar T) const { return K(p, T); } template<class Thermo, template<class> class Type> inline Foam::scalar Foam::species::thermo<Thermo, Type>::Kc(const scalar p, const scalar T) const { const scalar nm = this->Y()/this->W(); if (equal(nm, SMALL)) { return Kp(p, T); } else { return Kp(p, T)*pow(Pstd/(RR*T), nm); } } Best, Michael |
|
March 10, 2020, 16:23 |
|
#2 |
Senior Member
Adhiraj
Join Date: Sep 2010
Location: Karnataka, India
Posts: 187
Rep Power: 15 |
As far as I can tell, OpenFOAM handles multiple species like this:
|
|
March 11, 2020, 17:25 |
|
#3 |
Senior Member
Michael Alletto
Join Date: Jun 2018
Location: Bremen
Posts: 615
Rep Power: 15 |
Thank you Adhiraj for pointing me in the right direction. Looking at the constructor of the Reaction class ($FOAM_SRC/thermophysicalModels/specie/reaction/Reactions/Reaction/Reaction.C)
we see the function setThermo Code:
template<class ReactionThermo> Foam::Reaction<ReactionThermo>::Reaction ( const speciesTable& species, const List<specieCoeffs>& lhs, const List<specieCoeffs>& rhs, const HashPtrTable<ReactionThermo>& thermoDatabase, bool initReactionThermo ) : ReactionThermo::thermoType(*thermoDatabase[species[0]]), name_("un-named-reaction-" + Foam::name(getNewReactionID())), species_(species), lhs_(lhs), rhs_(rhs) { if (initReactionThermo) { setThermo(thermoDatabase); } } in this function we see that the stoichiometric coefficients and the molar weight of the species enter in the construction of the thermodynamic properties: Code:
template<class ReactionThermo> void Foam::Reaction<ReactionThermo>::setThermo ( const HashPtrTable<ReactionThermo>& thermoDatabase ) { typename ReactionThermo::thermoType rhsThermo ( rhs_[0].stoichCoeff *(*thermoDatabase[species_[rhs_[0].index]]).W() *(*thermoDatabase[species_[rhs_[0].index]]) ); for (label i=1; i<rhs_.size(); ++i) { rhsThermo += rhs_[i].stoichCoeff *(*thermoDatabase[species_[rhs_[i].index]]).W() *(*thermoDatabase[species_[rhs_[i].index]]); } typename ReactionThermo::thermoType lhsThermo ( lhs_[0].stoichCoeff *(*thermoDatabase[species_[lhs_[0].index]]).W() *(*thermoDatabase[species_[lhs_[0].index]]) ); for (label i=1; i<lhs_.size(); ++i) { lhsThermo += lhs_[i].stoichCoeff *(*thermoDatabase[species_[lhs_[i].index]]).W() *(*thermoDatabase[species_[lhs_[i].index]]); } ReactionThermo::thermoType::operator=(lhsThermo == rhsThermo); } |
|
March 12, 2020, 11:02 |
|
#4 |
Senior Member
Michael Alletto
Join Date: Jun 2018
Location: Bremen
Posts: 615
Rep Power: 15 |
I had a look how the exponent in is calculated.
Key feature is the function setThermo in the file Reaction.C: Code:
template<class ReactionThermo> void Foam::Reaction<ReactionThermo>::setThermo ( const HashPtrTable<ReactionThermo>& thermoDatabase ) { typename ReactionThermo::thermoType rhsThermo ( rhs_[0].stoichCoeff *(*thermoDatabase[species_[rhs_[0].index]]).W() *(*thermoDatabase[species_[rhs_[0].index]]) ); for (label i=1; i<rhs_.size(); ++i) { rhsThermo += rhs_[i].stoichCoeff *(*thermoDatabase[species_[rhs_[i].index]]).W() *(*thermoDatabase[species_[rhs_[i].index]]); } typename ReactionThermo::thermoType lhsThermo ( lhs_[0].stoichCoeff *(*thermoDatabase[species_[lhs_[0].index]]).W() *(*thermoDatabase[species_[lhs_[0].index]]) ); for (label i=1; i<lhs_.size(); ++i) { lhsThermo += lhs_[i].stoichCoeff *(*thermoDatabase[species_[lhs_[i].index]]).W() *(*thermoDatabase[species_[lhs_[i].index]]); } ReactionThermo::thermoType::operator=(lhsThermo == rhsThermo); } To calculate the exponent we need to find out how this operation affect the Y_ and molWeight_ data of the of the thermodynamic object is affected by this operation. Since the thermodynamic object inherits from the equation of state object and this again inherits from the species object and the latter carries the data Y_ and molWeight_ we'll have a look how the above operators are defined in $FOAM_SRC/thermophysicalModels/specie/specie/specieI.H: Code:
inline specie operator*(const scalar s, const specie& st) { return specie ( s*st.Y_, st.molWeight_ ); } inline void specie::operator+=(const specie& st) { const scalar sumY = Y_ + st.Y_; if (mag(sumY) > SMALL) { molWeight_ = sumY/(Y_/molWeight_ + st.Y_/st.molWeight_); } Y_ = sumY; } inline specie operator==(const specie& st1, const specie& st2) { scalar diffY = st2.Y_ - st1.Y_; if (mag(diffY) < SMALL) { diffY = SMALL; } const scalar diffRW = st2.Y_/st2.molWeight_ - st1.Y_/st1.molWeight_; #ifdef __clang__ // Using intermediate volatile bool to prevent compiler optimising out the // if block (above) - CLANG 3.7.1 volatile const bool valid = (mag(diffRW) > SMALL); const scalar molWeight = valid ? diffY/diffRW : GREAT; #else scalar molWeight = GREAT; if (mag(diffRW) > SMALL) { molWeight = diffY/diffRW; } #endif return specie(diffY, molWeight); } Code:
molWeight_ = sumY/(Y_/molWeight_ + st.Y_/st.molWeight_); and after the summation we obtain hence and for the left hand side (the forward side of the reaction). An analogous formulation is obtained also for the right hand side. After the application of the == operator we obtain: and We see that the exponent nm is computed as follows: Code:
const scalar nm = this->Y()/this->W(); |
|
March 16, 2020, 11:52 |
|
#5 |
Senior Member
Michael Alletto
Join Date: Jun 2018
Location: Bremen
Posts: 615
Rep Power: 15 |
If someone is interest there is a description of how the reverse rate constant is calculated also here: https://openfoamwiki.net/index.php/ChemFoam
|
|
March 7, 2021, 05:20 |
|
#6 |
New Member
Join Date: May 2020
Posts: 4
Rep Power: 5 |
Hi mAlletto, then how should we explain the calculation of arg = -this->Y()*this->G(Pstd, T)/(RR*T) in OpenFoam instead of -this->G(Pstd, T)/(RR*T)?
Thanks. |
|
March 7, 2021, 06:08 |
|
#7 |
New Member
Join Date: May 2020
Posts: 4
Rep Power: 5 |
It is still not clear why Y=v*W
|
|
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
calculation of mass flow rate from the inner part of a vertical cylinder in natural | manoj kumar dash | FLUENT | 5 | August 24, 2018 10:57 |
Understanding Surface Growth Rate | alw7 | STAR-CCM+ | 2 | August 13, 2018 19:53 |
PaSR + infinite reaction rate in reactingFoam --> no reactions occurring | tatu | OpenFOAM Running, Solving & CFD | 2 | November 24, 2016 18:34 |
Reverse rate parameters with CHEMKIN imports | Kevin L | FLUENT | 1 | June 27, 2013 04:22 |
Heat transfer rate calculation | Lotta_questions | CFX | 3 | February 11, 2010 18:35 |