17 ElectrodeKinetics::ElectrodeKinetics(
thermo_t* thermo) :
19 metalPhaseIndex_(
npos),
20 solnPhaseIndex_(
npos),
24 "To be removed after Cantera 2.2.");
29 for (
size_t i = 0; i <
rmcVector.size(); i++) {
59 for (
size_t i = 0; i <
rmcVector.size(); i++) {
63 for (
size_t i = 0; i <
m_ii; i++) {
74 return cInterfaceKinetics;
95 for (
size_t iph = 0; iph < np; iph++) {
100 if (eElectron !=
npos) {
101 for (
size_t k = 0; k < nSpecies; k++) {
102 if (tp->
nAtoms(k,eElectron) == 1) {
104 for (
size_t e = 0; e < nElements; e++) {
105 if (tp->
nAtoms(k,e) != 0.0) {
106 if (e != eElectron) {
142 size_t nd = tp.
nDim();
143 if (nd == 3 && nsp > 1) {
144 for (
size_t k = 0; k < nsp; k++) {
145 if (tp.
charge(k) != 0.0) {
147 string ss = tp.
name();
221 for (
size_t iBeta = 0; iBeta <
m_beta.size(); iBeta++) {
229 double beta =
m_beta[iBeta];
236 if (iECDFormulation == 0) {
238 "Straight kfwrd with BUTLERVOLMER_RXN not handled yet");
255 if (nStoichElectrons != 0.0) {
256 OCV =
m_deltaG[irxn]/Faraday/ nStoichElectrons;
267 double nu = voltage - OCV;
274 throw CanteraError(
"ElectrodeKinetics::",
"ROP orders pointer is zero ?!?");
277 const std::vector<size_t>& kinSpeciesIDs = ro_rop->
kinSpeciesIDs_;
279 for (
size_t j = 0; j < kinSpeciesIDs.size(); j++) {
280 size_t k = kinSpeciesIDs[j];
281 double oo = kinSpeciesOrders[j];
295 double ioc =
m_ropf[irxn] * nStoichElectrons;
299 double resist = m_ctrxn_resistivity_[iBeta];
300 double exp1 = nu * nStoichElectrons * beta / rtdf;
301 double exp2 = - nu * nStoichElectrons * (1.0 - beta) / (rtdf);
302 double io = ioc * (exp(exp1) - exp(exp2));
305 io = solveCurrentRes(nu, nStoichElectrons, ioc, beta, TT, resist, 0);
308 m_ropnet[irxn] = io / (Faraday * nStoichElectrons);
313 m_ropf[irxn] = calcForwardROP_BV(irxn, iBeta, ioc, nStoichElectrons, nu, io);
323 double beta =
m_beta[iBeta];
330 if (iECDFormulation == 0) {
332 "Straight kfwrd with BUTLERVOLMER_NOACTIVITYCOEFFS_RXN not handled yet");
347 if (nStoichElectrons != 0.0) {
348 OCV =
m_deltaG[irxn]/Faraday/ nStoichElectrons;
360 double nu = voltage - OCV;
374 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV()",
"forward orders pointer is zero ?!?");
378 const std::vector<size_t>& kinSpeciesIDs = ro_fwd->
kinSpeciesIDs_;
380 for (
size_t j = 0; j < kinSpeciesIDs.size(); j++) {
381 size_t ks = kinSpeciesIDs[j];
384 size_t klocal = ks -
m_start[n];
387 double oo = kinSpeciesOrders[j];
394 double resist = m_ctrxn_resistivity_[iBeta];
395 double exp1 = nu * nStoichElectrons * beta / rtdf;
396 double exp2 = - nu * nStoichElectrons * (1.0 - beta) / (rtdf);
397 double io = ioc * (exp(exp1) - exp(exp2));
399 io = solveCurrentRes(nu, nStoichElectrons, ioc, beta, TT, resist, 0);
402 m_ropnet[irxn] = io / (Faraday * nStoichElectrons);
407 m_ropf[irxn] = calcForwardROP_BV_NoAct(irxn, iBeta, ioc, nStoichElectrons, nu, io);
418 for (
size_t j = 0; j !=
m_ii; ++j) {
428 for (
size_t j = 0; j !=
m_ii; ++j) {
430 for (
size_t p = 0; p <
nPhases(); p++) {
436 for (
size_t rp = 0; rp <
nPhases(); rp++) {
455 for (
size_t p = 0; p <
nPhases(); p++) {
461 for (
size_t rp = 0; rp <
nPhases(); rp++) {
493 void ElectrodeKinetics::determineFwdOrdersBV(
ReactionData& rdata, std::vector<doublereal>& fwdFullorders)
503 double betaf = rdata.
beta;
509 for (
size_t j = 0; j < rdata.
reactants.size(); j++) {
513 fwdFullorders[kkin] += betaf * oo;
514 if (abs(fwdFullorders[kkin]) < 0.00001) {
515 fwdFullorders[kkin] = 0.0;
518 fwdFullorders[kkin] = 0.0;
521 for (
size_t j = 0; j < rdata.
products.size(); j++) {
525 fwdFullorders[kkin] -= betaf * oo;
526 if (abs(fwdFullorders[kkin]) < 0.00001) {
527 fwdFullorders[kkin] = 0.0;
530 fwdFullorders[kkin] = 0.0;
539 double ElectrodeKinetics::calcForwardROP_BV(
size_t irxn,
size_t iBeta,
double ioc,
double nStoich,
double nu, doublereal ioNet)
546 doublereal beta =
m_beta[iBeta];
554 if (!iECDFormulation) {
555 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV",
"not handled yet");
562 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV()",
"forward orders pointer is zero ?!?");
566 const std::vector<size_t>& kinSpeciesIDs = ro_fwd->kinSpeciesIDs_;
567 const std::vector<doublereal>& kinSpeciesOrders = ro_fwd->kinSpeciesOrders_;
568 for (
size_t j = 0; j < kinSpeciesIDs.size(); j++) {
569 size_t k = kinSpeciesIDs[j];
570 double oo = kinSpeciesOrders[j];
575 tmp *= 1.0 / tmp2 / Faraday;
580 double kf = iorc * tmp;
585 kf *= exp(- eamod / rt);
592 for (
size_t j = 0; j < kinSpeciesIDs.size(); j++) {
593 size_t k = kinSpeciesIDs[j];
594 double oo = kinSpeciesOrders[j];
604 double resistivity = m_ctrxn_resistivity_[iBeta];
605 if (fabs(resistivity * ioNet) > fabs(nu)) {
606 ioNet = nu / resistivity;
609 double exp1 = nStoich * Faraday * beta * (nu - resistivity * ioNet)/ (rt);
614 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV",
"ioc should be less than zero here");
617 double exp2 = -nu * nStoich * Faraday * (1.0 - beta) / (rt);
618 iof = ioc * ( - exp(exp2));
620 ropf = iof / ( Faraday * nStoich);
629 double ElectrodeKinetics::calcForwardROP_BV_NoAct(
size_t irxn,
size_t iBeta,
double ioc,
double nStoich,
double nu,
635 doublereal beta =
m_beta[iBeta];
705 double resistivity = m_ctrxn_resistivity_[iBeta];
706 if (fabs(resistivity * ioNet) > fabs(nu)) {
707 ioNet = nu / resistivity;
710 double exp1 = nStoich * Faraday * beta * (nu - resistivity * ioNet)/ (rt);
715 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV_NoAct",
"ioc should be less than zero here");
718 double exp2 = -nu * nStoich * Faraday * (1.0 - beta) / (rt);
719 iof = ioc * ( - exp(exp2));
721 double ropf = iof / ( Faraday * nStoich);
737 if (nStoichElectrons != 0.0) {
738 OCV =
m_deltaG[irxn] / Faraday / nStoichElectrons;
746 bool ElectrodeKinetics::
747 getExchangeCurrentDensityFormulation(
size_t irxn,
748 doublereal& nStoichElectrons, doublereal& OCV, doublereal& io,
749 doublereal& overPotential, doublereal& beta,
750 doublereal& resistivity)
768 nStoichElectrons = 0;
778 if (nStoichElectrons != 0.0) {
779 OCV =
m_deltaG[irxn] / Faraday / nStoichElectrons;
782 for (
size_t i = 0; i <
m_ctrxn.size(); i++) {
799 double iO =
m_rfn[irxn] * m_perturb[irxn];
801 if (! iECDFormulation) {
802 iO =
m_rfn[irxn] * Faraday * nStoichElectrons;
804 double fac = exp(mG0 / (rt));
805 iO *= pow(fac, beta);
808 fac = exp( beta * deltaElectricEnergy_[irxn] / (rt));
812 iO *= nStoichElectrons;
815 double omb = 1.0 - beta;
819 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV()",
"forward orders pointer is zero ?!?");
822 const std::vector<size_t>& kinSpeciesIDs = ro_fwd->kinSpeciesIDs_;
823 const std::vector<doublereal>& kinSpeciesOrders = ro_fwd->kinSpeciesOrders_;
824 for (
size_t j = 0; j < kinSpeciesIDs.size(); j++) {
825 size_t ks = kinSpeciesIDs[j];
828 size_t klocal = ks -
m_start[n];
829 double mfS = th.moleFraction(klocal);
831 double oo = kinSpeciesOrders[j];
838 throw CanteraError(
"ElectrodeKinetics::calcForwardROP_BV()",
"forward orders pointer is zero ?!?");
841 const std::vector<size_t>& kinSpeciesIDs = ro_fwd->kinSpeciesIDs_;
842 const std::vector<doublereal>& kinSpeciesOrders = ro_fwd->kinSpeciesOrders_;
843 for (
size_t j = 0; j < kinSpeciesIDs.size(); j++) {
844 size_t ks = kinSpeciesIDs[j];
846 double oo = kinSpeciesOrders[j];
851 for (
size_t k = 0; k <
m_kk; k++) {
855 if (reactCoeff != 0.0) {
859 if (prodCoeff != 0.0) {
866 resistivity = m_ctrxn_resistivity_[iBeta];
870 double E = phiMetal - phiSoln;
871 overPotential = E - OCV;
876 double ElectrodeKinetics::calcCurrentDensity(
double nu,
double nStoich,
double ioc,
double beta,
double temp,
877 doublereal resistivity)
const
879 double exp1 = nu * nStoich * Faraday * beta / (
GasConstant * temp);
880 double exp2 = -nu * nStoich * Faraday * (1.0 - beta) / (
GasConstant * temp);
881 double val = ioc * (exp(exp1) - exp(exp2));
882 if (resistivity > 0.0) {
883 val = solveCurrentRes(nu, nStoich, ioc, beta, temp, resistivity, 0);
899 for (
size_t i = 0; i <
m_ii; i++) {
906 double ElectrodeKinetics::solveCurrentRes(
double nu,
double nStoich, doublereal ioc, doublereal beta, doublereal temp,
907 doublereal resistivity,
int iprob)
const
910 doublereal f, dfdi, deltai, eexp1, eexp2, exp1, exp2, icurr, deltai_damp;
911 doublereal nFRT = nStoich * Faraday / (
GasConstant * temp);
913 eexp1 = exp(nu * nFRT * beta);
914 eexp2 = exp(-nu * nFRT * (1.0 - beta)) ;
917 eexp1 = exp(nu * nFRT * beta);
920 icurr = ioc * (eexp1 - eexp2);
921 double icurrDamp = icurr;
922 if (fabs(resistivity * icurr) > 0.9 * fabs(nu)) {
923 icurrDamp = 0.9 * nu / resistivity;
926 eexp1 = exp( nFRT * beta * (nu - resistivity * icurrDamp));
927 eexp2 = exp(- nFRT * (1.0 - beta) * (nu - resistivity * icurrDamp));
929 eexp1 = exp( nFRT * beta * (nu - resistivity * icurrDamp));
932 icurr = ioc * (eexp1 - eexp2);
933 if (fabs(resistivity * icurr) > 0.99 * fabs(nu)) {
934 icurr = 0.99 * nu / resistivity;
940 exp1 = nFRT * beta * (nu - resistivity * icurr);
941 exp2 = - nFRT * (1.0 - beta) * (nu - resistivity * icurr);
944 f = icurr - ioc * (eexp1 - eexp2);
945 dfdi = 1.0 - ioc * eexp1 * ( - beta * nFRT * resistivity ) +
946 ioc * eexp2 * ( (1.0 - beta) * nFRT * resistivity );
948 exp1 = nFRT * beta * (nu - resistivity * icurr);
950 f = icurr - ioc * (eexp1);
951 dfdi = 1.0 - ioc * eexp1 * ( - beta * nFRT * resistivity );
954 if (fabs(deltai) > 0.1 * fabs(icurr)) {
955 deltai_damp = 0.1 * deltai;
956 if (fabs(deltai_damp) > 0.1 * fabs(icurr)) {
957 deltai_damp = 0.1 * icurr * (deltai_damp / fabs(deltai_damp));
959 }
else if (fabs(deltai) > 0.01 * fabs(icurr)) {
960 deltai_damp = 0.3 * deltai;
961 }
else if (fabs(deltai) > 0.001 * fabs(icurr)) {
962 deltai_damp = 0.5 * deltai;
964 deltai_damp = deltai;
966 icurr += deltai_damp;
967 if (fabs(resistivity * icurr) > fabs(nu)) {
968 icurr = 0.999 * nu / resistivity;
971 }
while((fabs(deltai/icurr)> 1.0E-14) && (fabs(deltai) > 1.0E-20));
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
StoichManagerN m_revProductStoich
Stoichiometry manager for the products of reversible reactions.
vector_fp m_deltaG0
Vector of delta G^0, the standard state Gibbs free energies for each reaction.
vector_fp m_ropr
Reverse rate-of-progress for each reaction.
std::vector< thermo_t * > m_thermo
m_thermo is a vector of pointers to ThermoPhase objects that are involved with this kinetics operator...
size_t metalPhaseIndex_
Index of the metal phase in the list of phases for this kinetics object. This is the electron phase...
A kinetics manager for heterogeneous reaction mechanisms.
Header for a simple thermodynamics model of a surface phase derived from ThermoPhase, assuming an ideal solution model (see Thermodynamic Properties and class SurfPhase).
size_t nElements() const
Number of elements.
virtual void assignShallowPointers(const std::vector< thermo_t * > &tpVector)
Reassign the pointers within the Kinetics object.
Various templated functions that carry out common vector operations (see Templated Utility Functions)...
thermo_t & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism...
vector_fp forwardFullOrder_
Reaction order for the forward direction of the reaction.
size_t m_kk
The number of species in all of the phases that participate in this kinetics mechanism.
SurfPhase * m_surf
Pointer to the single surface phase.
virtual void finalize()
Finish adding reactions and prepare for use.
std::vector< size_t > m_start
m_start is a vector of integers specifying the beginning position for the species vector for the n'th...
const size_t npos
index returned by functions to indicate "no position"
vector_fp m_phi
Vector of phase electric potentials.
doublereal beta
Forward value of the apparent Electrochemical transfer coefficient.
vector_fp pstoich
Product stoichiometric coefficients, in the order given by products.
vector_fp m_deltaG
Vector of deltaG[] of reaction, the delta Gibbs free energies for each reaction.
vector_fp m_beta
Electrochemical transfer coefficient for the forward direction.
std::vector< size_t > kinSpeciesIDs_
ID's of the kinetic species.
virtual int type() const
Identifies the kinetics manager type.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
std::vector< std::vector< bool > > m_rxnPhaseIsProduct
Vector of vector of booleans indicating whether a phase participates in a reaction as a product...
vector_fp m_StandardConc
Vector of standard concentrations.
void identifyMetalPhase()
Identify the metal phase and the electrons species.
vector_fp m_ropnet
Net rate-of-progress for each reaction.
This file contains definitions for utility functions and text for modules, inputfiles, logs, textlogs, (see Input File Handling, Diagnostic Output, and Writing messages to the screen).
std::vector< RxnMolChange * > rmcVector
Vector of additional information about each reaction.
std::string name() const
Return the name of the phase.
void multiply_each(OutputIter x_begin, OutputIter x_end, InputIter y_begin)
Multiply each entry in x by the corresponding entry in y.
int m_phaseExistsCheck
Int flag to indicate that some phases in the kinetics mechanism are non-existent. ...
virtual void finalize()
Finish adding reactions and prepare for use.
std::vector< double > m_phaseChargeChange
Vector of mass changes for each phase in the Kinetics object due to the current reaction.
vector_fp deltaElectricEnergy_
Storage for the net electric energy change due to reaction.
ThermoPhase thermo_t
typedef for the ThermoPhase class
vector_fp m_ropf
Forward rate-of-progress for each reaction.
Base class for a phase with thermodynamic properties.
std::vector< size_t > products
Indices of product species.
virtual Kinetics * duplMyselfAsKinetics(const std::vector< thermo_t * > &tpVector) const
Duplication function.
vector_int m_ctrxn_ecdf
Vector of booleans indicating whether the charge transfer reaction rate constant is described by an e...
virtual void getDeltaGibbs(doublereal *deltaG)
Return the vector of values for the reaction Gibbs free energy change.
std::vector< RxnOrders * > m_ctrxn_ROPOrdersList_
Vector of booleans indicating whether the charge transfer reaction rate constant is described by an e...
virtual void init()
Prepare the class for the addition of reactions.
vector_fp kinSpeciesOrders_
Orders of the kinetic species.
size_t nPhases() const
The number of phases participating in the reaction mechanism.
A kinetics manager for heterogeneous reaction mechanisms.
double openCircuitVoltage(size_t irxn)
Calculate the open circuit voltage of a given reaction.
ElectrodeKinetics(thermo_t *thermo=0)
Constructor.
std::vector< bool > m_phaseExists
Vector of booleans indicating whether phases exist or not.
vector_fp m_rfn
Forward rate constant for each reaction.
StoichManagerN m_reactantStoich
Stoichiometry manager for the reactants for each reaction.
thermo_t & speciesPhase(const std::string &nm)
This function looks up the name of a species and returns a reference to the ThermoPhase object of the...
void _update_rates_T()
Update properties that depend on temperature.
vector_fp m_actConc
Array of activity concentrations for each species in the kinetics object.
vector_fp m_perturb
Vector of perturbation factors for each reaction's rate of progress vector.
Public interface for kinetics managers.
void _update_rates_C()
Update properties that depend on the species mole fractions and/or concentration,.
Intermediate class which stores data about a reaction and its rate parameterization before adding the...
#define AssertThrow(expr, procedure)
Assertion must be true or an error is thrown.
Base class for exceptions thrown by Cantera classes.
virtual ~ElectrodeKinetics()
Destructor.
std::vector< std::vector< bool > > m_rxnPhaseIsReactant
Vector of vector of booleans indicating whether a phase participates in a reaction as a reactant...
vector_fp m_rkcn
Reciprocal of the equilibrium constant in concentration units.
std::vector< size_t > reactants
Indices of reactant species.
vector_fp rstoich
Reactant stoichiometric coefficients, in the order given by reactants.
size_t nSpecies() const
Returns the number of species in the phase.
ElectrodeKinetics & operator=(const ElectrodeKinetics &right)
Assignment operator.
virtual void init()
Prepare the class for the addition of reactions.
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
doublereal temperature() const
Temperature (K).
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
void updateExchangeCurrentQuantities()
values needed to convert from exchange current density to surface reaction rate.
size_t elementIndex(const std::string &name) const
Return the index of element named 'name'.
size_t speciesPhaseIndex(size_t k)
This function takes as an argument the kineticsSpecies index (i.e., the list index in the list of spe...
std::vector< int > m_phaseIsStable
Vector of int indicating whether phases are stable or not.
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
size_t m_ii
Number of reactions in the mechanism.
std::vector< size_t > m_ctrxn
Vector of reaction indexes specifying the id of the current transfer reactions in the mechanism...
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
const int BUTLERVOLMER_NOACTIVITYCOEFFS_RXN
This is a surface reaction that is formulated using the Butler-Volmer formulation and using concentra...
virtual double reactantStoichCoeff(size_t k, size_t i) const
Stoichiometric coefficient of species k as a reactant in reaction i.
size_t kElectronIndex_
Index of the electrons species in the list of species for this surface kinetics, if none set it to -1...
virtual void updateROP()
Internal routine that updates the Rates of Progress of the reactions.
const int BUTLERVOLMER_RXN
This is a surface reaction that is formulated using the Butler-Volmer formulation.
size_t solnPhaseIndex_
Index of the solution phase in the list of phases for this surface.
Class that includes some bookeeping entries for a reaction or a global reaction defined on a surface...
virtual int reactionType(size_t i) const
Flag specifying the type of reaction.
virtual double productStoichCoeff(size_t k, size_t i) const
Stoichiometric coefficient of species k as a product in reaction i.
InterfaceKinetics & operator=(const InterfaceKinetics &right)
Assignment operator.
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
std::vector< RxnOrders * > m_ctrxn_FwdOrdersList_
Reaction Orders for the case where the forwards rate of progress is being calculated.