Skip to content

Commit

Permalink
[Kinetics] Implement rate-specific voltage correction
Browse files Browse the repository at this point in the history
  • Loading branch information
ischoegl committed Mar 13, 2022
1 parent 56bb1ad commit 5cfb693
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 10 deletions.
27 changes: 27 additions & 0 deletions include/cantera/kinetics/InterfaceKinetics.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ class InterfaceKinetics : public Kinetics

//! values needed to convert from exchange current density to surface
//! reaction rate.
/*!
* @deprecated To be removed after Cantera 2.6.
*/
void updateExchangeCurrentQuantities();

virtual void getDeltaGibbs(doublereal* deltaG);
Expand Down Expand Up @@ -127,6 +130,8 @@ class InterfaceKinetics : public Kinetics
*
* @return Beta parameter. This defaults to zero, even for charge
* transfer reactions.
*
* @deprecated To be removed after Cantera 2.6.
*/
doublereal electrochem_beta(size_t irxn) const;

Expand Down Expand Up @@ -325,6 +330,8 @@ class InterfaceKinetics : public Kinetics
*
* @param kfwd Vector of forward reaction rate constants on which to have
* the voltage correction applied
*
* @deprecated To be removed after Cantera 2.6.
*/
void applyVoltageKfwdCorrection(doublereal* const kfwd);

Expand All @@ -343,6 +350,8 @@ class InterfaceKinetics : public Kinetics
*
* @param kfwd Vector of forward reaction rate constants, given in either
* normal form or in exchange current density form.
*
* @deprecated To be removed after Cantera 2.6.
*/
void convertExchangeCurrentDensityFormulation(doublereal* const kfwd);

Expand Down Expand Up @@ -520,6 +529,8 @@ class InterfaceKinetics : public Kinetics
* potential energy change due to the reaction.
*
* deltaElectricEnergy_[jrxn] = sum_i ( F V_i z_i nu_ij)
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_fp deltaElectricEnergy_;

Expand All @@ -538,6 +549,8 @@ class InterfaceKinetics : public Kinetics
/*!
* Electrochemical transfer coefficient for all reactions that have
* transfer reactions the reaction is given by m_ctrxn[i]
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_fp m_beta;

Expand All @@ -548,6 +561,8 @@ class InterfaceKinetics : public Kinetics
* an index into the m_beta array.
*
* irxn = m_ctrxn[i]
*
* @deprecated To be removed after Cantera 2.6.
*/
std::vector<size_t> m_ctrxn;

Expand All @@ -560,34 +575,44 @@ class InterfaceKinetics : public Kinetics
* the rate constant as a chemical forward rate constant, a standard format.
* m_ctrxn_ecdf[irxn] = 1 this means that the rate coefficient calculator will calculate
* the rate constant as an exchange current density rate constant expression.
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_int m_ctrxn_ecdf;

//! Vector of standard concentrations
/*!
* Length number of kinetic species
* units depend on the definition of the standard concentration within each phase
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_fp m_StandardConc;

//! Vector of delta G^0, the standard state Gibbs free energies for each reaction
/*!
* Length is the number of reactions
* units are Joule kmol-1
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_fp m_deltaG0;

//! Vector of deltaG[] of reaction, the delta Gibbs free energies for each reaction
/*!
* Length is the number of reactions
* units are Joule kmol-1
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_fp m_deltaG;

//! Vector of the products of the standard concentrations of the reactants
/*!
* Units vary wrt what the units of the standard concentrations are
* Length = number of reactions.
*
* @deprecated To be removed after Cantera 2.6.
*/
vector_fp m_ProdStanConcReac;

Expand Down Expand Up @@ -623,6 +648,8 @@ class InterfaceKinetics : public Kinetics
* If this is true, the standard state Gibbs free energy of the reaction
* and the product of the reactant standard concentrations must be
* precalculated in order to calculate the rate constant.
*
* @deprecated To be removed after Cantera 2.6.
*/
bool m_has_exchange_current_density_formulation;

Expand Down
85 changes: 82 additions & 3 deletions include/cantera/kinetics/InterfaceRate.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class CoverageBase
if (shared_data.ready) {
m_siteDensity = shared_data.density;
}

if (m_indices.size() != m_cov.size()) {
// object is not set up correctly (setSpecies needs to be run)
m_acov = NAN;
Expand All @@ -110,6 +111,79 @@ class CoverageBase
m_ecov += m_ec[item.first] * shared_data.coverages[item.second];
m_mcov += m_mc[item.first] * shared_data.logCoverages[item.second];
}

// Update quantities used for exchange current density formulation
if (m_exchangeCurrentDensityFormulation) {
m_deltaG0 = 0.;
m_prodStandardConcentrations = 1.;
for (const auto& item : m_stoichCoeffs) {
m_deltaG0 +=
shared_data.standardChemPotentials[item.first] * item.second;
if (item.second > 0.) {
m_prodStandardConcentrations *=
shared_data.standardConcentrations[item.first];
}
}
}
}

//! Calculate modifications for the forward reaction rate for interfacial charge
//! transfer reactions
/*!
* For reactions that transfer charge across a potential difference, the
* activation energies are modified by the potential difference. This method
* calculates a correction factor based on the net electric potential energy
* change due to the reaction
* \f[
* deltaElectricEnergy = sum_i ( pot_i nu_ij)
* \f]
* where \f$ pot_i = F phi_i z_i \f$ is passed as an argument to this method.
*
* When an electrode reaction rate is specified in terms of its exchange current
* density, the correction factor is adjusted to the standard reaction rate
* constant form and units. Specifically, this converts a reaction rate constant
* that was specified in units of A/m2 to kmol/m2/s.
*
* @param pot Array of potential energies due to voltages
*
* @warning The updated calculation of voltage corrections is an experimental
* part of the %Cantera API and may be changed or removed without notice.
*/
//
double voltageCorrection(const double* pot, double RT) {
if (!m_chargeTransfer) {
return 1.;
}

// Compute the change in electrical potential energy.
// This will only be non-zero if a potential difference is present.
double deltaElectricEnergy = 0.;
for (const auto& item : m_stoichCoeffs) {
deltaElectricEnergy += pot[item.first] * item.second;
}

// Calculate reaction rate correction. Only modify those with a non-zero
// activation energy.
double correction = 1.;
if (deltaElectricEnergy != 0.) {
// Comments preserved from previous implementation:
// Below we decrease the activation energy below zero.
// NOTE, there is some discussion about this point. Should we decrease the
// activation energy below zero? I don't think this has been decided in any
// definitive way. The treatment below is numerically more stable, however.
correction = exp(-m_beta * deltaElectricEnergy / RT);
}

// Update correction if exchange current density formulation format is used.
if (m_exchangeCurrentDensityFormulation) {
// Comment preserved from previous implementation:
// We need to have the straight chemical reaction rate constant to
// come out of this calculation.
double tmp = exp(-m_beta * m_deltaG0 / RT);
tmp /= m_prodStandardConcentrations * Faraday;
correction *= tmp;
}
return correction;
}

//! Return site density [kmol/m^2]
Expand Down Expand Up @@ -139,14 +213,19 @@ class CoverageBase
double m_acov; //!< Coverage contribution to pre-exponential factor
double m_ecov; //!< Coverage contribution to activation energy
double m_mcov; //!< Coverage term in reaction rate
bool m_electrochemistry; //!< Boolean indicating use of electrochemistry
bool m_chargeTransfer; //!< Boolean indicating use of electrochemistry
double m_beta; //!< Forward value of apparent electrochemical transfer coefficient
bool m_exchangeCurrentDensityFormulation; //! Electrochemistry only
double m_deltaG0; //!< Standard state Gibbs free energy
double m_prodStandardConcentrations; //!< Products of standard concentrations
std::map<size_t, size_t> m_indices; //!< Map holding indices of coverage species
std::vector<std::string> m_cov; //!< Vector holding names of coverage species
vector_fp m_ac; //!< Vector holding coverage-specific exponential dependence
vector_fp m_ec; //!< Vector holding coverage-specific activation energy dependence
vector_fp m_mc; //!< Vector holding coverage-specific power-law exponents

//! Pairs of species indices and multiplers to calculate enthalpy change
std::vector<std::pair<size_t, double>> m_stoichCoeffs;
};


Expand Down Expand Up @@ -305,7 +384,7 @@ class InterfaceRate : public RateType, public CoverageBase
}

virtual bool usesElectrochemistry() override {
return m_electrochemistry;
return m_chargeTransfer;
}

//! Update reaction rate parameters
Expand Down Expand Up @@ -438,7 +517,7 @@ class StickingRate : public RateType, public StickingCoverage
}

virtual bool usesElectrochemistry() override {
return m_electrochemistry;
return m_chargeTransfer;
}

//! Update reaction rate parameters
Expand Down
8 changes: 6 additions & 2 deletions include/cantera/kinetics/ReactionData.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,17 @@ struct CoverageData : public BlowersMaselData
coverages.resize(n_species, 0.);
logCoverages.resize(n_species, 0.);
partial_molar_enthalpies.resize(n_species, 0.);
standardChemPotentials.resize(n_species, 0.);
standardConcentrations.resize(n_species, 0.);
ready = true;
}

double sqrtT; //!< square root of temperature

vector_fp coverages; //!< vector holding surface coverages
vector_fp logCoverages; //!< vector holding logarithm of surface coverages
vector_fp coverages; //!< surface coverages
vector_fp logCoverages; //!< logarithm of surface coverages
vector_fp standardChemPotentials; //!< standard state chemical potentials
vector_fp standardConcentrations; //!< standard state concentrations
};

}
Expand Down
16 changes: 13 additions & 3 deletions src/kinetics/InterfaceRate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ CoverageBase::CoverageBase()
, m_acov(0.)
, m_ecov(0.)
, m_mcov(0.)
, m_electrochemistry(false)
, m_chargeTransfer(false)
, m_beta(0.5)
, m_exchangeCurrentDensityFormulation(false)
, m_deltaG0(NAN)
, m_prodStandardConcentrations(NAN)
{
}

Expand All @@ -42,7 +44,7 @@ void CoverageBase::getParameters(AnyMap& node) const
getCoverageDependencies(deps);
node["coverage-dependencies"] = std::move(deps);
}
if (m_electrochemistry) {
if (m_chargeTransfer) {
if (m_beta != 0.5) {
node["beta"] = m_beta;
}
Expand Down Expand Up @@ -127,8 +129,16 @@ void CoverageBase::setSpecies(const std::vector<std::string>& species)

void CoverageBase::setContext(const Reaction& rxn, const Kinetics& kin)
{
m_electrochemistry = rxn.checkElectrochemistry(kin);
m_chargeTransfer = rxn.checkElectrochemistry(kin);
setSpecies(kin.thermo().speciesNames());

m_stoichCoeffs.clear();
for (const auto& sp : rxn.reactants) {
m_stoichCoeffs.emplace_back(kin.kineticsSpeciesIndex(sp.first), -sp.second);
}
for (const auto& sp : rxn.products) {
m_stoichCoeffs.emplace_back(kin.kineticsSpeciesIndex(sp.first), sp.second);
}
}

StickingCoverage::StickingCoverage()
Expand Down
11 changes: 9 additions & 2 deletions src/kinetics/ReactionData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,15 @@ bool CoverageData::update(const ThermoPhase& phase, const Kinetics& kin)
logCoverages[n] = std::log(std::max(coverages[n], Tiny));
}
for (size_t n = 0; n < kin.nPhases(); n++) {
kin.thermo(n).getPartialMolarEnthalpies(
partial_molar_enthalpies.data() + kin.kineticsSpeciesIndex(0, n));
size_t start = kin.kineticsSpeciesIndex(0, n);
const auto& ph = kin.thermo(n);
ph.getPartialMolarEnthalpies(partial_molar_enthalpies.data() + start);
ph.getStandardChemPotentials(standardChemPotentials.data() + start);
size_t nsp = ph.nSpecies();
for (size_t k = 0; k < nsp; k++) {
// only used for exchange current density formulation
standardConcentrations[k + start] = ph.standardConcentration(k);
}
}
m_state_mf_number = mf;
changed = true;
Expand Down

0 comments on commit 5cfb693

Please sign in to comment.