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

Discuss deprecating Butler-Volmer reaction types #749

Closed
bryanwweber opened this issue Nov 12, 2019 · 14 comments
Closed

Discuss deprecating Butler-Volmer reaction types #749

bryanwweber opened this issue Nov 12, 2019 · 14 comments
Labels
discussion Topics that are being discussed Input Input parsing and conversion (for example, ck2yaml) Kinetics

Comments

@bryanwweber
Copy link
Member

In Reaction.cpp, there is a bit of processing of the XML reaction entry to extract the specific type of an electrochemical reaction:

// Fix reaction_type for some specialized reaction types
std::string type = toLowerCopy(rxn_node["type"]);
if (type == "butlervolmer") {
R.reaction_type = BUTLERVOLMER_RXN;
} else if (type == "butlervolmer_noactivitycoeffs") {
R.reaction_type = BUTLERVOLMER_NOACTIVITYCOEFFS_RXN;
} else if (type == "surfaceaffinity") {
R.reaction_type = SURFACEAFFINITY_RXN;
} else if (type == "global") {
R.reaction_type = GLOBAL_RXN;
}

I believe a relevant XML reaction entry should look like

<reaction ... type="butlervolmer">
...
</reaction>

and similar for the other types in the C++ code. @decaluwe has suggested that the current method of specifying these reaction rate formalisms in the XML is somewhat tortured and should possibly be replaced, especially with the move to YAML input. There are currently no XML files in the Cantera repo that exercise the functionality present in the code snippet above, so there is no guarantee that they work as advertised.

I'm creating this issue to start the discussion about possibly deprecating and re-implementing (as necessary) these reaction rate types.

@bryanwweber bryanwweber added Input Input parsing and conversion (for example, ck2yaml) Kinetics labels Nov 12, 2019
@bryanwweber
Copy link
Member Author

Also related to #747 and #748

@bryanwweber bryanwweber added the discussion Topics that are being discussed label Nov 12, 2019
@ischoegl
Copy link
Member

ischoegl commented Nov 12, 2019

I'd be happy to hear input on this, as the current YAML syntax is not easily extendable (see #747). Reaction factories as envisioned by PR #745 would provide a fairly simple pathway of allowing for integration of additional reaction types (that do not depend on the tortured magic number solution that was mentioned).

PS: any existing XML files for additional electrochemical reaction definitions would be beneficial. From what I can tell, there are at least three different behaviors implemented (and accessible via XML), some of which are currently not reachable via YAML.

//! Vector of Reactions which follow the Butler-Volmer methodology for specifying the
//! exchange current density first. Then, the other forms are specified based on this form.
/*!
* Length is equal to the number of reactions with charge transfer coefficients, m_ctrxn[]
*
* m_ctrxn_BVform[i] = 0; This means that the irxn reaction is calculated via the standard forward
* and reverse reaction rates
* m_ctrxn_BVform[i] = 1; This means that the irxn reaction is calculated via the BV format
* directly.
* m_ctrxn_BVform[i] = 2; this means that the irxn reaction is calculated via the BV format
* directly, using concentrations instead of activity concentrations.
*/
std::vector<size_t> m_ctrxn_BVform;
//! Vector of booleans indicating whether the charge transfer reaction rate constant
//! is described by an exchange current density rate constant expression
/*!
* Length is equal to the number of reactions with charge transfer coefficients, m_ctrxn[]
*
* m_ctrxn_ecdf[irxn] = 0 This means that the rate coefficient calculator will calculate
* 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.
*/
vector_int m_ctrxn_ecdf;

@speth
Copy link
Member

speth commented Nov 12, 2019

I think some of the more complex electrochemical reaction stuff is an incomplete stub. I believe that there are actually implementation issues that prevent most if not all of it from being used at present (for both 2.4.0 and the current master branch) due to two mutually-exclusive conditions: (a) we don't currently allow reactant orders to be specified for reversible reactions and (b) Butler-Volmer reactions are required to be reversible and involve manipulating the reaction orders. As a result, I didn't implement most of this in the YAML format since there wasn't anything that I could test (let alone an existing XML input file). At this point, I think most of this could probably be removed without even needing to be deprecated first.

@ischoegl
Copy link
Member

ischoegl commented Nov 12, 2019

@speth ... not surprised based on what I had seen; I have not spent sufficient time trying to understand what was done or required internally, so thanks for providing context!

Still, the current YAML detection completely omits a type, which will make it hard to add things back in if they're required at a later point.

Regarding XML, a simple search for 'cantera' + 'volmer' + 'xml' produced this intro by Harry Moffat ... from where I extracted liquid_electrode.xml (it apparently doesn't specify the expected XML reaction types) ... The XML loads, but I'm not sure that I want to recreate the example to see whether it actually works. Not sure that I want to take this on (there is ample documentation though)

@bryanwweber
Copy link
Member Author

@ischoegl The "butlervolmer" and related reaction types in the C++ above don't appear in that XML file, so it wouldn't function as a test of these specific capabilities 🙁

In terms of adding these into the YAML format in the future, @decaluwe pointed out that these are not so much reaction types as they are reaction rate coefficient types, analogous to Arrhenius, Troe, et al. (at least to my rudimentary understanding). So that might help inform how they are specified in the future. Nonetheless, I'd rather not get into discussion of the type field in this issue, since that has its own issue.

For my purposes in #693, I'm planning to issue a warning if these reaction types are encountered and omit them from the YAML output.

@ischoegl
Copy link
Member

ischoegl commented Nov 12, 2019

@bryanwweber / @decaluwe ... yes, these are reaction rate related, but this is not necessarily a reason to create a hierarchy as done for falloff. Having a flat structure is imho much simpler to maintain down the line ... note that I make this distinction from the viewpoint of implementation, not in terms of what those reactions stand for.

@decaluwe
Copy link
Member

decaluwe commented Nov 12, 2019 via email

@speth
Copy link
Member

speth commented Nov 12, 2019

@bryanwweber, I think that sounds like a fine path forward for implementing the XML to YAML converter.

I've made PR #750 implementing the suggestion to deprecate these reaction types, with the expectation of re-implementing them in a later release.

@decaluwe
Copy link
Member

decaluwe commented Nov 24, 2019

Okay, I'm finally done writing up my thoughts. Sorry it took a while, I took a couple days going down a rabbit hole, in a directlion that ultimately proved more complex than I had anticipated.

See attached - the first 6 pages cover some of the underlying theory. They're based on some lecture notes from my e-chem class, with as much of the pedantry as possible stripped out (but n > 0, still. Fair warning).

If you just want to skip to my thoughts on Cantera implementation and backfill knowledge as needed, start at the top of page 7.

Charge Transfer in Cantera.pdf

@ischoegl
Copy link
Member

@decaluwe ... great to have a write-up for this! Regarding your thoughts about implementation, I copied the bulk of your comments below:

We currently provide the following means of indicating an electrochemical reaction:

  • Specify a β value
  • Provide an i◦ value.
  • In the absence of either of these, the reaction string is parsed to automatically detect a charge-transfer reaction.
  • I. Schoegl has suggested that we add some type of flag.
    It think this is a good idea, but should be optional, on the user end. Correctly
    evaluating the reaction driving forces is not a ‘special feature’ that a user needs to
    request, imho.
    But the larger question of when to parse the equation strings and when/how to mark
    an ‘electrochemical’ reaction is worth evaluating. At present we parse all surface
    reaction equation strings twice. Can we shift the labeling of echem reactions in some
    way such that this designation is made during the ‘main’ reaction string parsing?
    It would be nice.

I think with the introduction of YAML, there's a chance to implement a clean interface where duplicate parsing of reaction strings for surface reactions can be avoided. For electrochemical reactions, there's no obvious way for the parser to detect the presence of charge-transfer without knowing what the species are (which is read in a different YAML section). Hence my suggestion to clearly label those reactions with a mandatory flag electrochemical (see #747)

Regarding a potential shift of 'labeling' of reactions to a later point during parsing, there's the issue that in the current implementation a dedicated object for a reaction type is created first, and filled with XML/YAML node specific information later. Imho, by far the simplest approach is to consistently label all reactions that deviate from the default.

I do see that there is a benefit to comparing a reaction string to the species list before the reaction object is instantiated (errors for inconsistent input could be raised earlier etc.), but I wouldn't advocate for this change until after CTML-specific code is removed from the code base.

@bryanwweber
Copy link
Member Author

consistently label all reactions that deviate from the default.

While I don't disagree with "explicit is better than implicit" in general, the problem with this approach is that the "default" varies by field. In combustion, we expect Arrhenius reactions to be the default. In electrochemistry work, I imagine they expect electrochemical reactions to be the default, so why should a special flag be mandatory? I think an optional flag for clarity could be allowed, but I think the mild complexity and inefficiency is worth the simplified user experience.

@ischoegl
Copy link
Member

ischoegl commented Nov 28, 2019

@bryanwweber It is true that we're all rooted in our areas! Anyhow, for a bulk phase (dim=3) the default would be ElementaryReaction whereas for a surface phase (dim=2) it would be InterfaceReaction. From a (new) user perspective, a type identifier for anything else would not necessarily be detrimental.

I was suggesting the explicit identification due to the current approach where some duplication is necessary. There certainly are benefits to @decaluwe's suggestion of parsing reaction strings earlier in general (i.e. prior to the creation of the C++ objects). I'd advocate for that change if no explicit type string is used in the YAML specification.

PS: Thinking about it, this is a minor detail; duplicate parsing of surface reactions can likely be avoided by other means. Will close #747 as this was the last sticking point.

@wbessler
Copy link
Contributor

Dear all,

this is Wolfgang Bessler from Offenburg/Germany. I am an electrochemist, long-term user of Cantera (stayed with Dave Goodwin for a couple of months in 2006), contributed to its Li-ion battery functionality, and follow your development activities (big thanks for the good work). Concerning electrochemical reactions:

  1. For elementary reactions (“Marcus Theory”): A thermochemical surface reaction is really a special case of a charge-transfer reaction, where all species are uncharged. Calculation of equilibrium constants and rate constants for charge-transfer reactions always involve the species charge z_k. If all z_k = 0, it falls back to the “standard” expressions for thermochemical surface reactions. The species charges z_k are actually already part of the species class and filled by parsing for the “E” species. Therefore, other than for computational efficiency reasons, there is really no need for flagging or additional parsing at all. The implementation could be generalized for charge-transfer reactions, which will then automatically also be applicable to thermochemical reactions.

  2. Again, for elementary reactions, a Butler-Volmer type kinetics is already possible via the “rate_coeff_type = "exchangecurrentdensity"” flag in the surface_reaction and edge_reaction types. It converts the standard pre-exponential factor from a Butler-Volmer exchange current density and therefore reflects the fact that, for elementary reactions, Butler-Volmer is a rate coefficient type rather than a reaction type, as already pointed out by @bryanwweber .

  3. Still, as @decaluwe has nicely described in his document, there are many flavors of Butler-Volmer used in the electrochemistry community, often representing a global electrode reaction with empirical reaction orders and symmetry factors. I would advocate for an own, separate reaction type here for two reasons. Firstly, these special cases cannot be handeled by the generalized Marcus Theory mentioned above. Secondly, a Butler-Volmer reaction type adapted to the specific habits (and terminology) of electrochemists would open up Cantera to that whole large community. It would make sense to have also Marcus Theory type charge-transfer kinetics be possbile through this reaction type.

  4. I fully agree with deprecating the currently-implemented “Butler-Volmer” flags. I tried them a few years ago, they were neither well-documented, nor available on the CTI level, nor did they work properly. Instead, I suggest to re-implement in a clear and useful way.

@speth
Copy link
Member

speth commented Feb 23, 2020

Since the original topic of this issue was resolved by #750, I've tried to summarize the broader questions raised here in Cantera/enhancements#38, and would like to suggest that as the thread for any additional discussion about how electrochemical rates are handled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Topics that are being discussed Input Input parsing and conversion (for example, ck2yaml) Kinetics
Projects
None yet
Development

No branches or pull requests

5 participants