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

Partially reversible lithium plating #2043

Merged
merged 25 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
52ecb1b
Added SEI-limited dead lithium function parameter
Apr 21, 2022
0ad843e
Fixed bug in SEI-limited dead lithium function
Apr 21, 2022
c64b7e3
Updated GEM from upstream, then copied into this repo
Apr 27, 2022
ce46e98
Partially reversible plating tested and ready for pull request
Apr 27, 2022
0646725
Updated test_OKane2020.py and added test_OKane2022.py
Apr 27, 2022
336e972
Added dead lithium to porosity submodel
Apr 28, 2022
01692a8
flake8
Apr 28, 2022
cb43346
Modified Chen2020 negative electrode OCP to include stage 1 phase
Apr 28, 2022
4cfa1dc
Merge branch 'develop' of https://github.com/pybamm-team/PyBaMM into GEM
May 3, 2022
390a040
Fixed division by zero check in dead lithium decay rate function
May 3, 2022
92bc862
Changed default SEI to 'constant' to avoid division by zero error
May 3, 2022
15c6599
Updated Chen2020 negative OCP, Ecker2015 positive OCP and Ecker2015 e…
May 4, 2022
30f1556
Merge branch 'develop' of https://github.com/pybamm-team/PyBaMM into …
May 4, 2022
84d6825
Commented function parameter files for credit
May 4, 2022
1d730ae
flake8
May 4, 2022
4067b61
Restored NoSEI as default SEI submodel
May 4, 2022
05db55e
Merge branch 'UpdateParameters' into GEM
May 4, 2022
73e8b9f
Modified base_battery_model.py to change default SEI model to 'consta…
May 4, 2022
ff52db8
Restored Chen2020, ORegan2021 and Ecker2015 OCP functions to original…
Jun 14, 2022
d2b5a0c
Merged latest changes from upstream
Jun 14, 2022
abaf5af
Removed the few remaining references to n_L
Jun 14, 2022
ceb43c1
Removed L_pl_0 from reaction driven porosity so it still works even i…
Jun 15, 2022
5ce79cc
Added 'lithium plating transfer coefficient'=0.7 to yang2017_Li_plati…
Jun 15, 2022
fcd33fa
Added well-posedness tests for partially reversible plating
Jun 15, 2022
ad9e600
Reverted changes to comments in Chen2020 and ORegan2021 negative OCP …
Jun 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 176 additions & 45 deletions examples/notebooks/models/lithium-plating.ipynb

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions pybamm/CITATIONS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,20 @@
journal = {Journal of The Electrochemical Society}
}

@article{OKane2022,
author ="O{'}Kane, Simon E. J. and Ai, Weilong and Madabattula, Ganesh and Alonso-Alvarez, Diego and Timms, Robert and Sulzer, Valentin and Edge, Jacqueline Sophie and Wu, Billy and Offer, Gregory J. and Marinescu, Monica",
title ="Lithium-ion battery degradation: how to model it",
journal ="Phys. Chem. Chem. Phys.",
year ="2022",
volume ="24",
issue ="13",
pages ="7909-7922",
publisher ="The Royal Society of Chemistry",
doi ="10.1039/D2CP00417H",
url ="http://dx.doi.org/10.1039/D2CP00417H",
}


@article{ORegan2021,
author = {O'Regan, Kieran and Brosa Planella, Ferran and Widanage, W. Dhammika and Kendrick, Emma},
title = {{Thermal-electrochemical parametrisation of a lithium-ion battery: mapping Li concentration and temperature dependencies}},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Lithium plating parameters

Some example parameters for lithium plating from the paper:

> O’Kane, S. E. J., Ai, W., Madabattula, G., Alonso-Alvarez, D., Timms, R, Sulzer, V., Edge, J. S., Wu, B., Offer, G. J., & Marinescu, M. (2022) Lithium-ion battery degradation: how to model it. Physical Chemistry: Chemical Physics, accepted.

Note: this parameter set does not claim to be representative of the true parameter values. These are merely the parameter values that were used in the referenced papers.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from pybamm import FullBroadcast, Parameter, Scalar


def SEI_limited_dead_lithium_OKane2022(L_sei):
"""
Decay rate for dead lithium formation [s-1].
References
----------
.. [1] Simon E. J. O'Kane, Weilong Ai, Ganesh Madabattula, Diega Alonso-Alvarez,
Robert Timms, Valentin Sulzer, Jaqueline Sophie Edge, Billy Wu, Gregory J. Offer
and Monica Marinescu. "Lithium-ion battery degradation: how to model it."
Physical Chemistry: Chemical Physics 24, no. 13 (2022): 7909-7922.
Parameters
----------
L_sei : :class:`pybamm.Symbol`
Total SEI thickness [m]
Returns
-------
:class:`pybamm.Symbol`
Dead lithium decay rate [s-1]
"""

gamma_0 = Parameter("Dead lithium decay constant [s-1]")
L_inner_0 = Parameter("Initial inner SEI thickness [m]")
L_outer_0 = Parameter("Initial outer SEI thickness [m]")
L_sei_0 = L_inner_0 + L_outer_0

if L_sei < L_sei_0:
gamma = gamma_0
else:
L_inner_0 = Parameter("Initial inner SEI thickness [m]")
L_outer_0 = Parameter("Initial outer SEI thickness [m]")
L_sei_0 = L_inner_0 + L_outer_0
gamma = gamma_0 * L_sei_0 / L_sei

return gamma
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Name [units],Value,Reference,Notes
,,,
,,,
# Lithium plating parameters,,,
Lithium metal partial molar volume [m3.mol-1],1.30E-05,Yang2017,
Lithium plating kinetic rate constant [m.s-1],1E-9,,
Exchange-current density for plating [A.m-2],[function]plating_exchange_current_density_OKane2020,,
Exchange-current density for stripping [A.m-2],[function]stripping_exchange_current_density_OKane2020,,
Initial plated lithium concentration [mol.m-3],0.00E+00,,
Typical plated lithium concentration [mol.m-3],1000,1 molar,
Lithium stripping transfer coefficient,0.35,,
Lithium plating transfer coefficient,0.65,,
Dead lithium decay constant [s-1],1E-6,,
Dead lithium decay rate [s-1],[function]SEI_limited_dead_lithium_OKane2022,,
valentinsulzer marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from pybamm import constants, Parameter


def plating_exchange_current_density_OKane2020(c_e, c_Li, T):
"""
Exchange-current density for Li plating reaction [A.m-2].
References
----------
.. [1] O’Kane, Simon EJ, Ian D. Campbell, Mohamed WJ Marzook, Gregory J. Offer, and
Monica Marinescu. "Physical origin of the differential voltage minimum associated
with lithium plating in Li-ion batteries." Journal of The Electrochemical Society
167, no. 9 (2020): 090540.
Parameters
----------
c_e : :class:`pybamm.Symbol`
Electrolyte concentration [mol.m-3]
c_Li : :class:`pybamm.Symbol`
Plated lithium concentration [mol.m-3]
T : :class:`pybamm.Symbol`
Temperature [K]
Returns
-------
:class:`pybamm.Symbol`
Exchange-current density [A.m-2]
"""

k_plating = Parameter("Lithium plating kinetic rate constant [m.s-1]")

return constants.F * k_plating * c_e
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from pybamm import constants, Parameter


def stripping_exchange_current_density_OKane2020(c_e, c_Li, T):
"""
Exchange-current density for Li stripping reaction [A.m-2].

References
----------

.. [1] O’Kane, Simon EJ, Ian D. Campbell, Mohamed WJ Marzook, Gregory J. Offer, and
Monica Marinescu. "Physical origin of the differential voltage minimum associated
with lithium plating in Li-ion batteries." Journal of The Electrochemical Society
167, no. 9 (2020): 090540.

Parameters
----------

c_e : :class:`pybamm.Symbol`
Electrolyte concentration [mol.m-3]
c_Li : :class:`pybamm.Symbol`
Plated lithium concentration [mol.m-3]
T : :class:`pybamm.Symbol`
Temperature [K]

Returns
-------

:class:`pybamm.Symbol`
Exchange-current density [A.m-2]
"""

k_plating = Parameter("Lithium plating kinetic rate constant [m.s-1]")

return constants.F * k_plating * c_Li
9 changes: 7 additions & 2 deletions pybamm/models/full_battery_models/base_battery_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class BatteryModelOptions(pybamm.FuzzyDict):
Can be "full" (default), "constant", or "current-driven".
* "lithium plating" : str
Sets the model for lithium plating. Can be "none" (default),
"reversible" or "irreversible".
"reversible", "partially reversible", or "irreversible".
* "loss of active material" : str
Sets the model for loss of active material. Can be "none" (default),
"stress-driven", "reaction-driven", or "stress and reaction-driven".
Expand Down Expand Up @@ -198,7 +198,12 @@ def __init__(self, extra_options):
"Marcus-Hush-Chidsey",
],
"interface utilisation": ["full", "constant", "current-driven"],
"lithium plating": ["none", "reversible", "irreversible"],
"lithium plating": [
"none",
"reversible",
"partially reversible",
"irreversible",
],
"lithium plating porosity change": ["false", "true"],
"loss of active material": [
"none",
Expand Down
29 changes: 22 additions & 7 deletions pybamm/models/submodels/interface/lithium_plating/base_plating.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ class BasePlating(BaseInterface):
.. [1] SEJ O'Kane, ID Campbell, MWJ Marzook, GJ Offer and M Marinescu. "Physical
Origin of the Differential Voltage Minimum Associated with Li Plating in
Lithium-Ion Batteries". Journal of The Electrochemical Society,
167:090540, 2019
167:090540, 2020
.. [2] SEJ O'Kane, W Ai, G Madabattula, D Alonso-Alvarez, R Timms, V Sulzer,
JS Edge, B Wu, GJ Offer and M Marinescu. "Lithium-ion battery degradation:
how to model it". Physical Chemistry: Chemical Physics, 24:7909, 2022

**Extends:** :class:`pybamm.interface.BaseInterface`
"""
Expand Down Expand Up @@ -53,7 +56,7 @@ def get_coupled_variables(self, variables):

return variables

def _get_standard_concentration_variables(self, c_plated_Li):
def _get_standard_concentration_variables(self, c_plated_Li, c_dead_Li):
"""
A private function to obtain the standard variables which
can be derived from the local plated lithium concentration.
Expand Down Expand Up @@ -82,20 +85,32 @@ def _get_standard_concentration_variables(self, c_plated_Li):
L_plated_Li_av = pybamm.x_average(L_plated_Li)
Q_plated_Li = c_plated_Li_av * param.L_n * param.L_y * param.L_z

c_dead_Li_av = pybamm.x_average(c_dead_Li)
L_dead_Li = c_dead_Li # dead Li "thickness", required by porosity submodel
L_dead_Li_av = pybamm.x_average(L_dead_Li)
Q_dead_Li = c_dead_Li_av * param.L_n * param.L_y * param.L_z

variables = {
"Lithium plating concentration": c_plated_Li,
"Lithium plating concentration [mol.m-3]": c_plated_Li * c_scale,
"X-averaged lithium plating concentration": c_plated_Li_av,
"X-averaged lithium plating concentration"
" [mol.m-3]": c_plated_Li_av * c_scale,
"Dead lithium concentration": c_dead_Li,
"Dead lithium concentration [mol.m-3]": c_dead_Li * c_scale,
"X-averaged dead lithium concentration": c_dead_Li_av,
"X-averaged dead lithium concentration"
" [mol.m-3]": c_dead_Li_av * c_scale,
"Lithium plating thickness": L_plated_Li,
"Lithium plating thickness [m]": L_plated_Li * L_scale,
"X-averaged lithium plating thickness [m]": L_plated_Li_av * L_scale,
"Loss of lithium to lithium plating [mol]": Q_plated_Li * c_scale,
"Loss of capacity to lithium plating [A.h]": Q_plated_Li
* c_scale
* param.F
/ 3600,
"Dead lithium thickness": L_dead_Li,
"Dead lithium thickness [m]": L_dead_Li * L_scale,
"X-averaged dead lithium thickness [m]": L_dead_Li_av * L_scale,
"Loss of lithium to lithium plating [mol]": (Q_plated_Li + Q_dead_Li)
* c_scale,
"Loss of capacity to lithium plating [A.h]":
(Q_plated_Li + Q_dead_Li) * c_scale * param.F / 3600,
}

return variables
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_fundamental_variables(self):
zero = pybamm.FullBroadcast(
pybamm.Scalar(0), "negative electrode", "current collector"
)
variables = self._get_standard_concentration_variables(zero)
variables = self._get_standard_concentration_variables(zero, zero)
variables.update(self._get_standard_overpotential_variables(zero))
variables.update(self._get_standard_reaction_variables(zero))
return variables
Expand Down
58 changes: 47 additions & 11 deletions pybamm/models/submodels/interface/lithium_plating/plating.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ class Plating(BasePlating):
.. [1] SEJ O'Kane, ID Campbell, MWJ Marzook, GJ Offer and M Marinescu. "Physical
Origin of the Differential Voltage Minimum Associated with Li Plating in
Lithium-Ion Batteries". Journal of The Electrochemical Society,
167:090540, 2019
167:090540, 2020
.. [2] SEJ O'Kane, W Ai, G Madabattula, D Alonso-Alvarez, R Timms, V Sulzer,
JS Edge, B Wu, GJ Offer and M Marinescu. "Lithium-ion battery degradation:
how to model it". Physical Chemistry: Chemical Physics, 24:7909, 2022

**Extends:** :class:`pybamm.lithium_plating.BasePlating`
"""
Expand All @@ -31,6 +34,7 @@ def __init__(self, param, x_average, options):
super().__init__(param, options)
self.x_average = x_average
pybamm.citations.register("OKane2020")
pybamm.citations.register("OKane2022")

def get_fundamental_variables(self):
if self.x_average is True:
Expand All @@ -39,14 +43,24 @@ def get_fundamental_variables(self):
domain="current collector",
)
c_plated_Li = pybamm.PrimaryBroadcast(c_plated_Li_av, "negative electrode")
c_dead_Li_av = pybamm.Variable(
"X-averaged dead lithium concentration",
domain="current collector",
)
c_dead_Li = pybamm.PrimaryBroadcast(c_dead_Li_av, "negative electrode")
else:
c_plated_Li = pybamm.Variable(
"Lithium plating concentration",
domain="negative electrode",
auxiliary_domains={"secondary": "current collector"},
)
c_dead_Li = pybamm.Variable(
"Dead lithium concentration",
domain="negative electrode",
auxiliary_domains={"secondary": "current collector"},
)

variables = self._get_standard_concentration_variables(c_plated_Li)
variables = self._get_standard_concentration_variables(c_plated_Li, c_dead_Li)

return variables

Expand All @@ -59,20 +73,26 @@ def get_coupled_variables(self, variables):
c_plated_Li = variables["Lithium plating concentration"]
j0_stripping = param.j0_stripping(c_e_n, c_plated_Li, T)
j0_plating = param.j0_plating(c_e_n, c_plated_Li, T)
# phi_ref is part of the de-dimensionalization used in PyBaMM
phi_ref = param.U_n_ref / param.potential_scale

eta_stripping = delta_phi + phi_ref + eta_sei
eta_plating = -eta_stripping
prefactor = 1 / (2 * (1 + self.param.Theta * T))
prefactor = 1 / (1 + self.param.Theta * T)
# NEW: transfer coefficients can be set by the user
alpha_stripping = self.param.alpha_stripping
alpha_plating = self.param.alpha_stripping
valentinsulzer marked this conversation as resolved.
Show resolved Hide resolved

if self.options["lithium plating"] == "reversible":
if self.options["lithium plating"] in ["reversible", "partially reversible"]:
j_stripping = j0_stripping * pybamm.exp(
prefactor * eta_stripping
) - j0_plating * pybamm.exp(prefactor * eta_plating)
prefactor * alpha_stripping * eta_stripping
) - j0_plating * pybamm.exp(prefactor * alpha_plating * eta_plating)
elif self.options["lithium plating"] == "irreversible":
# j_stripping is always negative, because there is no stripping, only
# plating
j_stripping = -j0_plating * pybamm.exp(prefactor * eta_plating)
j_stripping = -j0_plating * pybamm.exp(
prefactor * alpha_plating * eta_plating
)

variables.update(self._get_standard_overpotential_variables(eta_stripping))
variables.update(self._get_standard_reaction_variables(j_stripping))
Expand All @@ -85,26 +105,42 @@ def get_coupled_variables(self, variables):
def set_rhs(self, variables):
if self.x_average is True:
c_plated_Li = variables["X-averaged lithium plating concentration"]
c_dead_Li = variables["X-averaged dead lithium concentration"]
j_stripping = variables[
"X-averaged lithium plating interfacial current density"
]
# Note a is dimensionless (has a constant value of 1 if the surface
# area does not change)
a = variables["X-averaged negative electrode surface area to volume ratio"]
L_sei = variables["X-averaged total SEI thickness"]
else:
c_plated_Li = variables["Lithium plating concentration"]
c_dead_Li = variables["Dead lithium concentration"]
j_stripping = variables["Lithium plating interfacial current density"]
a = variables["Negative electrode surface area to volume ratio"]
L_sei = variables["Total SEI thickness"]

Gamma_plating = self.param.Gamma_plating
# In the partially reversible plating model, coupling term turns reversible
# lithium into dead lithium. In other plating models, it is zero.
if self.options["lithium plating"] == "partially reversible":
dead_lithium_decay_rate = self.param.dead_lithium_decay_rate(L_sei)
coupling_term = dead_lithium_decay_rate * c_plated_Li
else:
zero = pybamm.Scalar(0)
coupling_term = zero
valentinsulzer marked this conversation as resolved.
Show resolved Hide resolved

self.rhs = {c_plated_Li: -Gamma_plating * a * j_stripping}
self.rhs = {
c_plated_Li: -Gamma_plating * a * j_stripping - coupling_term,
c_dead_Li: coupling_term
}

def set_initial_conditions(self, variables):
if self.x_average is True:
c_plated_Li = variables["X-averaged lithium plating concentration"]
c_dead_Li = variables["X-averaged dead lithium concentration"]
else:
c_plated_Li = variables["Lithium plating concentration"]
c_dead_Li = variables["Dead lithium concentration"]
c_plated_Li_0 = self.param.c_plated_Li_0
zero = pybamm.Scalar(0)

self.initial_conditions = {c_plated_Li: c_plated_Li_0}
self.initial_conditions = {c_plated_Li: c_plated_Li_0, c_dead_Li: zero}
4 changes: 3 additions & 1 deletion pybamm/models/submodels/porosity/reaction_driven_porosity.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ def __init__(self, param, options, x_average):
def get_coupled_variables(self, variables):
L_sei_n = variables["Total SEI thickness [m]"]
L_sei_0 = self.param.L_inner_0_dim + self.param.L_outer_0_dim
L_pl_0 = self.param.c_plated_Li_0_dim
L_pl_n = variables["Lithium plating thickness [m]"]
L_dead_n = variables["Dead lithium thickness [m]"]

L_tot = (L_sei_n - L_sei_0) + L_pl_n
L_tot = (L_sei_n - L_sei_0) + (L_pl_n - L_pl_0) + L_dead_n

a_n = variables["Negative electrode surface area to volume ratio [m-1]"]

Expand Down
Loading