Skip to content

Commit

Permalink
Merge pull request #1121 from ferranbrosa/issue-983-half-cell
Browse files Browse the repository at this point in the history
Issue 983 half cell
  • Loading branch information
valentinsulzer authored Aug 11, 2020
2 parents dd37a7f + e296965 commit c229326
Show file tree
Hide file tree
Showing 19 changed files with 922 additions and 9 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## Features


- Added Modulo, Floor and Ceiling operators ([#1121](https://github.com/pybamm-team/PyBaMM/pull/1121))
- Added DFN model for a half cell ([#1121](https://github.com/pybamm-team/PyBaMM/pull/1121))
- Automatically compute surface area per unit volume based on particle shape for li-ion models ([#1120])(https://github.com/pybamm-team/PyBaMM/pull/1120)
- Added "R-averaged particle concentration" variables ([#1118](https://github.com/pybamm-team/PyBaMM/pull/1118))
- Added support for sensitivity calculations to the casadi solver ([#1109](https://github.com/pybamm-team/PyBaMM/pull/1109))
Expand Down
65 changes: 65 additions & 0 deletions examples/scripts/DFN_half_cell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#
# Example showing how to load and solve the DFN for the half cell
#

import pybamm
import numpy as np

pybamm.set_logging_level("INFO")

# load model
options = {"working electrode": "positive"}
model = pybamm.lithium_ion.BasicDFNHalfCell(options=options)

# create geometry
geometry = model.default_geometry

# load parameter values
chemistry = pybamm.parameter_sets.Chen2020
param = pybamm.ParameterValues(chemistry=chemistry)

# add lithium counter electrode parameter values
param.update(
{
"Lithium counter electrode exchange-current density [A.m-2]": 12.6,
"Lithium counter electrode conductivity [S.m-1]": 1.0776e7,
"Lithium counter electrode thickness [m]": 250e-6,
},
check_already_exists=False,
)

# process model and geometry
param.process_model(model)
param.process_geometry(geometry)

# set mesh
var = pybamm.standard_spatial_vars
var_pts = {var.x_n: 30, var.x_s: 30, var.x_p: 30, var.r_n: 10, var.r_p: 10}
mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts)

# discretise model
disc = pybamm.Discretisation(mesh, model.default_spatial_methods)
disc.process_model(model)

# solve model
t_eval = np.linspace(0, 3800, 1000)
solver = pybamm.CasadiSolver(mode="fast", atol=1e-6, rtol=1e-3)
solution = solver.solve(model, t_eval)

# plot
plot = pybamm.QuickPlot(
solution,
[
"Negative particle surface concentration [mol.m-3]",
"Electrolyte concentration [mol.m-3]",
"Positive particle surface concentration [mol.m-3]",
"Current [A]",
"Negative electrode potential [V]",
"Electrolyte potential [V]",
"Positive electrode potential [V]",
"Terminal voltage [V]",
],
time_unit="seconds",
spatial_unit="um",
)
plot.dynamic_plot()
40 changes: 40 additions & 0 deletions pybamm/expression_tree/binary_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,46 @@ def _binary_evaluate(self, left, right):
return left < right


class Modulo(BinaryOperator):
"Calculates the remainder of an integer division"

def __init__(self, left, right):
super().__init__("%", left, right)

def _diff(self, variable):
""" See :meth:`pybamm.Symbol._diff()`. """
# apply chain rule and power rule
left, right = self.orphans
# derivative if variable is in the base
diff = left.diff(variable)
# derivative if variable is in the right term (rare, check separately to avoid
# unecessarily big tree)
if any(variable.id == x.id for x in right.pre_order()):
diff += - pybamm.Floor(left / right) * right.diff(variable)
return diff

def _binary_jac(self, left_jac, right_jac):
""" See :meth:`pybamm.BinaryOperator._binary_jac()`. """
# apply chain rule and power rule
left, right = self.orphans
if left.evaluates_to_number() and right.evaluates_to_number():
return pybamm.Scalar(0)
elif right.evaluates_to_number():
return left_jac
elif left.evaluates_to_number():
return - right_jac * pybamm.Floor(left / right)
else:
return left_jac - right_jac * pybamm.Floor(left / right)

def __str__(self):
""" See :meth:`pybamm.Symbol.__str__()`. """
return "{!s} mod {!s}".format(self.left, self.right)

def _binary_evaluate(self, left, right):
""" See :meth:`pybamm.BinaryOperator._binary_evaluate()`. """
return left % right


class Minimum(BinaryOperator):
" Returns the smaller of two objects "

Expand Down
6 changes: 6 additions & 0 deletions pybamm/expression_tree/operations/convert_to_casadi.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def _convert(self, symbol, t, y, y_dot, inputs):
converted_left = self.convert(left, t, y, y_dot, inputs)
converted_right = self.convert(right, t, y, y_dot, inputs)

if isinstance(symbol, pybamm.Modulo):
return casadi.fmod(converted_left, converted_right)
if isinstance(symbol, pybamm.Minimum):
return casadi.fmin(converted_left, converted_right)
if isinstance(symbol, pybamm.Maximum):
Expand All @@ -88,6 +90,10 @@ def _convert(self, symbol, t, y, y_dot, inputs):
converted_child = self.convert(symbol.child, t, y, y_dot, inputs)
if isinstance(symbol, pybamm.AbsoluteValue):
return casadi.fabs(converted_child)
if isinstance(symbol, pybamm.Floor):
return casadi.floor(converted_child)
if isinstance(symbol, pybamm.Ceiling):
return casadi.ceil(converted_child)
return symbol._unary_evaluate(converted_child)

elif isinstance(symbol, pybamm.Function):
Expand Down
6 changes: 6 additions & 0 deletions pybamm/expression_tree/symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,12 @@ def __abs__(self):
pybamm.AbsoluteValue(self), keep_domains=True
)

def __mod__(self, other):
"""return an :class:`Modulo` object"""
return pybamm.simplify_if_constant(
pybamm.Modulo(self, other), keep_domains=True
)

def diff(self, variable):
"""
Differentiate a symbol with respect to a variable. For any symbol that can be
Expand Down
46 changes: 46 additions & 0 deletions pybamm/expression_tree/unary_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,52 @@ def _unary_evaluate(self, child):
return np.sign(child)


class Floor(UnaryOperator):
"""A node in the expression tree representing an `floor` operator
**Extends:** :class:`UnaryOperator`
"""

def __init__(self, child):
""" See :meth:`pybamm.UnaryOperator.__init__()`. """
super().__init__("floor", child)

def diff(self, variable):
""" See :meth:`pybamm.Symbol.diff()`. """
return pybamm.Scalar(0)

def _unary_jac(self, child_jac):
""" See :meth:`pybamm.UnaryOperator._unary_jac()`. """
return pybamm.Scalar(0)

def _unary_evaluate(self, child):
""" See :meth:`UnaryOperator._unary_evaluate()`. """
return np.floor(child)


class Ceiling(UnaryOperator):
"""A node in the expression tree representing a `ceil` operator
**Extends:** :class:`UnaryOperator`
"""

def __init__(self, child):
""" See :meth:`pybamm.UnaryOperator.__init__()`. """
super().__init__("ceil", child)

def diff(self, variable):
""" See :meth:`pybamm.Symbol.diff()`. """
return pybamm.Scalar(0)

def _unary_jac(self, child_jac):
""" See :meth:`pybamm.UnaryOperator._unary_jac()`. """
return pybamm.Scalar(0)

def _unary_evaluate(self, child):
""" See :meth:`UnaryOperator._unary_evaluate()`. """
return np.ceil(child)


class Index(UnaryOperator):
"""A node in the expression tree, which stores the index that should be
extracted from its child after the child has been evaluated.
Expand Down
1 change: 1 addition & 0 deletions pybamm/models/full_battery_models/base_battery_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def options(self, extra_options):
"external submodels": [],
"sei": None,
"sei porosity change": False,
"working electrode": None
}
# Change the default for cell geometry based on which thermal option is provided
extra_options = extra_options or {}
Expand Down
1 change: 1 addition & 0 deletions pybamm/models/full_battery_models/lithium_ion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
from .dfn import DFN
from .basic_dfn import BasicDFN
from .basic_spm import BasicSPM
from .basic_dfn_half_cell import BasicDFNHalfCell
Loading

0 comments on commit c229326

Please sign in to comment.