#
# Doyle-Fuller-Newman (DFN) Model
#
import pybamm
from .base_lithium_ion_model import BaseModel
[docs]
class DFN(BaseModel):
"""
Doyle-Fuller-Newman (DFN) model of a lithium-ion battery, from
:footcite:t:`Marquis2019`. See :class:`pybamm.lithium_ion.BaseModel` for more
details.
Examples
--------
>>> model = pybamm.lithium_ion.DFN()
>>> model.name
'Doyle-Fuller-Newman model'
"""
def __init__(self, options=None, name="Doyle-Fuller-Newman model", build=True):
# For degradation models we use the full form since this is a full-order model
self.x_average = False
super().__init__(options, name)
self.set_submodels(build)
pybamm.citations.register("Doyle1993")
def set_intercalation_kinetics_submodel(self):
for domain in ["negative", "positive"]:
electrode_type = self.options.electrode_types[domain]
if electrode_type == "porous":
intercalation_kinetics = self.get_intercalation_kinetics(domain)
phases = self.options.phases[domain]
for phase in phases:
submod = intercalation_kinetics(
self.param, domain, "lithium-ion main", self.options, phase
)
self.submodels[f"{domain} {phase} interface"] = submod
if len(phases) > 1:
self.submodels[f"total {domain} interface"] = (
pybamm.kinetics.TotalMainKinetics(
self.param, domain, "lithium-ion main", self.options
)
)
def set_particle_submodel(self):
for domain in ["negative", "positive"]:
if self.options.electrode_types[domain] == "planar":
continue
particle = getattr(self.options, domain)["particle"]
for phase in self.options.phases[domain]:
if particle == "Fickian diffusion":
submod = pybamm.particle.FickianDiffusion(
self.param, domain, self.options, phase=phase, x_average=False
)
elif particle in [
"uniform profile",
"quadratic profile",
"quartic profile",
]:
submod = pybamm.particle.PolynomialProfile(
self.param, domain, self.options, phase=phase
)
elif particle == "MSMR":
submod = pybamm.particle.MSMRDiffusion(
self.param, domain, self.options, phase=phase, x_average=False
)
# also set the submodel for calculating stoichiometry from
# potential
self.submodels[f"{domain} {phase} stoichiometry"] = (
pybamm.particle.MSMRStoichiometryVariables(
self.param,
domain,
self.options,
phase=phase,
x_average=False,
)
)
self.submodels[f"{domain} {phase} particle"] = submod
self.submodels[f"{domain} {phase} total particle concentration"] = (
pybamm.particle.TotalConcentration(
self.param, domain, self.options, phase
)
)
def set_solid_submodel(self):
for domain in ["negative", "positive"]:
if self.options.electrode_types[domain] == "planar":
continue
if self.options["surface form"] == "false":
submodel = pybamm.electrode.ohm.Full
else:
submodel = pybamm.electrode.ohm.SurfaceForm
self.submodels[f"{domain} electrode potential"] = submodel(
self.param, domain, self.options
)
def set_electrolyte_concentration_submodel(self):
self.submodels["electrolyte diffusion"] = pybamm.electrolyte_diffusion.Full(
self.param, self.options
)
def set_electrolyte_potential_submodel(self):
surf_form = pybamm.electrolyte_conductivity.surface_potential_form
if self.options["electrolyte conductivity"] not in ["default", "full"]:
raise pybamm.OptionError(
"electrolyte conductivity '{}' not suitable for DFN".format(
self.options["electrolyte conductivity"]
)
)
if self.options["surface form"] == "false":
self.submodels["electrolyte conductivity"] = (
pybamm.electrolyte_conductivity.Full(self.param, self.options)
)
if self.options["surface form"] == "false":
surf_model = surf_form.Explicit
elif self.options["surface form"] == "differential":
surf_model = surf_form.FullDifferential
elif self.options["surface form"] == "algebraic":
surf_model = surf_form.FullAlgebraic
for domain in ["negative", "separator", "positive"]:
if self.options.electrode_types.get(domain) == "planar":
continue
self.submodels[f"{domain} surface potential difference"] = surf_model(
self.param, domain, self.options
)
def set_summary_variables(self):
self.set_default_summary_variables()