Tip
An interactive online version of this notebook is available, which can be accessed via
Alternatively, you may download this notebook and run it offline.
Loss of active material submodels#
In this notebook we show how to use the loss of active materials (LAM) submodels in PyBaMM.
Stress-driven LAM#
The first model we consider is the stress-driven submodel, which follows equation (25) from Reniers et al (2019), and the stresses are calculated by equations (7)-(9) in Ai et al (2020). To see all of the models and submodels available in PyBaMM, please take a look at the documentation.
As usual, we start by defining the model. We choose a DFN model with stress-driven loss of active material, and we also include SEI growth. We then define the parameters and experiments, and solve the simulation.
[1]:
%pip install "pybamm[plot,cite]" -q # install PyBaMM if it is not installed
import pybamm
model = pybamm.lithium_ion.DFN(
options={
"SEI": "solvent-diffusion limited",
"SEI porosity change": "false",
"particle mechanics": "swelling only",
"loss of active material": "stress-driven",
}
)
param = pybamm.ParameterValues("Ai2020")
param.update({"Negative electrode LAM constant proportional term [s-1]": 1e-4 / 3600})
param.update({"Positive electrode LAM constant proportional term [s-1]": 1e-4 / 3600})
experiment = pybamm.Experiment(
[
"Discharge at 1C until 3 V",
"Rest for 600 seconds",
"Charge at 1C until 4.2 V",
"Hold at 4.199 V for 600 seconds",
]
)
sim = pybamm.Simulation(
model,
experiment=experiment,
parameter_values=param,
discretisation_kwargs={"remove_independent_variables_from_rhs": True},
)
solution = sim.solve(calc_esoh=False)
Note: you may need to restart the kernel to use updated packages.
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3387, , mxstep steps taken before reaching tout.
We can now plot the results as usual.
[2]:
sim.plot(
[
"Voltage [V]",
"Current [A]",
"Sum of x-averaged positive electrode volumetric interfacial current densities [A.m-3]",
"Sum of x-averaged negative electrode volumetric interfacial current densities [A.m-3]",
"X-averaged positive electrode active material volume fraction",
"X-averaged negative electrode active material volume fraction",
"X-averaged positive particle surface tangential stress [Pa]",
"X-averaged negative particle surface tangential stress [Pa]",
]
)
[2]:
<pybamm.plotting.quick_plot.QuickPlot at 0x301e27dd0>
To understand the effect of the LAM constant proportional term, let’s perform a parameter sweep.
[3]:
ks = [1e-4, 1e-3, 1e-2]
solutions = []
for k in ks:
param.update({"Positive electrode LAM constant proportional term [s-1]": k / 3600})
param.update({"Negative electrode LAM constant proportional term [s-1]": k / 3600})
sim = pybamm.Simulation(
model,
experiment=experiment,
parameter_values=param,
discretisation_kwargs={"remove_independent_variables_from_rhs": True},
)
solution = sim.solve(calc_esoh=False)
solutions.append(solution)
pybamm.dynamic_plot(
solutions,
output_variables=[
"Voltage [V]",
"Current [A]",
"Sum of x-averaged positive electrode volumetric interfacial current densities [A.m-3]",
"Sum of x-averaged negative electrode volumetric interfacial current densities [A.m-3]",
"X-averaged positive electrode active material volume fraction",
"X-averaged negative electrode active material volume fraction",
"X-averaged positive electrode surface area to volume ratio [m-1]",
"X-averaged negative electrode surface area to volume ratio [m-1]",
],
labels=[f"k={k:.0e}" for k in ks],
)
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3387, , mxstep steps taken before reaching tout.
At t = 57.3307, , mxstep steps taken before reaching tout.
At t = 57.3307 and h = 3.45325e-14, the corrector convergence failed repeatedly or with |h| = hmin.
At t = 57.3307, , mxstep steps taken before reaching tout.
At t = 57.3307, , mxstep steps taken before reaching tout.
At t = 57.2504, , mxstep steps taken before reaching tout.
At t = 57.2504, , mxstep steps taken before reaching tout.
At t = 57.2504, , mxstep steps taken before reaching tout.
At t = 57.2504, , mxstep steps taken before reaching tout.
[3]:
<pybamm.plotting.quick_plot.QuickPlot at 0x301aa2ed0>
Reaction-driven LAM#
Another option is to use reaction-driven (i.e. SEI) LAM. In this case we need to choose the "reaction-driven"
option in the model, and proceed along the lines of the previous example.
[4]:
import pybamm
experiment = pybamm.Experiment(
[
"Discharge at 1C until 3 V",
"Rest for 600 seconds",
"Charge at 1C until 4.2 V",
"Hold at 4.199 V for 600 seconds",
]
)
model = pybamm.lithium_ion.DFN(
options={
"SEI": "solvent-diffusion limited",
"loss of active material": "reaction-driven",
}
)
param = pybamm.ParameterValues("Chen2020")
param.update({"Negative electrode reaction-driven LAM factor [m3.mol-1]": 1e-4})
sim = pybamm.Simulation(
model,
experiment=experiment,
parameter_values=param,
solver=pybamm.CasadiSolver("fast with events"),
)
solution = sim.solve(calc_esoh=False)
sim.plot(
[
"Voltage [V]",
"Current [A]",
"Sum of x-averaged negative electrode volumetric interfacial current densities [A.m-3]",
"X-averaged negative electrode active material volume fraction",
"Negative total SEI thickness [m]",
"X-averaged negative total SEI thickness [m]",
]
)
[4]:
<pybamm.plotting.quick_plot.QuickPlot at 0x325594650>
Both stress-driven and reaction-driven can be combined by calling the "stress and reaction-driven"
option.
Current-driven LAM#
The final submodel is current-driven LAM, which follows equation (26) from Reniers et al (2019). In this case we need to define the RHS of the equation as a function of current density and temperature. The example here is illustrative and does not represent any real scenario.
[5]:
def current_LAM(i, T):
return -1e-10 * (abs(i) + 1e3 * abs(i) ** 0.5)
model = pybamm.lithium_ion.DFN(
options={
"loss of active material": "current-driven",
}
)
param = pybamm.ParameterValues("Chen2020")
param.update(
{
"Positive electrode current-driven LAM rate": current_LAM,
"Negative electrode current-driven LAM rate": current_LAM,
},
check_already_exists=False,
)
sim = pybamm.Simulation(
model,
experiment=experiment,
parameter_values=param,
solver=pybamm.CasadiSolver("fast with events"),
)
solution = sim.solve(calc_esoh=False)
sim.plot(
[
"Voltage [V]",
"Current [A]",
"X-averaged positive electrode active material volume fraction",
"X-averaged negative electrode active material volume fraction",
]
)
[5]:
<pybamm.plotting.quick_plot.QuickPlot at 0x328bee650>
LAM with composite electrode#
The LAM submodel is also compatible with multiple phases within an electrode for both stress- and reaction-driven loss of active material. Currently, there is no single parameter set that combines both LAM degradation and composite materials. The following examples use the Chen2020 composite parameter set with LAM parameters taken from the Ai2020 parameter set.
[6]:
# Volume change functions from Ai2020 parameters
def graphite_volume_change_Ai2020(sto):
p1 = 145.907
p2 = -681.229
p3 = 1334.442
p4 = -1415.710
p5 = 873.906
p6 = -312.528
p7 = 60.641
p8 = -5.706
p9 = 0.386
p10 = -4.966e-05
t_change = (
p1 * sto**9
+ p2 * sto**8
+ p3 * sto**7
+ p4 * sto**6
+ p5 * sto**5
+ p6 * sto**4
+ p7 * sto**3
+ p8 * sto**2
+ p9 * sto
+ p10
)
return t_change
def lico2_volume_change_Ai2020(sto):
omega = pybamm.Parameter("Positive electrode partial molar volume [m3.mol-1]")
c_s_max = pybamm.Parameter("Maximum concentration in positive electrode [mol.m-3]")
t_change = omega * c_s_max * sto
return t_change
Stress-driven composite anode#
The secondary phase LAM parameters have been adjusted from the Ai2020 by about 10% to show less degradation in that phase. The model is set up in the same way the single-phase simulation is but with additional parameters.
[7]:
options = {
"particle phases": ("2", "1"),
"open-circuit potential": (("single", "current sigmoid"), "single"),
"loss of active material": "stress-driven",
}
model = pybamm.lithium_ion.SPM(options)
parameter_values = pybamm.ParameterValues("Chen2020_composite")
second = 0.1
parameter_values.update(
{
"Primary: Negative electrode reference concentration for free of deformation [mol.m-3]": 0.0,
"Secondary: Negative electrode reference concentration for free of deformation [mol.m-3]": 0.0,
"Primary: Negative electrode LAM constant proportional term [s-1]": 1e-4 / 3600,
"Secondary: Negative electrode LAM constant proportional term [s-1]": 1e-4
/ 3600
* second,
"Positive electrode LAM constant proportional term [s-1]": 1e-4 / 3600,
"Primary: Negative electrode partial molar volume [m3.mol-1]": 3.1e-06,
"Primary: Negative electrode Young's modulus [Pa]": 15000000000.0,
"Primary: Negative electrode Poisson's ratio": 0.3,
"Primary: Negative electrode critical stress [Pa]": 60000000.0,
"Secondary: Negative electrode critical stress [Pa]": 60000000.0,
"Primary: Negative electrode LAM constant exponential term": 2.0,
"Secondary: Negative electrode LAM constant exponential term": 2.0,
"Secondary: Negative electrode partial molar volume [m3.mol-1]": 3.1e-06
* second,
"Secondary: Negative electrode Young's modulus [Pa]": 15000000000.0 * second,
"Secondary: Negative electrode Poisson's ratio": 0.3 * second,
"Negative electrode reference concentration for free of deformation [mol.m-3]": 0.0,
"Primary: Negative electrode volume change": graphite_volume_change_Ai2020,
"Secondary: Negative electrode volume change": graphite_volume_change_Ai2020,
"Positive electrode partial molar volume [m3.mol-1]": -7.28e-07,
"Positive electrode Young's modulus [Pa]": 375000000000.0,
"Positive electrode Poisson's ratio": 0.2,
"Positive electrode critical stress [Pa]": 375000000.0,
"Positive electrode LAM constant exponential term": 2.0,
"Positive electrode reference concentration for free of deformation [mol.m-3]": 0.0,
"Positive electrode volume change": lico2_volume_change_Ai2020,
},
check_already_exists=False,
)
# sim = pybamm.Simulation(model, parameter_values=parameter_values)
# sim.solve([0, 4500])
experiment = pybamm.Experiment(
[
"Discharge at 1C until 3 V",
"Rest for 600 seconds",
"Charge at 1C until 4.2 V",
"Hold at 4.199 V for 600 seconds",
]
)
sim = pybamm.Simulation(
model,
experiment=experiment,
parameter_values=parameter_values,
discretisation_kwargs={"remove_independent_variables_from_rhs": True},
)
solution = sim.solve(calc_esoh=False)
The two phase LAM model can be compared between the cathode and two anode phases.
[8]:
pybamm.dynamic_plot(
sim,
[
"Voltage [V]",
"Current [A]",
[
"Average negative primary particle concentration",
"Average negative secondary particle concentration",
"Average positive particle concentration",
],
"X-averaged negative electrode primary active material volume fraction",
"X-averaged positive electrode active material volume fraction",
"X-averaged negative electrode secondary active material volume fraction",
"Sum of x-averaged positive electrode volumetric interfacial current densities [A.m-3]",
"Sum of x-averaged negative electrode volumetric interfacial current densities [A.m-3]",
"X-averaged positive particle surface tangential stress [Pa]",
"X-averaged negative primary particle surface tangential stress [Pa]",
"X-averaged negative secondary particle surface tangential stress [Pa]",
],
)
[8]:
<pybamm.plotting.quick_plot.QuickPlot at 0x324b0add0>
Reaction-driven composite anode#
The same process is repeated for the reaction-driven LAM degradation.
[9]:
options = {
"particle phases": ("2", "1"),
"open-circuit potential": (("single", "current sigmoid"), "single"),
"SEI": "solvent-diffusion limited",
"loss of active material": "reaction-driven",
}
model = pybamm.lithium_ion.SPM(options)
parameter_values = pybamm.ParameterValues("Chen2020_composite")
second = 0.9
parameter_values.update(
{
"Primary: Negative electrode partial molar volume [m3.mol-1]": 3.1e-06,
"Primary: Negative electrode Young's modulus [Pa]": 15000000000.0,
"Primary: Negative electrode Poisson's ratio": 0.3,
"Negative electrode critical stress [Pa]": 60000000.0,
"Negative electrode LAM constant exponential term": 2.0,
"Secondary: Negative electrode partial molar volume [m3.mol-1]": 3.1e-06
* second,
"Secondary: Negative electrode Young's modulus [Pa]": 15000000000.0 * second,
"Secondary: Negative electrode Poisson's ratio": 0.3 * second,
"Negative electrode reference concentration for free of deformation [mol.m-3]": 0.0,
"Primary: Negative electrode volume change": graphite_volume_change_Ai2020,
"Secondary: Negative electrode volume change": graphite_volume_change_Ai2020,
"Positive electrode partial molar volume [m3.mol-1]": -7.28e-07,
"Positive electrode Young's modulus [Pa]": 375000000000.0,
"Positive electrode Poisson's ratio": 0.2,
"Positive electrode critical stress [Pa]": 375000000.0,
"Positive electrode LAM constant exponential term": 2.0,
"Positive electrode reference concentration for free of deformation [mol.m-3]": 0.0,
"Positive electrode volume change": lico2_volume_change_Ai2020,
"Primary: Negative electrode reaction-driven LAM factor [m3.mol-1]": 1e-9,
"Secondary: Negative electrode reaction-driven LAM factor [m3.mol-1]": 10,
},
check_already_exists=False,
)
# Changing secondary SEI solvent diffusivity to show different degradation between phases
parameter_values.update(
{
"Secondary: SEI solvent diffusivity [m2.s-1]": 2.5e-24,
}
)
# sim = pybamm.Simulation(model, parameter_values=parameter_values)
# sim.solve([0, 4100])
sim = pybamm.Simulation(
model,
experiment=experiment,
parameter_values=parameter_values,
solver=pybamm.CasadiSolver("fast with events"),
)
solution = sim.solve(calc_esoh=False)
sim.plot(
[
"Voltage [V]",
"Current [A]",
"Sum of x-averaged negative electrode volumetric interfacial current densities [A.m-3]",
"X-averaged negative electrode primary active material volume fraction",
"X-averaged negative electrode secondary active material volume fraction",
"Negative total primary SEI thickness [m]",
"Negative total secondary SEI thickness [m]",
]
)
[9]:
<pybamm.plotting.quick_plot.QuickPlot at 0x32a9a6a10>
References#
The relevant papers for this notebook are:
[10]:
pybamm.print_citations()
[1] Weilong Ai, Niall Kirkaldy, Yang Jiang, Gregory Offer, Huizhi Wang, and Billy Wu. A composite electrode model for lithium-ion batteries with silicon/graphite negative electrodes. Journal of Power Sources, 527:231142, 2022. URL: https://www.sciencedirect.com/science/article/pii/S0378775322001604, doi:https://doi.org/10.1016/j.jpowsour.2022.231142.
[2] Weilong Ai, Ludwig Kraft, Johannes Sturm, Andreas Jossen, and Billy Wu. Electrochemical thermal-mechanical modelling of stress inhomogeneity in lithium-ion pouch cells. Journal of The Electrochemical Society, 167(1):013512, 2019. doi:10.1149/2.0122001JES.
[3] Joel A. E. Andersson, Joris Gillis, Greg Horn, James B. Rawlings, and Moritz Diehl. CasADi – A software framework for nonlinear optimization and optimal control. Mathematical Programming Computation, 11(1):1–36, 2019. doi:10.1007/s12532-018-0139-4.
[4] Ferran Brosa Planella and W. Dhammika Widanage. Systematic derivation of a Single Particle Model with Electrolyte and Side Reactions (SPMe+SR) for degradation of lithium-ion batteries. Submitted for publication, ():, 2022. doi:.
[5] Von DAG Bruggeman. Berechnung verschiedener physikalischer konstanten von heterogenen substanzen. i. dielektrizitätskonstanten und leitfähigkeiten der mischkörper aus isotropen substanzen. Annalen der physik, 416(7):636–664, 1935.
[6] Chang-Hui Chen, Ferran Brosa Planella, Kieran O'Regan, Dominika Gastol, W. Dhammika Widanage, and Emma Kendrick. Development of Experimental Techniques for Parameterization of Multi-scale Lithium-ion Battery Models. Journal of The Electrochemical Society, 167(8):080534, 2020. doi:10.1149/1945-7111/ab9050.
[7] Rutooj Deshpande, Mark Verbrugge, Yang-Tse Cheng, John Wang, and Ping Liu. Battery cycle life prediction with coupled chemical degradation and fatigue mechanics. Journal of the Electrochemical Society, 159(10):A1730, 2012. doi:10.1149/2.049210jes.
[8] Marc Doyle, Thomas F. Fuller, and John Newman. Modeling of galvanostatic charge and discharge of the lithium/polymer/insertion cell. Journal of the Electrochemical society, 140(6):1526–1533, 1993. doi:10.1149/1.2221597.
[9] Charles R. Harris, K. Jarrod Millman, Stéfan J. van der Walt, Ralf Gommers, Pauli Virtanen, David Cournapeau, Eric Wieser, Julian Taylor, Sebastian Berg, Nathaniel J. Smith, and others. Array programming with NumPy. Nature, 585(7825):357–362, 2020. doi:10.1038/s41586-020-2649-2.
[10] Scott G. Marquis. Long-term degradation of lithium-ion batteries. PhD thesis, University of Oxford, 2020.
[11] Scott G. Marquis, Valentin Sulzer, Robert Timms, Colin P. Please, and S. Jon Chapman. An asymptotic derivation of a single particle model with electrolyte. Journal of The Electrochemical Society, 166(15):A3693–A3706, 2019. doi:10.1149/2.0341915jes.
[12] Jorn M. Reniers, Grietus Mulder, and David A. Howey. Review and performance comparison of mechanical-chemical degradation models for lithium-ion batteries. Journal of The Electrochemical Society, 166(14):A3189, 2019. doi:10.1149/2.0281914jes.
[13] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). Journal of Open Research Software, 9(1):14, 2021. doi:10.5334/jors.309.
[ ]: