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

Lfp parameters #1209

Merged
merged 27 commits into from
Oct 25, 2020
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
976c66f
This is a test commit, please ignore it
dalbamont Apr 8, 2020
f47d630
Added parameters for LFP cathod - based on Prada 2013, Peyman, and La…
dalbamont May 2, 2020
7a5f151
Merging before adding LFP and A123 parameters
dalbamont May 2, 2020
7c5dc4c
Removed incorrect file
dalbamont May 2, 2020
be13aa9
Adjusted formating to agree with flake8
dalbamont May 2, 2020
eff587b
Merge pull request #1036 from pybamm-team/develop
rtimms Jun 1, 2020
66dc659
Merge pull request #1043 from pybamm-team/develop
tlestang Jun 9, 2020
ee2a54f
Merge pull request #1047 from pybamm-team/develop
rtimms Jun 12, 2020
dd26cc7
Merge pull request #1054 from pybamm-team/develop
tlestang Jun 12, 2020
09a3c08
Merge pull request #1095 from pybamm-team/develop
valentinsulzer Jul 1, 2020
b7da2cd
The state used to create the parameter evolution figures included in …
dalbamont Jul 8, 2020
23b2927
Merge branch 'develop' of https://github.com/pybamm-team/PyBaMM into …
dalbamont Jul 8, 2020
0e20e51
Merge branch 'develop' of https://github.com/pybamm-team/PyBaMM into …
dalbamont Jul 13, 2020
f00b8d1
Merge pull request #1139 from pybamm-team/develop
valentinsulzer Sep 7, 2020
f5b6479
Cleaning code charges, updating input files
dalbamont Sep 11, 2020
a56f477
Merge remote-tracking branch 'upstream/master' into cleaned
dalbamont Sep 11, 2020
803ba50
change to reaction rate
dalbamont Sep 11, 2020
cedd3d6
updating files to comply with PEP8
dalbamont Sep 16, 2020
c61f292
merge develop
valentinsulzer Oct 19, 2020
0efbcb7
Merge branch 'develop' into lfp-parameters
valentinsulzer Oct 22, 2020
20a9b92
add refs for parameters
valentinsulzer Oct 22, 2020
5c26f30
some cleaning up
valentinsulzer Oct 22, 2020
1b0c370
fix test
valentinsulzer Oct 22, 2020
b4e1325
ferran comments
valentinsulzer Oct 23, 2020
79b914f
Merge branch 'develop' of github.com:pybamm-team/PyBaMM into lfp-para…
valentinsulzer Oct 23, 2020
54844e5
changelog
valentinsulzer Oct 23, 2020
90250c4
codacy
valentinsulzer Oct 24, 2020
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
61 changes: 31 additions & 30 deletions examples/scripts/compare_spectral_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

# load model
# don't use new_copy
models = [pybamm.lithium_ion.DFN(name="Finite Volume"),
pybamm.lithium_ion.DFN(name="Spectral Volume")]
models = [
pybamm.lithium_ion.DFN(name="Finite Volume"),
pybamm.lithium_ion.DFN(name="Spectral Volume"),
]

# create geometry
geometries = [m.default_geometry for m in models]
Expand All @@ -24,32 +26,31 @@
var = pybamm.standard_spatial_vars
var_pts = {var.x_n: 1, var.x_s: 1, var.x_p: 1, var.r_n: 1, var.r_p: 1}
# the Finite Volume method also works on spectral meshes
meshes = [pybamm.Mesh(
geometry,
{
"negative particle": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh,
{"order": order}
),
"positive particle": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh,
{"order": order}
),
"negative electrode": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh,
{"order": order}
),
"separator": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh,
{"order": order}
),
"positive electrode": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh,
{"order": order}
),
"current collector": pybamm.SubMesh0D,
},
var_pts) for geometry in geometries]
meshes = [
pybamm.Mesh(
geometry,
{
"negative particle": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh, {"order": order}
),
"positive particle": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh, {"order": order}
),
"negative electrode": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh, {"order": order}
),
"separator": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh, {"order": order}
),
"positive electrode": pybamm.MeshGenerator(
pybamm.SpectralVolume1DSubMesh, {"order": order}
),
"current collector": pybamm.SubMesh0D,
},
var_pts,
)
for geometry in geometries
]

# discretise model
disc_fv = pybamm.Discretisation(meshes[0], models[0].default_spatial_methods)
Expand All @@ -61,8 +62,8 @@
"negative electrode": pybamm.SpectralVolume(order=order),
"separator": pybamm.SpectralVolume(order=order),
"positive electrode": pybamm.SpectralVolume(order=order),
"current collector": pybamm.ZeroDimensionalSpatialMethod()
}
"current collector": pybamm.ZeroDimensionalSpatialMethod(),
},
)

disc_fv.process_model(models[0])
Expand Down
37 changes: 31 additions & 6 deletions pybamm/CITATIONS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,15 @@ year={2019},
publisher={The Electrochemical Society}
}

@article{Mohtat2020,
author = {Mohtat, Peyman and Siegel, Jason B and Stefanopoulou, Anna G},
title = {{High C-rate Differential Expansion and Voltage Model for Li-ion Batteries}},
journal = {Submitted for publication},
year = {2019},
publisher={ECSarXiv}
@article{mohtat2020differential,
title={Differential Expansion and Voltage Model for Li-ion Batteries at Practical Charging Rates},
author={Mohtat, Peyman and Lee, Suhak and Sulzer, Valentin and Siegel, Jason B and Stefanopoulou, Anna G},
journal={Journal of The Electrochemical Society},
volume={167},
number={11},
pages={110561},
year={2020},
publisher={IOP Publishing}
}

@article{scikits-odes,
Expand Down Expand Up @@ -204,3 +207,25 @@ primaryClass={physics.app-ph},
year={2005},
publisher={IOP Publishing}
}

@article{lain2019design,
title={Design Strategies for High Power vs. High Energy Lithium Ion Cells},
author={Lain, Michael J and Brandon, James and Kendrick, Emma},
journal={Batteries},
volume={5},
number={4},
pages={64},
year={2019},
publisher={Multidisciplinary Digital Publishing Institute}
}

@article{prada2013simplified,
title={A simplified electrochemical and thermal aging model of LiFePO4-graphite Li-ion batteries: power and capacity fade simulations},
author={Prada, Eric and Di Domenico, D and Creff, Y and Bernard, J and Sauvant-Moynot, Val{\'e}rie and Huet, Fran{\c{c}}ois},
journal={Journal of The Electrochemical Society},
volume={160},
number={4},
pages={A616},
year={2013},
publisher={IOP Publishing}
}
75 changes: 40 additions & 35 deletions pybamm/expression_tree/operations/evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

import numbers
from platform import system

if system() != "Windows":
import jax

from jax.config import config

config.update("jax_enable_x64", True)


Expand Down Expand Up @@ -95,30 +97,35 @@ def find_symbols(symbol, constant_symbols, variable_symbols, to_dense=False):
dummy_eval_left = symbol.children[0].evaluate_for_shape()
dummy_eval_right = symbol.children[1].evaluate_for_shape()
if not to_dense and scipy.sparse.issparse(dummy_eval_left):
symbol_str = "{0}.multiply({1})"\
.format(children_vars[0], children_vars[1])
symbol_str = "{0}.multiply({1})".format(
children_vars[0], children_vars[1]
)
elif not to_dense and scipy.sparse.issparse(dummy_eval_right):
symbol_str = "{1}.multiply({0})"\
.format(children_vars[0], children_vars[1])
symbol_str = "{1}.multiply({0})".format(
children_vars[0], children_vars[1]
)
else:
symbol_str = "{0} * {1}".format(children_vars[0], children_vars[1])
elif isinstance(symbol, pybamm.Division):
dummy_eval_left = symbol.children[0].evaluate_for_shape()
if not to_dense and scipy.sparse.issparse(dummy_eval_left):
symbol_str = "{0}.multiply(1/{1})"\
.format(children_vars[0], children_vars[1])
symbol_str = "{0}.multiply(1/{1})".format(
children_vars[0], children_vars[1]
)
else:
symbol_str = "{0} / {1}".format(children_vars[0], children_vars[1])

elif isinstance(symbol, pybamm.Inner):
dummy_eval_left = symbol.children[0].evaluate_for_shape()
dummy_eval_right = symbol.children[1].evaluate_for_shape()
if not to_dense and scipy.sparse.issparse(dummy_eval_left):
symbol_str = "{0}.multiply({1})"\
.format(children_vars[0], children_vars[1])
symbol_str = "{0}.multiply({1})".format(
children_vars[0], children_vars[1]
)
elif not to_dense and scipy.sparse.issparse(dummy_eval_right):
symbol_str = "{1}.multiply({0})"\
.format(children_vars[0], children_vars[1])
symbol_str = "{1}.multiply({0})".format(
children_vars[0], children_vars[1]
)
else:
symbol_str = "{0} * {1}".format(children_vars[0], children_vars[1])

Expand Down Expand Up @@ -294,18 +301,20 @@ def __init__(self, symbol):
# extract constants in generated function
for i, symbol_id in enumerate(constants.keys()):
const_name = id_to_python_variable(symbol_id, True)
python_str = '{} = constants[{}]\n'.format(const_name, i) + python_str
python_str = "{} = constants[{}]\n".format(const_name, i) + python_str

# constants passed in as an ordered dict, convert to list
self._constants = list(constants.values())

# indent code
python_str = ' ' + python_str
python_str = python_str.replace('\n', '\n ')
python_str = " " + python_str
python_str = python_str.replace("\n", "\n ")

# add function def to first line
python_str = 'def evaluate(constants, t=None, y=None, '\
'y_dot=None, inputs=None, known_evals=None):\n' + python_str
python_str = (
"def evaluate(constants, t=None, y=None, "
"y_dot=None, inputs=None, known_evals=None):\n" + python_str
)

# calculate the final variable that will output the result of calling `evaluate`
# on `symbol`
Expand All @@ -315,21 +324,18 @@ def __init__(self, symbol):

# add return line
if symbol.is_constant() and isinstance(result_value, numbers.Number):
python_str = python_str + '\n return ' + str(result_value)
python_str = python_str + "\n return " + str(result_value)
else:
python_str = python_str + '\n return ' + result_var
python_str = python_str + "\n return " + result_var

# store a copy of examine_jaxpr
python_str = python_str + \
'\nself._evaluate = evaluate'
python_str = python_str + "\nself._evaluate = evaluate"

self._python_str = python_str
self._symbol = symbol

# compile and run the generated python code,
compiled_function = compile(
python_str, result_var, "exec"
)
compiled_function = compile(python_str, result_var, "exec")
exec(compiled_function)

def evaluate(self, t=None, y=None, y_dot=None, inputs=None, known_evals=None):
Expand Down Expand Up @@ -377,7 +383,7 @@ def __init__(self, symbol):
constants, python_str = pybamm.to_python(symbol, debug=False, to_dense=True)

# replace numpy function calls to jax numpy calls
python_str = python_str.replace('np.', 'jax.numpy.')
python_str = python_str.replace("np.", "jax.numpy.")

# convert all numpy constants to device vectors
for symbol_id in constants:
Expand All @@ -387,18 +393,20 @@ def __init__(self, symbol):
# extract constants in generated function
for i, symbol_id in enumerate(constants.keys()):
const_name = id_to_python_variable(symbol_id, True)
python_str = '{} = constants[{}]\n'.format(const_name, i) + python_str
python_str = "{} = constants[{}]\n".format(const_name, i) + python_str

# constants passed in as an ordered dict, convert to list
self._constants = list(constants.values())

# indent code
python_str = ' ' + python_str
python_str = python_str.replace('\n', '\n ')
python_str = " " + python_str
python_str = python_str.replace("\n", "\n ")

# add function def to first line
python_str = 'def evaluate_jax(constants, t=None, y=None, '\
'y_dot=None, inputs=None, known_evals=None):\n' + python_str
python_str = (
"def evaluate_jax(constants, t=None, y=None, "
"y_dot=None, inputs=None, known_evals=None):\n" + python_str
)

# calculate the final variable that will output the result of calling `evaluate`
# on `symbol`
Expand All @@ -408,18 +416,15 @@ def __init__(self, symbol):

# add return line
if symbol.is_constant() and isinstance(result_value, numbers.Number):
python_str = python_str + '\n return ' + str(result_value)
python_str = python_str + "\n return " + str(result_value)
else:
python_str = python_str + '\n return ' + result_var
python_str = python_str + "\n return " + result_var

# store a copy of examine_jaxpr
python_str = python_str + \
'\nself._evaluate_jax = evaluate_jax'
python_str = python_str + "\nself._evaluate_jax = evaluate_jax"

# compile and run the generated python code,
compiled_function = compile(
python_str, result_var, "exec"
)
compiled_function = compile(python_str, result_var, "exec")
exec(compiled_function)

self._jit_evaluate = jax.jit(self._evaluate_jax, static_argnums=(0, 4, 5))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Graphite anode parameters

Parameters for a graphite anode, from the papers:

> Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of a lithium-ion battery I. determination of parameters." Journal of the Electrochemical Society 162.9 (2015): A1836-A1848.

>Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of a lithium-ion battery II. Model validation." Journal of The Electrochemical Society 162.9 (2015): A1849-A1857.

The fits to data for the electrode and electrolyte properties are those provided
by Dr. Simon O’Kane in the paper:

> Richardson, Giles, et. al. "Generalised single particle models for high-rate operation of graded lithium-ion electrodes: Systematic derivation and validation." Electrochemica Acta 339 (2020): 135862

Some parameters have been adjusted to better fit experimental data from the paper

> Severson, K. A., Attia, P. M., Jin, N., Perkins, N., Jiang, B., Yang, Z., ... & Bazant, M. Z. (2019). Data-driven prediction of battery cycle life before capacity degradation. Nature Energy, 4(5), 383-391.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from pybamm import exp, constants


def graphite_diffusivity_Ecker2015(sto, T):
"""
Graphite diffusivity as a function of stochiometry [1, 2, 3].

References
----------
.. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of
a lithium-ion battery i. determination of parameters." Journal of the
Electrochemical Society 162.9 (2015): A1836-A1848.
.. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of
a lithium-ion battery ii. model validation." Journal of The Electrochemical
Society 162.9 (2015): A1849-A1857.
.. [3] Richardson, Giles, et. al. "Generalised single particle models for
high-rate operation of graded lithium-ion electrodes: Systematic derivation
and validation." Electrochemica Acta 339 (2020): 135862

Parameters
----------
sto: :class:`pybamm.Symbol`
Electrode stochiometry
T: :class:`pybamm.Symbol`
Dimensional temperature

Returns
-------
:class:`pybamm.Symbol`
Solid diffusivity
"""

D_ref = 8.4e-13 * exp(-11.3 * sto) + 8.2e-15
E_D_s = 3.03e4
arrhenius = exp(-E_D_s / (constants.R * T)) * exp(E_D_s / (constants.R * 296))

return D_ref * arrhenius
Loading