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

Li metal spm #1731

Merged
merged 10 commits into from
Nov 5, 2021
58 changes: 0 additions & 58 deletions examples/scripts/DFN_half_cell.py

This file was deleted.

26 changes: 26 additions & 0 deletions examples/scripts/compare_lithium_ion_half_cell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# Compare half-cell lithium-ion battery models
#
import pybamm

pybamm.set_logging_level("INFO")

# load models
models = [
pybamm.lithium_ion.SPM({"working electrode": "positive"}),
pybamm.lithium_ion.SPMe({"working electrode": "positive"}),
pybamm.lithium_ion.DFN({"working electrode": "positive"}),
]

chemistry = pybamm.parameter_sets.Xu2019
param = pybamm.ParameterValues(chemistry=chemistry)

# create and run simulations
sims = []
for model in models:
sim = pybamm.Simulation(model, parameter_values=param)
sim.solve([0, 3600])
sims.append(sim)

# plot
pybamm.dynamic_plot(sims)
2 changes: 1 addition & 1 deletion pybamm/models/full_battery_models/base_battery_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ def build_model(self):

# Massive hack for consistent delta_phi = phi_s - phi_e with SPMe
# This needs to be corrected
if isinstance(self, pybamm.lithium_ion.SPMe):
if isinstance(self, pybamm.lithium_ion.SPMe) and not self.half_cell:
for domain in ["Negative", "Positive"]:
phi_s = self.variables[domain + " electrode potential"]
phi_e = self.variables[domain + " electrolyte potential"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,42 @@ def set_porosity_submodel(self):
self.submodels["porosity"] = pybamm.porosity.ReactionDriven(
self.param, self.options, self.x_average
)

def set_li_metal_counter_electrode_submodels(self):
if self.options["SEI"] in ["none", "constant"]:
self.submodels[
"counter electrode potential"
] = pybamm.electrode.ohm.LithiumMetalExplicit(self.param, self.options)
self.submodels[
"counter electrode interface"
] = pybamm.interface.InverseButlerVolmer(
self.param, "Negative", "lithium metal plating", self.options
) # assuming symmetric reaction for now so we can take the inverse
self.submodels[
"counter electrode interface current"
] = pybamm.interface.CurrentForInverseButlerVolmerLithiumMetal(
self.param, "Negative", "lithium metal plating", self.options
)
else:
self.submodels[
"counter electrode potential"
] = pybamm.electrode.ohm.LithiumMetalSurfaceForm(self.param, self.options)
self.submodels[
"counter electrode interface"
] = pybamm.interface.ButlerVolmer(
self.param, "Negative", "lithium metal plating", self.options
)

# For half-cell models, remove negative electrode submodels
# that are not needed before building
# We do this whether the working electrode is 'positive' or 'negative' since
# the half-cell models are always defined assuming the positive electrode is
# the working electrode

# This should be done before `self.build_model`, which is the expensive part

# Models added specifically for the counter electrode have been labelled with
# "counter electrode" so as not to be caught by this check
self.submodels = {
k: v for k, v in self.submodels.items() if not k.startswith("negative")
}
50 changes: 3 additions & 47 deletions pybamm/models/full_battery_models/lithium_ion/dfn.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,9 @@ def __init__(self, options=None, name="Doyle-Fuller-Newman model", build=True):
self.set_sei_submodel()
self.set_lithium_plating_submodel()

# For half-cell models, remove negative electrode submodels
# that are not needed before building
# We do this whether the working electrode is 'positive' or 'negative' since
# the half-cell models are always defined assuming the positive electrode is
# the working electrode
# It's ok to only do this now since `build_model` is the expensive part
if self.options["working electrode"] != "both":
self.submodels = {
k: v for k, v in self.submodels.items() if not k.startswith("negative")
}
# Models added specifically for the counter electrode should be labelled with
# "counter electrode" so as not to be caught by this check
if self.half_cell:
# This also removes "negative electrode" submodels, so should be done last
self.set_li_metal_counter_electrode_submodels()

if build:
self.build_model()
Expand All @@ -87,27 +78,6 @@ def set_interfacial_submodel(self):
self.param, "Positive", "lithium-ion main", self.options
)

# Set the counter-electrode model for the half-cell model
# The negative electrode model will be ignored
if self.half_cell:
if self.options["SEI"] in ["none", "constant"]:
self.submodels[
"counter electrode interface"
] = pybamm.interface.InverseButlerVolmer(
self.param, "Negative", "lithium metal plating", self.options
) # assuming symmetric reaction for now so we can take the inverse
self.submodels[
"counter electrode interface current"
] = pybamm.interface.CurrentForInverseButlerVolmerLithiumMetal(
self.param, "Negative", "lithium metal plating", self.options
)
else:
self.submodels[
"counter electrode interface"
] = pybamm.interface.ButlerVolmer(
self.param, "Negative", "lithium metal plating", self.options
)

def set_particle_submodel(self):

if isinstance(self.options["particle"], str):
Expand Down Expand Up @@ -166,20 +136,6 @@ def set_solid_submodel(self):
self.submodels["negative electrode potential"] = submod_n
self.submodels["positive electrode potential"] = submod_p

# Set the counter-electrode model for the half-cell model
# The negative electrode model will be ignored
if self.half_cell:
if self.options["SEI"] in ["none", "constant"]:
self.submodels[
"counter electrode potential"
] = pybamm.electrode.ohm.LithiumMetalExplicit(self.param, self.options)
else:
self.submodels[
"counter electrode potential"
] = pybamm.electrode.ohm.LithiumMetalSurfaceForm(
self.param, self.options
)

def set_electrolyte_submodel(self):

surf_form = pybamm.electrolyte_conductivity.surface_potential_form
Expand Down
34 changes: 20 additions & 14 deletions pybamm/models/full_battery_models/lithium_ion/spm.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,18 @@ def __init__(self, options=None, name="Single Particle Model", build=True):
self.set_interfacial_submodel()
self.set_other_reaction_submodels_to_zero()
self.set_particle_submodel()
self.set_negative_electrode_submodel()
self.set_solid_submodel()
self.set_electrolyte_submodel()
self.set_positive_electrode_submodel()
self.set_thermal_submodel()
self.set_current_collector_submodel()

self.set_sei_submodel()
self.set_lithium_plating_submodel()

if self.half_cell:
# This also removes "negative electrode" submodels, so should be done last
self.set_li_metal_counter_electrode_submodels()

if build:
self.build_model()

Expand All @@ -63,10 +66,10 @@ def set_convection_submodel(self):

self.submodels[
"through-cell convection"
] = pybamm.convection.through_cell.NoConvection(self.param)
] = pybamm.convection.through_cell.NoConvection(self.param, self.options)
self.submodels[
"transverse convection"
] = pybamm.convection.transverse.NoConvection(self.param)
] = pybamm.convection.transverse.NoConvection(self.param, self.options)

def set_interfacial_submodel(self):

Expand All @@ -80,12 +83,12 @@ def set_interfacial_submodel(self):
self.submodels[
"negative interface current"
] = pybamm.interface.CurrentForInverseButlerVolmer(
self.param, "Negative", "lithium-ion main"
self.param, "Negative", "lithium-ion main", self.options
)
self.submodels[
"positive interface current"
] = pybamm.interface.CurrentForInverseButlerVolmer(
self.param, "Positive", "lithium-ion main"
self.param, "Positive", "lithium-ion main", self.options
)
else:
self.submodels["negative interface"] = pybamm.interface.ButlerVolmer(
Expand Down Expand Up @@ -123,17 +126,18 @@ def set_particle_submodel(self):
self.param, domain, particle_side
)

def set_negative_electrode_submodel(self):
def set_solid_submodel(self):

self.submodels[
"negative electrode potential"
] = pybamm.electrode.ohm.LeadingOrder(self.param, "Negative")

def set_positive_electrode_submodel(self):

] = pybamm.electrode.ohm.LeadingOrder(
self.param, "Negative", options=self.options
)
self.submodels[
"positive electrode potential"
] = pybamm.electrode.ohm.LeadingOrder(self.param, "Positive")
] = pybamm.electrode.ohm.LeadingOrder(
self.param, "Positive", options=self.options
)

def set_electrolyte_submodel(self):

Expand All @@ -149,7 +153,9 @@ def set_electrolyte_submodel(self):
if self.options["surface form"] == "false":
self.submodels[
"leading-order electrolyte conductivity"
] = pybamm.electrolyte_conductivity.LeadingOrder(self.param)
] = pybamm.electrolyte_conductivity.LeadingOrder(
self.param, options=self.options
)

elif self.options["surface form"] == "differential":
for domain in ["Negative", "Separator", "Positive"]:
Expand All @@ -165,4 +171,4 @@ def set_electrolyte_submodel(self):

self.submodels[
"electrolyte diffusion"
] = pybamm.electrolyte_diffusion.ConstantConcentration(self.param)
] = pybamm.electrolyte_diffusion.ConstantConcentration(self.param, self.options)
Loading