Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in reaction rate calculation #1273

Closed
NickJCSQ opened this issue May 5, 2022 · 6 comments
Closed

Error in reaction rate calculation #1273

NickJCSQ opened this issue May 5, 2022 · 6 comments
Labels

Comments

@NickJCSQ
Copy link

NickJCSQ commented May 5, 2022

Description:
In the formula that calculates the value Kci (following CHEMKIN's notation) cantera uses the pressure of the mixture instead of 1 atm, which is what should be used (according to CHEMKIN's documentation, which cantera says it is based on). The formula used by cantera is Kci = Kpi * (P/(R*T))^(sum(vki)) whilst it sould use Patm instead of P (with Patm = 1 atm). At the end of this post I have attached the documentation.

How I found this error:
I was writing my own code in order to calculate the reaction rates of a mixture. To validate it I was comparing it to the solutions given by cantera. All intermidiate values of my code lined up but I could not manage to get the final solution just right. After much testing I found the mentioned error. If I changed the value of 1atm to the pressure of the mixture my results lined up perfectly with cantera's (all significant figures).
The error caused by this difference in the reaction rates is not much, the first 4 to 5 significant figures were the same in my code and cantera for the examples tested; this is due to the little significance of the terms affected by the formula in the example used. As I said, since changing this formula makes my code completely coincide with cantera's there are no other external factors and the difference must be located in said formula.

Documentation which I followed:
I attach CHEMKIN's documentation, where one can find said formula and where it is explicitely said that the pressure should be 1atm. As I mentioned before, cantera says in its webpage that it follows said documentation. The formula is numbered 54 in page 21.
ChemKin II Fortran theory.pdf

Please let me know if there has been any misconception from my part.

@ischoegl
Copy link
Member

ischoegl commented May 5, 2022

@NickJCSQ ... thank you for filing this issue report. While CHEMKIN II is rather dated, more recent CHEMKIN manuals still use the same equation. Please note that Cantera's code generally follows Kee, Coltrin and Glarborg, 'Chemically Reacting Flow', Wiley Interscience, 2003 (there's also a newer version of that text), where the equation is 9.91. Looking over the source code, I am actually not sure that Cantera is even using that expression? So it would be helpful if you could be more specific about where you suspect an error - please include Cantera version, as well as file and line number(s). (Note that I edited this post after looking up some references.)

@bryanwweber
Copy link
Member

@NickJCSQ To add to the comment from @ischoegl, please also include a minimal reproducer script, so that we can help verify the code in Cantera. Thank you!

@ischoegl
Copy link
Member

ischoegl commented May 5, 2022

To aid discussion: the question appears to be about the calculation of the equilibrium constant. For Cantera's implementation, the docstring is

//! 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.
*
* \f[
* Kc_i = exp [ \Delta G_{ss,i} ] prod(Cs_k) exp(\sum_k \nu_{k,i} F \phi_n) ]
* \f]
*
* @param kc Output vector containing the equilibrium constants.
* Length: nReactions().
*/

where - for the case of GasKinetics - the actual code is
void GasKinetics::getEquilibriumConstants(doublereal* kc)
{
update_rates_T(); // this step ensures that m_grt is updated
vector_fp& delta_gibbs0 = m_rbuf0;
fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0);
// compute Delta G^0 for all reactions
getReactionDelta(m_grt.data(), delta_gibbs0.data());
double rrt = 1.0 / thermo().RT();
for (size_t i = 0; i < nReactions(); i++) {
kc[i] = exp(-delta_gibbs0[i] * rrt + m_dn[i] * m_logStandConc);
}
}

@NickJCSQ
Copy link
Author

NickJCSQ commented May 9, 2022

I believe I am currently using cantera version 2.4. I did not make the installation and I do not know where to find the version of the software, please let me know how to check it.

I have not found any open source version of the documents mentioned, so I cannot check their contents.

The exact function where I find the difference is Cantera::Kinetics::getRevRateConstants.
Using reaction ' H + H = H2 ' as an example I get the same results as cantera for the forward rates (using Cantera::Kinetics::getFwdRateConstants). On the other hand, results given by Cantera::Kinetics::getRevRateConstants are off by a factor of (P/1atm)^sum(v''[k]-v'[k]); which is why I believe the error must be in the mentioned formula. On the contrary, if I use a formula where the sum(v''[k]-v'[k])=0 such as ' H + O2 = OH + O ' (same amount of moles in products in reactants) the reactions rates coincide perfectly (including the reverse rates. This strongly indicates that the difference resides in the operation Kci = Kpi*(Patm/(RT))^sum(v''[k]-v'[k]) or its equivalent.

Looking at the provided code snippet for the equilibrium constant calculation it seams that it calculates Kpi but does not take into account the term result of the molar difference between products and reactants, but I could be mistaken since it is not the same formula that I am using. The formula I am using for Kp is Kp[i] = exp(dS/R - dH/(RT)) which seams quite similar to the one provided for Kc[i] in the snippet. My integration strictly follows the formulas from the CHEMKIN manual.

@bryanwweber
Copy link
Member

I believe I am currently using cantera version 2.4.

This version is two-versions out-of-date, please update if you can. You can write import cantera; print(cantera.__version__) to check the version.

In addition, please include a minimal, complete, verifiable example code with your report. Otherwise, we have absolutely no chance of seeing what is really going on here.

@speth
Copy link
Member

speth commented May 10, 2022

Although it would really help to have a complete example, I think you might be running into Cantera's confusing definition of "standard state". Despite the name delta_gibbs0 in the code snippet @ischoegl posted above, the values in this array are pressure dependent. This is spelled out (among other places) in the documentation for ThermoPhase::getStandardChemPotentials:

//! Get the array of chemical potentials at unit activity for the species at
//! their standard states at the current *T* and *P* of the solution.
/*!
* These are the standard state chemical potentials \f$ \mu^0_k(T,P)
* \f$. The values are evaluated at the current temperature and pressure of
* the solution
*
* @param mu Output vector of chemical potentials.
* Length: m_kk.
*/
virtual void getStandardChemPotentials(doublereal* mu) const {

and you can see that the calculation for the ideal gas phase does indeed include the pressure dependence:
void IdealGasPhase::getStandardChemPotentials(doublereal* muStar) const
{
const vector_fp& gibbsrt = gibbs_RT_ref();
scale(gibbsrt.begin(), gibbsrt.end(), muStar, RT());
double tmp = log(pressure() / refPressure()) * RT();
for (size_t k = 0; k < m_kk; k++) {
muStar[k] += tmp; // add RT*ln(P/P_0)
}
}

The only contribution to the full chemical potentials that is not included here is the composition dependence.

The end result of all this is that Cantera's calculation of the reverse reaction rates is correct. One way you can see this is by equilibrating the mixture (the equilibrium code is independent and does not use GasKinetics for any of its calculations) and seeing that the rates for all (reversible) reactions do indeed go to zero.

We've discussed this before (see #841) but not come to a satisfactory resolution.

@speth speth closed this as not planned Won't fix, can't repro, duplicate, stale Jun 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants