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

Asymmetric SEI reaction #2425

Merged
merged 11 commits into from
Nov 4, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Features

- SEI reactions can now be asymmetric ([#2425](https://github.com/pybamm-team/PyBaMM/pull/2425))
- Third-party parameter sets can be added by registering entry points to `pybamm_parameter_set` ([#2396](https://github.com/pybamm-team/PyBaMM/pull/2396))
- Added three-dimensional interpolation ([#2380](https://github.com/pybamm-team/PyBaMM/pull/2380))

Expand Down
4 changes: 4 additions & 0 deletions benchmarks/different_model_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ class TimeBuildModelSEI:
"none",
"constant",
"reaction limited",
"reaction limited (asymmetric)",
"solvent-diffusion limited",
"electron-migration limited",
"interstitial-diffusion limited",
"ec reaction limited",
"ec reaction limited (asymmetric)",
],
)

Expand All @@ -143,10 +145,12 @@ class TimeSolveSEI:
"none",
"constant",
"reaction limited",
"reaction limited (asymmetric)",
"solvent-diffusion limited",
"electron-migration limited",
"interstitial-diffusion limited",
"ec reaction limited",
"ec reaction limited (asymmetric)",
],
)

Expand Down
6 changes: 4 additions & 2 deletions examples/scripts/calendar_ageing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
pb.lithium_ion.SPM({"SEI": "reaction limited"}),
pb.lithium_ion.SPMe({"SEI": "reaction limited"}),
pb.lithium_ion.SPM(
{"SEI": "reaction limited", "surface form": "algebraic"}, name="Algebraic SPM"
{"SEI": "reaction limited", "surface form": "algebraic"},
name="Algebraic SPM",
),
pb.lithium_ion.SPMe(
{"SEI": "reaction limited", "surface form": "algebraic"}, name="Algebraic SPMe"
{"SEI": "reaction limited", "surface form": "algebraic"},
name="Algebraic SPMe",
),
pb.lithium_ion.DFN({"SEI": "reaction limited"}),
]
Expand Down
9 changes: 6 additions & 3 deletions pybamm/models/full_battery_models/base_battery_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ class BatteryModelOptions(pybamm.FuzzyDict):

- "none": :class:`pybamm.sei.NoSEI` (no SEI growth)
- "constant": :class:`pybamm.sei.Constant` (constant SEI thickness)
- "reaction limited", "solvent-diffusion limited",\
"electron-migration limited", "interstitial-diffusion limited", \
or "ec reaction limited": :class:`pybamm.sei.SEIGrowth`
- "reaction limited", "reaction limited (asymmetric)", \
"solvent-diffusion limited", "electron-migration limited", \
"interstitial-diffusion limited", "ec reaction limited" \
or "ec reaction limited (asymmetric)": :class:`pybamm.sei.SEIGrowth`
* "SEI film resistance" : str
Set the submodel for additional term in the overpotential due to SEI.
The default value is "none" if the "SEI" option is "none", and
Expand Down Expand Up @@ -255,10 +256,12 @@ def __init__(self, extra_options):
"none",
"constant",
"reaction limited",
"reaction limited (asymmetric)",
"solvent-diffusion limited",
"electron-migration limited",
"interstitial-diffusion limited",
"ec reaction limited",
"ec reaction limited (asymmetric)",
],
"SEI film resistance": ["none", "distributed", "average"],
"SEI on cracks": ["false", "true"],
Expand Down
5 changes: 3 additions & 2 deletions pybamm/models/submodels/interface/sei/base_sei.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ def _get_standard_concentration_variables(self, variables):
)
v_bar = phase_param.v_bar
z_sei = phase_param.z_sei
# Set scales for the "EC Reaction Limited" model
if self.options["SEI"] == "ec reaction limited":
# Set scales for the "EC Reaction Limited" models (both symmetric and
# asymmetric)
if self.options["SEI"].startswith("ec reaction limited"):
L_inner_0 = 0
L_outer_0 = 1
L_inner_crack_0 = 0
Expand Down
23 changes: 15 additions & 8 deletions pybamm/models/submodels/interface/sei/sei_growth.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def get_fundamental_variables(self):

L_inner, L_outer = Ls

if self.options["SEI"] == "ec reaction limited":
if self.options["SEI"].startswith("ec reaction limited"):
L_inner = 0 * L_inner # Set L_inner to zero, copying domains

variables = self._get_standard_thickness_variables(L_inner, L_outer)
Expand Down Expand Up @@ -100,9 +100,16 @@ def get_coupled_variables(self, variables):
# Thermal prefactor for reaction, interstitial and EC models
prefactor = 1 / (1 + self.param.Theta * T)

if self.options["SEI"] == "reaction limited":
# Define alpha_SEI depending on whether it is symmetric or asymmetric. This
# applies to "reaction limited" and "EC reaction limited"
if self.options["SEI"].endswith("(asymmetric)"):
alpha_SEI = phase_param.alpha_SEI
else:
alpha_SEI = 0.5

if self.options["SEI"].startswith("reaction limited"):
C_sei = phase_param.C_sei_reaction
j_sei = -(1 / C_sei) * pybamm.exp(-0.5 * prefactor * eta_SEI)
j_sei = -(1 / C_sei) * pybamm.exp(-alpha_SEI * prefactor * eta_SEI)

elif self.options["SEI"] == "electron-migration limited":
U_inner = phase_param.U_inner_electron
Expand All @@ -117,7 +124,7 @@ def get_coupled_variables(self, variables):
C_sei = phase_param.C_sei_solvent
j_sei = -1 / (C_sei * L_sei_outer)

elif self.options["SEI"] == "ec reaction limited":
elif self.options["SEI"].startswith("ec reaction limited"):
C_sei_ec = phase_param.C_sei_ec
C_ec = phase_param.C_ec

Expand All @@ -129,7 +136,7 @@ def get_coupled_variables(self, variables):
# so
# j_sei = -C_sei_ec * exp() / (1 + L_sei * C_ec * C_sei_ec * exp())
# c_ec = 1 / (1 + L_sei * C_ec * C_sei_ec * exp())
C_sei_exp = C_sei_ec * pybamm.exp(-0.5 * prefactor * eta_SEI)
C_sei_exp = C_sei_ec * pybamm.exp(-alpha_SEI * prefactor * eta_SEI)
j_sei = -C_sei_exp / (1 + L_sei * C_ec * C_sei_exp)
c_ec = 1 / (1 + L_sei * C_ec * C_sei_exp)

Expand All @@ -150,7 +157,7 @@ def get_coupled_variables(self, variables):
}
)

if self.options["SEI"] == "ec reaction limited":
if self.options["SEI"].startswith("ec reaction limited"):
inner_sei_proportion = 0
else:
inner_sei_proportion = phase_param.inner_sei_proportion
Expand Down Expand Up @@ -224,7 +231,7 @@ def set_rhs(self, variables):

Gamma_SEI = self.phase_param.Gamma_SEI

if self.options["SEI"] == "ec reaction limited":
if self.options["SEI"].startswith("ec reaction limited"):
self.rhs = {L_outer: -Gamma_SEI * a * j_outer + spreading_outer}
else:
v_bar = self.phase_param.v_bar
Expand All @@ -247,7 +254,7 @@ def set_initial_conditions(self, variables):
else:
L_inner_0 = self.phase_param.L_inner_0
L_outer_0 = self.phase_param.L_outer_0
if self.options["SEI"] == "ec reaction limited":
if self.options["SEI"].startswith("ec reaction limited"):
self.initial_conditions = {L_outer: L_inner_0 + L_outer_0}
else:
self.initial_conditions = {L_inner: L_inner_0, L_outer: L_outer_0}
1 change: 1 addition & 0 deletions pybamm/parameters/lithium_ion_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ def _set_dimensional_parameters(self):
self.E_sei_dimensional = pybamm.Parameter(
f"{pref}SEI growth activation energy [J.mol-1]"
)
self.alpha_SEI = pybamm.Parameter(f"{pref}SEI growth transfer coefficient")

# EC reaction
self.c_ec_0_dim = pybamm.Parameter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ def test_sei_reaction_limited(self):
options = {"SEI": "reaction limited"}
self.run_basic_processing_test(options)

def test_sei_asymmetric_reaction_limited(self):
options = {"SEI": "reaction limited (asymmetric)"}
parameter_values = pybamm.ParameterValues("Xu2019")
parameter_values.update(
{"SEI growth transfer coefficient": 0.2},
check_already_exists=False,
)
self.run_basic_processing_test(options, parameter_values=parameter_values)

def test_sei_solvent_diffusion_limited(self):
options = {"SEI": "solvent-diffusion limited"}
self.run_basic_processing_test(options)
Expand All @@ -69,6 +78,15 @@ def test_sei_ec_reaction_limited(self):
options = {"SEI": "ec reaction limited"}
self.run_basic_processing_test(options)

def test_sei_asymmetric_ec_reaction_limited(self):
options = {"SEI": "ec reaction limited (asymmetric)"}
parameter_values = pybamm.ParameterValues("Xu2019")
parameter_values.update(
{"SEI growth transfer coefficient": 0.2},
check_already_exists=False,
)
self.run_basic_processing_test(options, parameter_values=parameter_values)

def test_constant_utilisation(self):
options = {"interface utilisation": "constant"}
parameter_values = pybamm.ParameterValues("Xu2019")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,15 @@ def test_sei_reaction_limited(self):
options = {"SEI": "reaction limited"}
self.run_basic_processing_test(options)

def test_sei_asymmetric_reaction_limited(self):
options = {"SEI": "reaction limited (asymmetric)"}
parameter_values = pybamm.ParameterValues("Marquis2019")
parameter_values.update(
{"SEI growth transfer coefficient": 0.2},
check_already_exists=False,
)
self.run_basic_processing_test(options, parameter_values=parameter_values)

def test_sei_solvent_diffusion_limited(self):
options = {"SEI": "solvent-diffusion limited"}
self.run_basic_processing_test(options)
Expand All @@ -182,9 +191,24 @@ def test_sei_interstitial_diffusion_limited(self):
self.run_basic_processing_test(options)

def test_sei_ec_reaction_limited(self):
options = {"SEI": "ec reaction limited", "SEI porosity change": "true"}
options = {
"SEI": "ec reaction limited",
"SEI porosity change": "true",
}
self.run_basic_processing_test(options)

def test_sei_asymmetric_ec_reaction_limited(self):
options = {
"SEI": "ec reaction limited (asymmetric)",
"SEI porosity change": "true",
}
parameter_values = pybamm.ParameterValues("Marquis2019")
parameter_values.update(
{"SEI growth transfer coefficient": 0.2},
check_already_exists=False,
)
self.run_basic_processing_test(options, parameter_values=parameter_values)

def test_loss_active_material_stress_negative(self):
options = {"loss of active material": ("none", "stress-driven")}
parameter_values = pybamm.ParameterValues("Ai2020")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
'particle phases': '1' (possible: ['1', '2'])
'particle shape': 'spherical' (possible: ['spherical', 'no particles'])
'particle size': 'single' (possible: ['single', 'distribution'])
'SEI': 'none' (possible: ['none', 'constant', 'reaction limited', 'solvent-diffusion limited', 'electron-migration limited', 'interstitial-diffusion limited', 'ec reaction limited'])
'SEI': 'none' (possible: ['none', 'constant', 'reaction limited', 'reaction limited (asymmetric)', 'solvent-diffusion limited', 'electron-migration limited', 'interstitial-diffusion limited', 'ec reaction limited', 'ec reaction limited (asymmetric)'])
'SEI film resistance': 'none' (possible: ['none', 'distributed', 'average'])
'SEI on cracks': 'false' (possible: ['false', 'true'])
'SEI porosity change': 'false' (possible: ['false', 'true'])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ def test_well_posed_reaction_limited_sei(self):
options = {"SEI": "reaction limited"}
self.check_well_posedness(options)

def test_well_posed_asymmetric_reaction_limited_sei(self):
options = {"SEI": "reaction limited (asymmetric)"}
self.check_well_posedness(options)

def test_well_posed_solvent_diffusion_limited_sei(self):
options = {"SEI": "solvent-diffusion limited"}
self.check_well_posedness(options)
Expand All @@ -71,6 +75,10 @@ def test_well_posed_ec_reaction_limited_sei(self):
options = {"SEI": "ec reaction limited"}
self.check_well_posedness(options)

def test_well_posed_asymmetric_ec_reaction_limited_sei(self):
options = {"SEI": "ec reaction limited (asymmetric)"}
self.check_well_posedness(options)

def test_well_posed_lumped_thermal(self):
options = {"thermal": "lumped"}
self.check_well_posedness(options)
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,22 @@ def test_well_posed_sei_reaction_limited(self):
options = {"SEI": "reaction limited"}
self.check_well_posedness(options)

def test_well_posed_asymmetric_sei_reaction_limited(self):
options = {"SEI": "reaction limited (asymmetric)"}
self.check_well_posedness(options)

def test_well_posed_sei_reaction_limited_average_film_resistance(self):
options = {"SEI": "reaction limited", "SEI film resistance": "average"}
options = {
"SEI": "reaction limited",
"SEI film resistance": "average",
}
self.check_well_posedness(options)

def test_well_posed_asymmetric_sei_reaction_limited_average_film_resistance(self):
options = {
"SEI": "reaction limited (asymmetric)",
"SEI film resistance": "average",
}
self.check_well_posedness(options)

def test_well_posed_sei_solvent_diffusion_limited(self):
Expand All @@ -164,7 +178,17 @@ def test_well_posed_sei_interstitial_diffusion_limited(self):
self.check_well_posedness(options)

def test_well_posed_sei_ec_reaction_limited(self):
options = {"SEI": "ec reaction limited", "SEI porosity change": "true"}
options = {
"SEI": "ec reaction limited",
"SEI porosity change": "true",
}
self.check_well_posedness(options)

def test_well_posed_sei_asymmetric_ec_reaction_limited(self):
options = {
"SEI": "ec reaction limited (asymmetric)",
"SEI porosity change": "true",
}
self.check_well_posedness(options)

def test_well_posed_mechanics_negative_cracking(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ def test_interstitial_diffusion_limited_not_implemented(self):
pybamm.lithium_ion.MPM(options)

def test_ec_reaction_limited_not_implemented(self):
options = {"SEI": "ec reaction limited", "SEI porosity change": "true"}
options = {
"SEI": "ec reaction limited",
"SEI porosity change": "true",
}
with self.assertRaises(NotImplementedError):
pybamm.lithium_ion.MPM(options)

Expand Down