In [1]: import Cantera as ctIn [2]: gas = ct.GRI30()In [3]: gas.set(T=1700, P=101325, X='H2:1.0, N2:3.0')In [4]: gas.equilibriumConstants()[39]Out[4]: 6418881501.4493847In [5]: gas.set(T=1700, P=101325*5, X='H2:1.0, N2:3.0')In [6]: gas.equilibriumConstants()[39]Out[6]: 6418881501.4493618
Hi,
The function getEquilibriumConstants() from InterfaceKinetics returns an equilibrium constant that is pressure dependent in the general case, but is pressure independent for reactions involving ideal gases. This is consistent with what’s done with solution thermodynamics (see Denbigh chaps 9 and 10). getEquilibriumConstants() doesn’t return K_p nor K_c per se, because these really aren’t defined well or aren’t meaningful for general non-ideal phases, which may be gases, solutions, solids, or a combination of those.
Cantera’s implementation of equilibrium is consistent with the activity coefficient model for presentation of chemical potentials with additions to also make it consistent with the kinetics operator. Let me explain. I’ll leave out complications due to charge transfer reactions. The chemical potential of a species can be separated into the standard state chemical potential and the activity.
chemPot_i(T, P, X_j) = chemPot_i^ss(T,P) + RT ln (a_i)
chemPot_i^ss(T,P) is the standard state chemical potential of species i at the solution T and P.
a_i is the activity of species i.
For a single reaction the sum of the product of the chemical potentials multiplied by the stoichiometric coefficient must be zero. The equilibrium constant returned by getEquilibriumConstants() is based on the sum of the product of [chemPot_i^ss(T,P) - RT ln(co_i)] and the stoichiometric coefficients.
For ideal gases,
chemPot_i^ss(T,P) = chemPot_i^0(T,Po) + RT ln (P / Po)
where Po is the reference pressure. Usually 1 bar is used in the JANAF tables. In other words, the standard state for gases is defined as a pure ideal gas species at the temperature and pressure of the solution. The reference state for gases is defined as a pure ideal gas species at the reference pressure of 1 bar and the temperature of the solution. (it’s the reference state thermo that can be looked up in the JANAF tables, btw).
For mass action kinetics, we multiply the activity by the standard concentration for species i to obtain an activity concentration, which is then used in kinetics expressions involving the phase.
ac_i = (co_i) (a_i)
For gases, the standard concentration is defined as P/RT , where P is the system pressure and T is the system temperature. Note, for solids and liquids and surface ligands, usually the standard concentration is defined as unity, however. Then the activity concentration for species i, ac_i, is defined for gases as
ac_i = P X_i gamma_i / RT
which is basically the concentration of gases, which is what you want for gas-phase mass action kinetics. (gamma_i is the activity coefficient of species i, which for ideal gases is equal to one)
Therefore, we can manipulate terms to get:
chemPot_i(T, P, X_j) = chemPot_i^ss(T,P) + RT ln (ac_i) – RT ln(co_i)
For ideal gases, the terms left over after separating out the concentration looks a lot like the input to the concentration equilibrium coefficient.
chemPot_i^ss(T,P) – RT ln(co_i) = chemPot_i^o(T,Po) + RT ln (P / Po) - RT ln (RT / P)
= chemPot_i^o(T,Po) + RT ln (RT / Po)
This is what’s used in the equilibrium constant. Therefore, as Ray’s example shows the equilibrium constant returned by Cantera is independent of P for gas phase reaction that are not equimolar, but only because there is a fortuitous cancelling of terms for the ideal gas case.
For non-ideal solutions (e.g., brines at elevated temperatures and pressures) the situation gets complicated, and there is no other general starting point possible other than the activity coefficient representation of the chemical potential. In particular reactions which lower the molar volumes are constituents are favored when the pressure goes up. This effect is captured by the pressure dependence of the standard state gibbs free energies of the species and is reflected in a change in the equilibrium constant as a function of pressure. Cantera’s implementation has been checked against multiple problems and is quite solid.
In particular IdealGasPhase::getStandardChemPotentials() adds the + RT ln (P / Po) term as appropriate to change the chemical potential from the reference pressure to the current pressure. IdealGasPhase::getChemPotentials() just adds the RTln(X_i) term to the resulting standard state chemical potential.
Best wishes,
Harry
--
You received this message because you are subscribed to the Google Groups "Cantera User's Group" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/cantera-users/-/SoEsUaxx-30J.
To post to this group, send email to
canter...@googlegroups.com.
To unsubscribe from this group, send email to
cantera-user...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/cantera-users?hl=en.
import cantera as ctimport numpy as np
gas = ct.Solution('sample.cti')gas.TPX = 1100, 5e5, 'c2h5:0.9, c4h10:0.1'gas.equilibrate('TP')
p_c4h10, p_c2h5 = gas.P * gas['c4h10', 'c2h5'].XRT = ct.gas_constant * gas.Tp0 = 1e5nu_net = 1
# KcKc_1 = gas.equilibrium_constants[0]Kc_2 = ((p_c4h10/RT)**1) * ((p_c2h5/RT)**-2)print 'Kc: {0:e}, {1:e}'.format(Kc_1, Kc_2)
# = 2.038503e+09
# KpKp_1 = ((p_c4h10/p0)**1) * ((p_c2h5/p0)**-2)# need delta G at p0gas.TP = None, p0Kp_2 = np.exp(-gas.delta_standard_gibbs[0] / RT)Kp_3 = Kc_1 * (p0/RT)**nu_netprint 'Kp: {0:e}, {1:e}, {2:e}'.format(Kp_1, Kp_2, Kp_3)
# 2.228868e+07
--
You received this message because you are subscribed to a topic in the Google Groups "Cantera Users' Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cantera-users/65bMdBD0dAI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cantera-user...@googlegroups.com.
Visit this group at http://groups.google.com/group/cantera-users.
For more options, visit https://groups.google.com/d/optout.