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.
Thermal models#
There are a number of thermal submodels available in PyBaMM. In this notebook we give details of each of the models, and highlight any relevant parameters. At present PyBaMM includes an isothermal and a lumped thermal model, both of which can be used with any cell geometry, as well as a 1D thermal model which accounts for the through-cell variation in temperature in a pouch cell, and “1+1D” and “2+1D” pouch cell models which assumed the temperature is uniform through the thickness of the pouch, but accounts for variations in temperature in the remaining dimensions. Here we give the governing equations for each model (except the isothermal model, which just sets the temperature to be equal to to the parameter “Ambient temperature [K]”).
A more comprehensive review of the pouch cell models, including how to properly compute the effective cooling terms, can be found in references [4] and [6] at the end of this notebook.
[1]:
%pip install "pybamm[plot,cite]" -q # install PyBaMM if it is not installed
import pybamm
Note: you may need to restart the kernel to use updated packages.
Lumped model#
The lumped thermal model solves the following ordinary differential equation for the average temperature, given here in dimensional terms,
where \(\rho_{eff}\) is effective volumetric heat capacity, \(T\) is the temperature, \(t\) is time, \(\bar{Q}\) is the averaged heat source term, \(h\) is the heat transfer coefficient, \(A\) is the surface area (available for cooling), \(V\) is the cell volume, and \(T_{\infty}\) is the ambient temperature. An initial temperature \(T_0\) must be prescribed.
The effective volumetric heat capacity is computed as
where \(\rho_k\) is the density, \(c_{p,k}\) is the specific heat, and \(L_k\) is the thickness of each component. The subscript \(k \in \{cn, n, s, p, cp\}\) is used to refer to the components negative current collector, negative electrode, separator, positive electrode, and positive current collector.
The heat source term accounts for Ohmic heating \(Q_{Ohm,k}\) due to resistance in the solid and electrolyte, irreverisble heating due to electrochemical reactions \(Q_{rxn,k}\), reversible heating due to entropic changes in the the electrode \(Q_{rev,k}\), and heating due to contact resistance \(Q_{cr}\):
with
Here \(i_k\) is the current, \(\phi_k\) the potential, \(a_k\) the surface area to volume ratio, \(j_k\) the interfacial current density, \(\eta_k\) the overpotential, \(U\) the open-circuit potential, \(R_{cr}\) is the contact resistance, and \(V_{cell}\) is the total cell volume. The averaged heat source term \(\bar{Q}\) is computed by taking the volume-average of \(Q\).
When using the option {"cell geometry": "arbitrary"}
the relevant parameters to specify the cooling conditions are:
which correspond directly to the parameters \(h\), \(A\) and \(V\) in the governing equation.
When using the option {"cell geometry": "pouch"}
the parameter \(A\) and \(V\) are computed automatically from the pouch dimensions, assuming a single-layer pouch cell, i.e. \(A\) is the total surface area of a single-layer pouch cell and \(V\) is the volume. The parameter \(h\) is still set by the “Total heat transfer coefficient [W.m-2.K-1]” parameter.
When using the option {"contact resistance": "true"}
the parameter “Contact resistance [Ohm]” must be specified to calculate the heating from contact resistance, which corresponds to \(R_{cr}\). “Cell volume [m3]” is \(V_{cell}\) within the governing equation. The default lumped model option is {"contact resistance": "false"}
.
The lumped thermal option can be selected as follows
[2]:
options = {"cell geometry": "arbitrary", "thermal": "lumped"}
arbitrary_lumped_model = pybamm.lithium_ion.DFN(options)
# OR
options = {"cell geometry": "pouch", "thermal": "lumped"}
pouch_lumped_model = pybamm.lithium_ion.DFN(options)
If no cell geometry is specified, the “arbitrary” cell geometry is used by default
[3]:
options = {"thermal": "lumped"}
model = pybamm.lithium_ion.DFN(options)
print("Cell geometry:", model.options["cell geometry"])
Cell geometry: arbitrary
The contact resistance option can be turned on via the following
[4]:
options = {"thermal": "lumped", "contact resistance": "true"}
model = pybamm.lithium_ion.DFN(options)
The default option for the lumped model does not include contact resistance.
[5]:
options = {"thermal": "lumped"}
model = pybamm.lithium_ion.DFN(options)
print("contact resistance:", model.options["contact resistance"])
contact resistance: false
Pouch cell models#
1D (through-cell) model#
The 1D model solves for \(T(x,t)\), capturing variations through the thickness of the cell, but ignoring variations in the other dimensions. The temperature is found as the solution of a partial differential equation, given here in dimensional terms
with boundary conditions
and initial condition
Here \(\lambda_k\) is the thermal conductivity of component \(k\), and the heat transfer coefficients \(h_{cn}\) and \(h_{cp}\) correspond to heat transfer at the large surface of the pouch on the side of the negative current collector, heat transfer at the large surface of the pouch on the side of the positive current collector, respectively. The heat source term \(Q\) is as described in the section on lumped models. The term \(Q_cool\) accounts for additional heat losses due to heat transfer at the sides of the pouch, as well as the tabs. This term is computed automatically by PyBaMM based on the cell geometry and heat transfer coefficients on the edges and tabs of the cell.
The relevant heat transfer parameters are: “Negative current collector surface heat transfer coefficient [W.m-2.K-1]” “Positive current collector surface heat transfer coefficient [W.m-2.K-1]” “Negative tab heat transfer coefficient [W.m-2.K-1]” “Positive tab heat transfer coefficient [W.m-2.K-1]” “Edge heat transfer coefficient [W.m-2.K-1]”
The 1D model is termed “x-full” (since it fully accounts for variation in the x direction) and can be selected as follows
[7]:
options = {"thermal": "x-full"}
model = pybamm.lithium_ion.DFN(options)
Higher dimensional pouch cell models#
These pouch cell thermal models ignore any variation in temperature through the thickness of the cell (x direction), and solve for \(T(y,z,t)\). It is therefore referred to as an “x-lumped” model. The temperature is found as the solution of a partial differential equation, given here in dimensional terms,
along with boundary conditions
at the negative tab,
at the positive tab, and
elsewhere. Again, an initial temperature \(T_0\) must be prescribed.
Here the heat source term is averaged in the x direction so that \(\bar{Q}=\bar{Q}(y,z)\). The parameter \(\lambda_{eff}\) is the effective thermal conductivity, computed as
The heat transfer coefficients \(h_{cn}\), \(h_{cp}\) and \(h_{egde}\) correspond to heat transfer at the large surface of the pouch on the side of the negative current collector, heat transfer at the large surface of the pouch on the side of the positive current collector, and heat transfer at the remaining, respectively.
The relevant heat transfer parameters are: “Negative current collector surface heat transfer coefficient [W.m-2.K-1]” “Positive current collector surface heat transfer coefficient [W.m-2.K-1]” “Negative tab heat transfer coefficient [W.m-2.K-1]” “Positive tab heat transfer coefficient [W.m-2.K-1]” “Edge heat transfer coefficient [W.m-2.K-1]”
The “2+1D” model can be selected as follows
[8]:
options = {
"current collector": "potential pair",
"dimensionality": 2,
"thermal": "x-lumped",
}
model = pybamm.lithium_ion.DFN(options)
Model usage#
Here we compare the “full” one-dimensional model with the lumped model for a pouch cell. We first set up our models, passing the relevant options, and then show how to adjust the parameters to so that the lumped and full models give the same behaviour
[9]:
full_thermal_model = pybamm.lithium_ion.SPMe(
{"thermal": "x-full"}, name="full thermal model"
)
lumped_thermal_model = pybamm.lithium_ion.SPMe(
{"thermal": "lumped"}, name="lumped thermal model"
)
models = [full_thermal_model, lumped_thermal_model]
We then pick our parameter set
[10]:
parameter_values = pybamm.ParameterValues("Marquis2019")
For the “full” model we use a heat transfer coefficient of \(5\, \text{Wm}^{-2}\text{K}^{-1}\) on the large surfaces of the pouch and zero heat transfer coefficient on the tabs and edges
[11]:
full_params = parameter_values.copy()
full_params.update(
{
"Negative current collector"
+ " surface heat transfer coefficient [W.m-2.K-1]": 5,
"Positive current collector"
+ " surface heat transfer coefficient [W.m-2.K-1]": 5,
"Negative tab heat transfer coefficient [W.m-2.K-1]": 0,
"Positive tab heat transfer coefficient [W.m-2.K-1]": 0,
"Edge heat transfer coefficient [W.m-2.K-1]": 0,
}
)
For the lumped model we set the “Total heat transfer coefficient [W.m-2.K-1]” parameter as well as the “Cell cooling surface area [m2]” parameter. Since the “full” model only accounts for cooling from the large surfaces of the pouch, we set the “Surface area for cooling” parameter to the area of the large surfaces of the pouch, and the total heat transfer coefficient to \(5\, \text{Wm}^{-2}\text{K}^{-1}\)
[12]:
A = parameter_values["Electrode width [m]"] * parameter_values["Electrode height [m]"]
lumped_params = parameter_values.copy()
lumped_params.update(
{
"Total heat transfer coefficient [W.m-2.K-1]": 5,
"Cell cooling surface area [m2]": 2 * A,
}
)
Let’s run simulations with both options and compare the results. For demonstration purposes we’ll increase the current to amplify the thermal effects
[13]:
params = [full_params, lumped_params]
# loop over the models and solve
sols = []
for model, param in zip(models, params):
param["Current function [A]"] = 3 * 0.68
sim = pybamm.Simulation(model, parameter_values=param)
sim.solve([0, 3600])
sols.append(sim.solution)
# plot
output_variables = [
"Voltage [V]",
"X-averaged cell temperature [K]",
"Cell temperature [K]",
]
pybamm.dynamic_plot(sols, output_variables)
# plot the results
pybamm.dynamic_plot(
sols,
[
"Volume-averaged cell temperature [K]",
"Volume-averaged total heating [W.m-3]",
"Current [A]",
"Voltage [V]",
],
)
[13]:
<pybamm.plotting.quick_plot.QuickPlot at 0x17f501e90>
For the lumped model, we can compare how the contact resistance affects the heating. To do so, we must set the "contact resistance"
option to "true"
and update the "Contact resistance [Ohm]"
parameter.
[7]:
model_no_contact_resistance = pybamm.lithium_ion.SPMe(
{"cell geometry": "arbitrary", "thermal": "lumped", "contact resistance": "false"},
name="lumped thermal model",
)
model_contact_resistance = pybamm.lithium_ion.SPMe(
{"cell geometry": "arbitrary", "thermal": "lumped", "contact resistance": "true"},
name="lumped thermal model with contact resistance",
)
models = [model_no_contact_resistance, model_contact_resistance]
We then choose a parameter set.
[8]:
parameter_values = pybamm.ParameterValues("Marquis2019")
lumped_params = parameter_values.copy()
lumped_params_contact_resistance = parameter_values.copy()
For the contact resistance model, we must specify a contact resistance greater than zero. The default is zero.
[9]:
lumped_params_contact_resistance.update(
{
"Contact resistance [Ohm]": 0.05,
}
)
The models and parameters are then used to solve for a 1C discharge.
[10]:
params = [lumped_params, lumped_params_contact_resistance]
sols = []
for model, param in zip(models, params):
sim = pybamm.Simulation(model, parameter_values=param)
sim.solve([0, 3600])
sols.append(sim.solution)
We can then compare the voltage and cell temperature and see the impact of the contact resistance.
[11]:
output_variables = [
"Voltage [V]",
"X-averaged cell temperature [K]",
"Cell temperature [K]",
]
pybamm.dynamic_plot(sols, output_variables)
[11]:
<pybamm.plotting.quick_plot.QuickPlot at 0x338900950>
References#
The relevant papers for this notebook are:
[14]:
pybamm.print_citations()
[1] 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.
[2] 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.
[3] 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.
[4] 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.
[5] 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.
[6] Robert Timms, Scott G Marquis, Valentin Sulzer, Colin P. Please, and S Jonathan Chapman. Asymptotic Reduction of a Lithium-ion Pouch Cell Model. SIAM Journal on Applied Mathematics, 81(3):765–788, 2021. doi:10.1137/20M1336898.