Repository: PMEAL/OpenPNM
Pull request #2316 (2022-01-31 18:46:44)

Correcting BV formulations
This PR closes  #2290.


Patch:
diff --git a/CITATION.cff b/CITATION.cff
deleted file mode 100644
index 5b81808d8..000000000
--- a/CITATION.cff
+++ /dev/null
@@ -1,42 +0,0 @@
-cff-version: 1.2.0
-message: "If you use this software, please cite it as below."
-authors:
-- family-names: "Gostick"
-  given-names: "Jeff"
-  orcid: "https://orcid.org/0000-0001-7736-7124"
-title: "OpenPNM"
-url: "https://github.com/PMEAL/OpenPNM"
-preferred-citation:
-  type: article
-  authors:
-  - family-names: "Gostick"
-    given-names: "Jeff"
-    orcid: "https://orcid.org/0000-0001-7736-7124"
-  - family-names: "Aghighi"
-    given-names: "Mahmoudreza"
-  - family-names: "Hinebaugh"
-    given-names: "James"
-  - family-names: "Tranter"
-    given-names: "Tom"
-  - family-names: "Hoeh"
-    given-names: "Michael A."
-  - family-names: "Day"
-    given-names: "Harold"
-  - family-names: "Spellacy"
-    given-names: "Brennan"
-  - family-names: "Sharqawy"
-    given-names: "Mostafa H."
-  - family-names: "Bazylak"
-    given-names: "Aimy"
-  - family-names: "Burns"
-    given-names: "Lehnert"
-  - family-names: "Werner"
-    given-names: "Harold"
-  - family-names: "Putz"
-    given-names: "Andreas"
-  doi: "10.1109/MCSE.2016.49"
-  journal: "Computing in Science & Engineering"
-  start: 60 # First page number
-  end: 74 # Last page number
-  title: "OpenPNM: a pore network modeling package"
-  year: 2016
diff --git a/openpnm/__version__.py b/openpnm/__version__.py
index feba75fa2..b025be614 100644
--- a/openpnm/__version__.py
+++ b/openpnm/__version__.py
@@ -1,1 +1,1 @@
-__version__ = '2.8.2.dev18'
+__version__ = '2.8.2.dev15'
diff --git a/openpnm/models/physics/source_terms.py b/openpnm/models/physics/source_terms.py
index 569caef7a..dfb153b0d 100644
--- a/openpnm/models/physics/source_terms.py
+++ b/openpnm/models/physics/source_terms.py
@@ -560,7 +560,7 @@ def general_symbolic(target, eqn, x, **kwargs):
 
 @_doctxt
 def butler_volmer_conc(
-    target, X, z, j0, c_ref, alpha_anode, alpha_cathode,
+    target, X, z, j0, c_ref, alpha_anode, alpha_cathode, z_rds=1,
     reaction_order=1,
     temperature="pore.temperature",
     reaction_area="pore.reaction_area",
@@ -589,6 +589,8 @@ def butler_volmer_conc(
         Anodic transfer coefficient.
     alpha_cathode : float
         Cathodic transfer coefficient.
+    z_rds : float
+        Number of electrons transferred in the rate determining step.
     reaction_order : float
         Reaction order, i.e. the exponent of the concentration term
     solid_voltage : str
@@ -626,10 +628,10 @@ def butler_volmer_conc(
     number of electrons transferred and F is the Faraday's constant.
 
     .. math::
-        r = j_0 A_{rxn} (\frac{ X }{ c_{ref} }) ^ {\nu}
+        r =  j_0 A_{rxn} (\frac{ 1 }{ z F })(\frac{ X }{ c_{ref} }) ^ {\nu}
         \Big(
-            \exp(  \frac{\alpha_a z F}{RT} \eta )
-          - \exp( -\frac{\alpha_c z F}{RT} \eta )
+            \exp(  \frac{\alpha_a z_{rds} F}{RT} \eta )
+          - \exp( -\frac{\alpha_c z_{rds} F}{RT} \eta )
         \Big)
 
     where:
@@ -645,6 +647,9 @@ def butler_volmer_conc(
 
     .. math::
         rate = S_{1} X + S_{2}
+    
+    Reference: Rahn, Christopher D. Wang, Chao-Yang. (2013). Battery Systems Engineering - 
+    3.2.1 The Butler-Volmer Equation. (pp. 27). John Wiley & Sons.
 
     """
     network = target.project.network
@@ -665,8 +670,8 @@ def butler_volmer_conc(
     # Linearize with respect to X (electrolyte concentration)
     eta = Vs - Ve - Voc
     cte = j0 * A_rxn / (z * F)
-    m1 = alpha_anode * z * F / (R * T)
-    m2 = alpha_cathode * z * F / (R * T)
+    m1 = alpha_anode * z_rds * F / (R * T)
+    m2 = alpha_cathode * z_rds * F / (R * T)
     fV = _np.exp(m1 * eta) - _np.exp(-m2 * eta)
     fC = (X / c_ref)**nu
     r = cte * fC * fV
@@ -679,7 +684,7 @@ def butler_volmer_conc(
 
 
 def butler_volmer_voltage(
-    target, X, z, j0, c_ref, alpha_anode, alpha_cathode,
+    target, X, z, j0, c_ref, alpha_anode, alpha_cathode, z_rds=1,
     reaction_order=1,
     temperature="pore.temperature",
     reaction_area="pore.reaction_area",
@@ -708,6 +713,8 @@ def butler_volmer_voltage(
         Anodic transfer coefficient.
     alpha_cathode : float
         Cathodic transfer coefficient.
+    z_rds : float
+        Number of electrons transferred in the rate determining step.
     electrolyte_concentration : str
         The dictionary key of the electrolyte concentrations [mol/m^3].
     reaction_order : float
@@ -749,8 +756,8 @@ def butler_volmer_voltage(
     .. math::
         r = j_0 A_{rxn} (\frac{ c }{ c_{ref} }) ^ {\nu}
         \Big(
-            \exp(  \frac{\alpha_a z F}{RT} \eta )
-          - \exp( -\frac{\alpha_c z F}{RT} \eta )
+            \exp(  \frac{\alpha_a z_{rds} F}{RT} \eta )
+          - \exp( -\frac{\alpha_c z_{rds} F}{RT} \eta )
         \Big)
 
     where:
@@ -766,7 +773,9 @@ def butler_volmer_voltage(
 
     .. math::
         rate = S_{1} X + S_{2}
-
+    
+    Reference: Rahn, Christopher D. Wang, Chao-Yang. (2013). Battery Systems Engineering - 
+    3.2.1 The Butler-Volmer Equation. (pp. 27). John Wiley & Sons.
     """
     network = target.project.network
     domain = target._domain
@@ -786,8 +795,8 @@ def butler_volmer_voltage(
     # Linearize with respect to X (electrolyte voltage)
     eta = Vs - X - Voc
     cte = j0 * A_rxn
-    m1 = alpha_anode * z * F / (R * T)
-    m2 = alpha_cathode * z * F / (R * T)
+    m1 = alpha_anode * z_rds * F / (R * T)
+    m2 = alpha_cathode * z_rds * F / (R * T)
     fV = _np.exp(m1 * eta) - _np.exp(-m2 * eta)
     dfVdV = -(m1 * _np.exp(m1 * eta) + m2 * _np.exp(-m2 * eta))
     fC = (c / c_ref)**nu
diff --git a/setup.cfg b/setup.cfg
index 8e52e875c..9bbad9a6a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 2.8.2.dev18
+current_version = 2.8.2.dev15
 parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>.*)(?P<build>\d+))?
 serialize = {major}.{minor}.{patch}.{release}{build}
 


Test patch:
diff --git a/tests/unit/models/physics/GenericSourceTermTest.py b/tests/unit/models/physics/GenericSourceTermTest.py
index 275f3e598..07168168c 100644
--- a/tests/unit/models/physics/GenericSourceTermTest.py
+++ b/tests/unit/models/physics/GenericSourceTermTest.py
@@ -274,15 +274,15 @@ class GenericSourceTermTest:
         rate_BV_c = self.phys["pore.rxn_BV_c.rate"]
         eps = np.finfo(float).eps * np.abs(rate_BV_c).max()
         assert_allclose(S2_BV_c.mean(), 0, atol=eps)
-        assert_allclose(S1_BV_c.mean(), -0.06977055)
-        assert_allclose(rate_BV_c.mean(), -0.03541646)
+        assert_allclose(S1_BV_c.mean(), -2.744732328358524e-10)
+        assert_allclose(rate_BV_c.mean(), -1.2661585976335576e-10)
         # Check Butler-Volmer model (voltage)
         S1_BV_v = self.phys["pore.rxn_BV_v.S1"]
         S2_BV_v = self.phys["pore.rxn_BV_v.S2"]
         rate_BV_v = self.phys["pore.rxn_BV_v.rate"]
-        assert_allclose(S2_BV_v.mean(), 226884.32)
-        assert_allclose(S1_BV_v.mean(), -1277463.52)
-        assert_allclose(rate_BV_v.mean(), -13668.675)
+        assert_allclose(S2_BV_v.mean(), 0.00012658874867221232)
+        assert_allclose(S1_BV_v.mean(), -0.0011423824344684425)
+        assert_allclose(rate_BV_v.mean(), -4.886629312370691e-05)
         # The two Butler-Volmer models must only differ by z*F (unit conversion)
         assert_allclose(rate_BV_v, rate_BV_c * BV_params["z"] * 96485.33212)