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

Many-Particle Models #1529

Merged
merged 82 commits into from
Jul 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
0d94d25
added BasicMPM class to lithium_ion
tobykirk Jun 17, 2020
fbfe2d2
Merge branch 'develop' into add-PSD-models
tobykirk Jun 17, 2020
095484c
expanded output variables
tobykirk Jun 18, 2020
ec61fb3
rename model class
tobykirk Jun 24, 2020
86a21b5
renamed PSD model file
tobykirk Jun 24, 2020
bf9949b
Merge branch 'develop' into add-PSD-models
tobykirk Jun 24, 2020
1360cc5
added interp for 1D ProcessedVariables in particle-size domain R
tobykirk Jun 24, 2020
274413c
fixed style to black
tobykirk Jun 25, 2020
6b081c2
Merge branch 'develop' into add-PSD-models
tobykirk Jun 26, 2020
4bbc39b
added PSDModel incorporating submodel structure
tobykirk Jul 13, 2020
ad2b172
tidied up PSDModel
tobykirk Jul 13, 2020
1a97965
Merge branch 'develop' into add-PSD-models
tobykirk Jul 13, 2020
a2b7df8
quick plotting for 2D vars of particle size
tobykirk Jul 13, 2020
534b60b
tidied up PSD output variables
tobykirk Jul 14, 2020
8487ef9
added fast diffusion PSD submodels
tobykirk Jul 14, 2020
9eb72e4
Default geometry and meshes etc for PSDs
tobykirk Jul 16, 2020
0c2850f
added R-average
tobykirk Jul 17, 2020
5f489df
fied typos and style
tobykirk Jul 17, 2020
5d938a8
added ManyPSD submodels, and the option to DFN
tobykirk Jul 17, 2020
6e41c07
added option to use SPM as MPM
tobykirk Jul 17, 2020
61ee854
added PSD with fast diffusion submodel to DFN
tobykirk Jul 17, 2020
af48cf0
add distribution parameters to Marquis2019 set
tobykirk Jul 30, 2020
010ac48
automatic distribution normalising
tobykirk Aug 18, 2020
4525057
changed event tolerance
tobykirk Nov 13, 2020
11f1188
revert submodel selection changes to SPM
tobykirk Jun 1, 2021
af4e016
fix SPM interface submodel selection
tobykirk Jun 1, 2021
686c5e2
fix tests
tobykirk Jun 1, 2021
7c91e3f
Merge branch 'develop' into many-particle-models
tobykirk Jun 1, 2021
683f008
fixed MPM
tobykirk Jun 2, 2021
5784af9
name changes to domains, options, spatial vars
tobykirk Jun 4, 2021
65d568f
refactor of size distribution submodels
tobykirk Jun 4, 2021
0a379ab
fix fast diffusion MP submodels and output vars
tobykirk Jun 4, 2021
ba8988b
fix tests
tobykirk Jun 4, 2021
003bff6
added citations to Kirk et al 2020
tobykirk Jun 4, 2021
9050cf2
add unit tests for MPM and submodels
tobykirk Jun 8, 2021
b1a33f8
added standard integration tests for MPM
tobykirk Jun 8, 2021
df13141
change MPM submodels to surface form
tobykirk Jun 10, 2021
415ee98
delete plots_of_MPM script
tobykirk Jun 10, 2021
a6aa477
remove test for Fickian MPDFN
tobykirk Jun 10, 2021
b7d95d8
Merge branch 'develop' into many-particle-models
tobykirk Jun 10, 2021
ea72822
fixed surface area for MP models and tests
tobykirk Jun 11, 2021
31855e7
incompatible options with size distributions
tobykirk Jun 11, 2021
23b9f4a
rename mean radii variables
tobykirk Jun 11, 2021
582d56b
Merge branch 'develop' into many-particle-models
tobykirk Jun 15, 2021
ea1c372
added voltage control to MPM
tobykirk Jun 15, 2021
57b706a
added more distribution output vars
tobykirk Jun 15, 2021
8f4b30e
added doc index files for MPM and submodels
tobykirk Jun 15, 2021
a11b5ec
fix distribution output variables
tobykirk Jun 15, 2021
a6582b6
add output vars to fix lead acid tests
tobykirk Jun 30, 2021
e2a0840
added Kirk2021 citation
tobykirk Jun 30, 2021
e0de928
added MPM notebook
tobykirk Jun 30, 2021
95aecaf
Merge branch 'develop' into many-particle-models
tobykirk Jun 30, 2021
683674c
removed the 'ManyDistributions' submodels
tobykirk Jun 30, 2021
532d47a
revert DFN to develop
tobykirk Jun 30, 2021
b3c12eb
remove size distributions from Marquis param set
tobykirk Jun 30, 2021
f93fa09
remove test for 'FastManyDistributions' submodel
tobykirk Jun 30, 2021
f00d86d
change name of R_average
tobykirk Jul 5, 2021
e081d08
fix exchange current density tests
tobykirk Jul 5, 2021
c955d72
add function get_size_distribution_parameters
tobykirk Jul 6, 2021
23fa913
refactor interface distribution variables
tobykirk Jul 6, 2021
009752f
reduce code duplication in quick_plot
tobykirk Jul 6, 2021
a8e5c16
Merge branch 'develop' into add-mpm
tobykirk Jul 6, 2021
2ca98d4
remove some mpm tests
tobykirk Jul 6, 2021
b9eb06e
change MPM init and reduce tests
tobykirk Jul 7, 2021
339b9f0
moved particle size params to geometric parameters
tobykirk Jul 7, 2021
c2f284b
Merge branch 'develop' into add-mpm
tobykirk Jul 7, 2021
494bf0c
Merge branch 'develop' into add-mpm
tobykirk Jul 16, 2021
82ea288
move default standard deviations
tobykirk Jul 16, 2021
edf67bb
change definition of particle flux
tobykirk Jul 16, 2021
de5afe3
fix notebooks
tobykirk Jul 16, 2021
3fbe86a
add broadcast tests with particle size
tobykirk Jul 20, 2021
c7472ec
add particle size processed variable tests
tobykirk Jul 20, 2021
3e9261d
add mpm tests for coverage
tobykirk Jul 20, 2021
85989da
remove untested code for size distr in DFN
tobykirk Jul 22, 2021
7b87152
tests to increase coverage
tobykirk Jul 22, 2021
681826a
Merge branch 'develop' into add-mpm
tobykirk Jul 27, 2021
8a964b3
update changelog
tobykirk Jul 27, 2021
49a00d6
Merge branch 'develop' into add-mpm
valentinsulzer Jul 28, 2021
7c50b99
reduced code duplication in processed var tests
tobykirk Jul 29, 2021
57f9e08
Merge remote-tracking branch 'upstream/develop' into add-mpm
tobykirk Jul 29, 2021
515590d
remove unusued variable to fix codacy
tobykirk Jul 29, 2021
34700c0
Merge branch 'develop' into add-mpm
tobykirk Jul 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
## Features

- Added temperature dependence on electrode electronic conductivity ([#1570](https://github.com/pybamm-team/PyBaMM/pull/1570))
- Added fitted expressions for OCPs for the Chen2020 parameter set ([#1526](https://github.com/pybamm-team/PyBaMM/pull/1526))
- Added a new lithium-ion model `MPM` or Many-Particle Model, with a distribution of particle sizes in each electrode. ([#1529](https://github.com/pybamm-team/PyBaMM/pull/1529))
- Added 2 new submodels for lithium transport in a size distribution of electrode particles: Fickian diffusion (`FickianSingleSizeDistribution`) and uniform concentration profile (`FastSingleSizeDistribution`). ([#1529](https://github.com/pybamm-team/PyBaMM/pull/1529))
- Added a "particle size" domain to the default lithium-ion geometry, including plotting capabilities (`QuickPlot`) and processing of variables (`ProcessedVariable`). ([#1529](https://github.com/pybamm-team/PyBaMM/pull/1529))
- Added fitted expressions for OCPs for the Chen2020 parameter set ([#1526](https://github.com/pybamm-team/PyBaMM/pull/1497))
- Added `initial_soc` argument to `Simualtion.solve` for specifying the initial SOC when solving a model ([#1512](https://github.com/pybamm-team/PyBaMM/pull/1512))
- Added `print_name` to some symbols ([#1495](https://github.com/pybamm-team/PyBaMM/pull/1495), [#1497](https://github.com/pybamm-team/PyBaMM/pull/1497))
- Added Base Parameters class and SymPy in dependencies ([#1495](https://github.com/pybamm-team/PyBaMM/pull/1495))
Expand Down
2 changes: 2 additions & 0 deletions docs/source/expression_tree/unary_operator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ Unary Operators

.. autofunction:: pybamm.r_average

.. autofunction:: pybamm.size_average

.. autofunction:: pybamm.z_average

.. autofunction:: pybamm.yz_average
Expand Down
1 change: 1 addition & 0 deletions docs/source/models/lithium_ion/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Lithium-ion Models
base_lithium_ion_model
spm
spme
mpm
dfn
newman_tobias
yang2017
5 changes: 5 additions & 0 deletions docs/source/models/lithium_ion/mpm.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Many Particle Model (MPM)
===========================

.. autoclass:: pybamm.lithium_ion.MPM
:members:
1 change: 1 addition & 0 deletions docs/source/models/submodels/particle/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Particle
fickian_many_particles
polynomial_single_particle
polynomial_many_particles
size_distribution/index
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Particle Size Distribution Base Model
=====================================

.. autoclass:: pybamm.particle.BaseSizeDistribution
:members:

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fast Single Size Distribution
=============================

.. autoclass:: pybamm.particle.FastSingleSizeDistribution
:members:
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Fickian Single Size Distribution
================================

.. autoclass:: pybamm.particle.FickianSingleSizeDistribution
:members:

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Particle Size Distribution
==========================

.. toctree::
:maxdepth: 1

base_distribution
fickian_single_distribution
fast_single_distribution
983 changes: 983 additions & 0 deletions examples/notebooks/models/MPM.ipynb

Large diffs are not rendered by default.

27 changes: 11 additions & 16 deletions examples/notebooks/using-submodels.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"In the Single Particle Model, the overpotential can be obtianed by inverting the Butler-Volmer relation, so we choose the `InverseButlerVolmer` submodel for the interface, with the \"main\" lithium-ion reaction. Because of how the current is implemented, we also need to separately specify the `CurrentForInverseButlerVolmer` submodel"
"In the Single Particle Model, the overpotential can be obtianed by inverting the Butler-Volmer relation, so we choose the `InverseButlerVolmer` submodel for the interface, with the \"main\" lithium-ion reaction (and default lithium ion options). Because of how the current is implemented, we also need to separately specify the `CurrentForInverseButlerVolmer` submodel"
]
},
{
Expand All @@ -414,10 +414,14 @@
"source": [
"model.submodels[\n",
" \"negative interface\"\n",
"] = pybamm.interface.InverseButlerVolmer(model.param, \"Negative\", \"lithium-ion main\")\n",
"] = pybamm.interface.InverseButlerVolmer(\n",
" model.param, \"Negative\", \"lithium-ion main\", options=model.options\n",
")\n",
"model.submodels[\n",
" \"positive interface\"\n",
"] = pybamm.interface.InverseButlerVolmer(model.param, \"Positive\", \"lithium-ion main\")\n",
"] = pybamm.interface.InverseButlerVolmer(\n",
" model.param, \"Positive\", \"lithium-ion main\", options=model.options\n",
")\n",
"model.submodels[\n",
" \"negative interface current\"\n",
"] = pybamm.interface.CurrentForInverseButlerVolmer(\n",
Expand Down Expand Up @@ -540,23 +544,14 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
"display_name": "Python 2.7.17 64-bit",
"name": "python375jvsc74a57bd0fd69f43f58546b570e94fd7eba7b65e6bcc7a5bbc4eab0408017d18902915d69"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5"
"version": ""
}
},
"nbformat": 4,
"nbformat_minor": 2
}
}
4 changes: 2 additions & 2 deletions examples/scripts/custom_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
model.param, "Positive", "uniform profile"
)
model.submodels["negative interface"] = pybamm.interface.InverseButlerVolmer(
model.param, "Negative", "lithium-ion main"
model.param, "Negative", "lithium-ion main", options=model.options
)
model.submodels["positive interface"] = pybamm.interface.InverseButlerVolmer(
model.param, "Positive", "lithium-ion main"
model.param, "Positive", "lithium-ion main", options=model.options
)
model.submodels[
"negative interface current"
Expand Down
25 changes: 25 additions & 0 deletions pybamm/CITATIONS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,31 @@
publisher={Elsevier}
}

@misc{Kirk2020,
author = {Kirk, Toby L. and Evans, Jack and Please, Colin P. and Chapman, S. Jonathan},
title = {Modelling electrode heterogeneity in lithium-ion batteries: unimodal and bimodal particle-size distributions},
year = {2020},
howpublished = {arXiv:2006.12208},
eprint = {2006.12208},
url = {https://arxiv.org/abs/2006.12208},
archiveprefix = {arXiv},
primaryclass = {physics.app-ph},
}

@article{Kirk2021,
author = {Toby L. Kirk and Colin P. Please and S. Jon Chapman},
title = {Physical Modelling of the Slow Voltage Relaxation Phenomenon in Lithium-Ion Batteries},
journal = {Journal of The Electrochemical Society},
year = 2021,
month = {jun},
publisher = {The Electrochemical Society},
volume = {168},
number = {6},
pages = {060554},
doi = {10.1149/1945-7111/ac0bf7},
url = {https://doi.org/10.1149/1945-7111/ac0bf7},
}

@article{Xu2019,
title={Evolution of Dead Lithium Growth in Lithium Metal Batteries: Experimentally Validated Model of the Apparent Capacity Loss},
author={Xu, Shanshan and Chen, Kuan-Hung and Dasgupta, Neil P and Siegel, Jason B and Stefanopoulou, Anna G},
Expand Down
1 change: 1 addition & 0 deletions pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def version(formatted=False):
from .parameters.thermal_parameters import thermal_parameters, ThermalParameters
from .parameters.lithium_ion_parameters import LithiumIonParameters
from .parameters.lead_acid_parameters import LeadAcidParameters
from .parameters.size_distribution_parameters import *
from .parameters import parameter_sets

#
Expand Down
55 changes: 45 additions & 10 deletions pybamm/expression_tree/broadcasts.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,29 +104,49 @@ def check_and_set_domains(
self, child, broadcast_type, broadcast_domain, broadcast_auxiliary_domains
):
"""See :meth:`Broadcast.check_and_set_domains`"""
# Can only do primary broadcast from current collector to electrode or particle
# or from electrode to particle. Note current collector to particle *is* allowed
# Can only do primary broadcast from current collector to electrode,
# particle-size or particle or from electrode to particle-size or particle.
# Note e.g. current collector to particle *is* allowed
if child.domain == []:
pass
elif child.domain == ["current collector"] and broadcast_domain[0] not in [
"negative electrode",
"separator",
"positive electrode",
"negative particle size",
"positive particle size",
"negative particle",
"positive particle",
]:
raise pybamm.DomainError(
"""Primary broadcast from current collector domain must be to electrode
or separator or particle domains"""
or separator or particle or particle size domains"""
)
elif (
child.domain[0]
in [
"negative electrode",
"separator",
"positive electrode",
]
and broadcast_domain[0] not in [
"negative particle",
"positive particle",
"negative particle size",
"positive particle size",
]
):
raise pybamm.DomainError(
"""Primary broadcast from electrode or separator must be to particle
or particle size domains"""
)
elif child.domain[0] in [
"negative electrode",
"separator",
"positive electrode",
"negative particle size",
"positive particle size",
] and broadcast_domain[0] not in ["negative particle", "positive particle"]:
raise pybamm.DomainError(
"""Primary broadcast from electrode or separator must be to particle
domains"""
"""Primary broadcast from particle size domain must be to particle
domain"""
)
elif child.domain[0] in ["negative particle", "positive particle"]:
raise pybamm.DomainError("Cannot do primary broadcast from particle domain")
Expand Down Expand Up @@ -211,14 +231,29 @@ def check_and_set_domains(
if child.domain[0] in [
"negative particle",
"positive particle",
] and broadcast_domain[0] not in [
"negative particle size",
"positive particle size",
"negative electrode",
"separator",
"positive electrode",
]:
raise pybamm.DomainError(
"""Secondary broadcast from particle domain must be to particle-size,
electrode or separator domains"""
)
if child.domain[0] in [
"negative particle size",
"positive particle size",
] and broadcast_domain[0] not in [
"negative electrode",
"separator",
"positive electrode",
"current collector"
]:
raise pybamm.DomainError(
"""Secondary broadcast from particle domain must be to electrode or
separator domains"""
"""Secondary broadcast from particle size domain must be to
electrode or separator or current collector domains"""
)
elif child.domain[0] in [
"negative electrode",
Expand Down
71 changes: 69 additions & 2 deletions pybamm/expression_tree/unary_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,10 +1272,16 @@ def x_average(symbol):
# Even if domain is "negative electrode", "separator", or
# "positive electrode", and we know l, we still compute it as Integral(1, x)
# as this will be easier to identify for simplifications later on
if symbol.domain == ["negative particle"]:
if (
symbol.domain == ["negative particle"] or
symbol.domain == ["negative particle size"]
):
x = pybamm.standard_spatial_vars.x_n
l = geo.l_n
elif symbol.domain == ["positive particle"]:
elif (
symbol.domain == ["positive particle"] or
symbol.domain == ["positive particle size"]
):
x = pybamm.standard_spatial_vars.x_p
l = geo.l_p
else:
Expand Down Expand Up @@ -1421,6 +1427,67 @@ def r_average(symbol):
return Integral(symbol, r) / Integral(v, r)


def size_average(symbol):
"""convenience function for averaging over particle size R using the area-weighted
particle-size distribution.

Parameters
----------
symbol : :class:`pybamm.Symbol`
The function to be averaged
Returns
-------
:class:`Symbol`
the new averaged symbol
"""
# Can't take average if the symbol evaluates on edges
if symbol.evaluates_on_edges("primary"):
raise ValueError(
"""Can't take the size-average of a symbol that evaluates on edges"""
)

# If symbol doesn't have a domain, or doesn't have "negative particle size"
# or "positive particle size" as a domain, it's average value is itself
if symbol.domain == [] or not any(
domain in [["negative particle size"], ["positive particle size"]]
for domain in list(symbol.domains.values())
):
new_symbol = symbol.new_copy()
new_symbol.parent = None
return new_symbol

# If symbol is a primary broadcast to "particle size", take the orphan
elif isinstance(symbol, pybamm.PrimaryBroadcast) and symbol.domain in [
["negative particle size"], ["positive particle size"]
]:
return symbol.orphans[0]
# If symbol is a secondary broadcast to "particle size" from "particle",
# take the orphan
elif (
isinstance(symbol, pybamm.SecondaryBroadcast) and
symbol.domains["secondary"] in [
["negative particle size"], ["positive particle size"]
]
):
return symbol.orphans[0]
# Otherwise, perform the integration in R
else:
R = pybamm.SpatialVariable(
"R",
domain=symbol.domain,
auxiliary_domains=symbol.auxiliary_domains,
coord_sys="cartesian",
)
geo = pybamm.geometric_parameters
if ["negative particle size"] in list(symbol.domains.values()):
f_a_dist = geo.f_a_dist_n(R)
elif ["positive particle size"] in list(symbol.domains.values()):
f_a_dist = geo.f_a_dist_p(R)

# take average using Integral and distribution f_a_dist
return Integral(f_a_dist * symbol, R) / Integral(f_a_dist, R)


def boundary_value(symbol, side):
"""
convenience function for creating a :class:`pybamm.BoundaryValue`
Expand Down
Loading