Skip to content

Commit

Permalink
Merge pull request #581 from pybamm-team/issue-580-processed-variable
Browse files Browse the repository at this point in the history
Issue 580 processed variable
  • Loading branch information
valentinsulzer authored Oct 24, 2019
2 parents 79c9d34 + ba6cb49 commit d4db5b2
Show file tree
Hide file tree
Showing 20 changed files with 294 additions and 158 deletions.
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ exclude=
lib,
lib64,
share,
pyvenv.cfg
pyvenv.cfg,
third-party,
ignore=
# False positive for white space before ':' on list slice
# black should format these correctly
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pyproject.toml
# virtual enviroment
venv/
venv3.5/
PyBaMM-env/
bin/
etc/
lib/
Expand Down
16 changes: 9 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

## Features

- Add method to evaluate parameters more easily (#669 )
- Add `Interpolant` class to interpolate experimental data (e.g. OCP curves) (#661 )
- Allow parameters to be set by material or by specifying a particular paper (#647 )
- Set relative and absolute tolerances independently in solvers (#645 )
- Add some non-uniform meshes in 1D and 2D (#617 )
- Add method to evaluate parameters more easily ([#669](https://github.com/pybamm-team/PyBaMM/pull/669))
- Add `Interpolant` class to interpolate experimental data (e.g. OCP curves) ([#661](https://github.com/pybamm-team/PyBaMM/pull/661))
- Allow parameters to be set by material or by specifying a particular paper ([#647](https://github.com/pybamm-team/PyBaMM/pull/647))
- Set relative and absolute tolerances independently in solvers ([#645](https://github.com/pybamm-team/PyBaMM/pull/645))
- Add some non-uniform meshes in 1D and 2D ([#617](https://github.com/pybamm-team/PyBaMM/pull/617))

## Optimizations

- Avoid re-checking size when making a copy of an `Index` object (#656 )
- Avoid recalculating `_evaluation_array` when making a copy of a `StateVector` object (#653 )
- Avoid re-checking size when making a copy of an `Index` object ([#656](https://github.com/pybamm-team/PyBaMM/pull/656))
- Avoid recalculating `_evaluation_array` when making a copy of a `StateVector` object ([#653](https://github.com/pybamm-team/PyBaMM/pull/653))

## Bug fixes

- Improve the way `ProcessedVariable` objects are created in higher dimensions ([#581](https://github.com/pybamm-team/PyBaMM/pull/581))

# [v0.1.0](https://github.com/pybamm-team/PyBaMM/tree/v0.1.0) - 2019-10-08

This is the first official version of PyBaMM.
Expand Down
1 change: 1 addition & 0 deletions examples/scripts/compare_lead_acid_3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
for i, model in enumerate(models):
solution = model.default_solver.solve(model, t_eval)
solutions[i] = solution
pybamm.post_process_variables(model.variables, solution.t, solution.y, mesh=mesh)

# plot
output_variables = [
Expand Down
3 changes: 1 addition & 2 deletions pybamm/discretisations/discretisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,6 @@ def process_dict(self, var_eqn_dict):

new_var_eqn_dict[eqn_key] = self.process_symbol(eqn)

new_var_eqn_dict[eqn_key].test_shape()

return new_var_eqn_dict

def process_symbol(self, symbol):
Expand All @@ -549,6 +547,7 @@ def process_symbol(self, symbol):
except KeyError:
discretised_symbol = self._process_symbol(symbol)
self._discretised_symbols[symbol.id] = discretised_symbol
discretised_symbol.test_shape()
return discretised_symbol

def _process_symbol(self, symbol):
Expand Down
23 changes: 20 additions & 3 deletions pybamm/expression_tree/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,30 @@ class Array(pybamm.Symbol):
the name of the node
domain : iterable of str, optional
list of domains the parameter is valid over, defaults to empty list
auxiliary_domainds : dict, optional
dictionary of auxiliary domains, defaults to empty dict
entries_string : str
String representing the entries (slow to recalculate when copying)
*Extends:* :class:`Symbol`
"""

def __init__(self, entries, name=None, domain=[], entries_string=None):
def __init__(
self,
entries,
name=None,
domain=None,
auxiliary_domains=None,
entries_string=None,
):
if entries.ndim == 1:
entries = entries[:, np.newaxis]
if name is None:
name = "Array of shape {!s}".format(entries.shape)
self._entries = entries
# Use known entries string to avoid re-hashing, where possible
self.entries_string = entries_string
super().__init__(name, domain=domain)
super().__init__(name, domain=domain, auxiliary_domains=auxiliary_domains)

@property
def entries(self):
Expand Down Expand Up @@ -73,7 +84,13 @@ def set_id(self):

def new_copy(self):
""" See :meth:`pybamm.Symbol.new_copy()`. """
return self.__class__(self.entries, self.name, self.domain, self.entries_string)
return self.__class__(
self.entries,
self.name,
self.domain,
self.auxiliary_domains,
self.entries_string,
)

def _base_evaluate(self, t=None, y=None):
""" See :meth:`pybamm.Symbol._base_evaluate()`. """
Expand Down
14 changes: 2 additions & 12 deletions pybamm/expression_tree/binary_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,10 @@ def __init__(self, name, left, right):
# right child.
if isinstance(self, (pybamm.Outer, pybamm.Kron)):
domain = right.domain
auxiliary_domains = {"secondary": left.domain}
else:
domain = self.get_children_domains(left.domain, right.domain)
auxiliary_domains = self.get_children_auxiliary_domains(
left.auxiliary_domains, right.auxiliary_domains
)
auxiliary_domains = self.get_children_auxiliary_domains([left, right])
super().__init__(
name,
children=[left, right],
Expand Down Expand Up @@ -118,15 +117,6 @@ def get_children_domains(self, ldomain, rdomain):
)
)

def get_children_auxiliary_domains(self, l_aux_domains, r_aux_domains):
"Combine auxiliary domains from children, at all levels"
aux_domains = {}
for level in set(l_aux_domains.keys()).union(r_aux_domains.keys()):
ldomain = l_aux_domains.get(level, [])
rdomain = r_aux_domains.get(level, [])
aux_domains[level] = self.get_children_domains(ldomain, rdomain)
return aux_domains

def new_copy(self):
""" See :meth:`pybamm.Symbol.new_copy()`. """

Expand Down
21 changes: 0 additions & 21 deletions pybamm/expression_tree/concatenations.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,6 @@ def get_children_domains(self, children):
raise pybamm.DomainError("""domain of children must be disjoint""")
return domain

def get_children_auxiliary_domains(self, children):
"Combine auxiliary domains from children, at all levels"
aux_domains = {}
for child in children:
for level in child.auxiliary_domains.keys():
if (
not hasattr(aux_domains, level)
or aux_domains[level] == []
or child.auxiliary_domains[level] == aux_domains[level]
):
aux_domains[level] = child.auxiliary_domains[level]
else:
raise pybamm.DomainError(
"""children must have same or empty auxiliary domains,
not {!s} and {!s}""".format(
aux_domains[level], child.auxiliary_domains[level]
)
)

return aux_domains

def _concatenation_evaluate(self, children_eval):
""" See :meth:`Concatenation._concatenation_evaluate()`. """
if len(children_eval) == 0:
Expand Down
8 changes: 7 additions & 1 deletion pybamm/expression_tree/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, function, *children, name=None, derivative="autograd"):
name = "function ({})".format(function.__class__)
children_list = list(children)
domain = self.get_children_domains(children_list)
auxiliary_domains = self.get_children_auxiliary_domains(children)

self.function = function
self.derivative = derivative
Expand All @@ -46,7 +47,12 @@ def __init__(self, function, *children, name=None, derivative="autograd"):
else:
self.takes_no_params = len(signature(function).parameters) == 0

super().__init__(name, children=children_list, domain=domain)
super().__init__(
name,
children=children_list,
domain=domain,
auxiliary_domains=auxiliary_domains,
)

def get_children_domains(self, children_list):
"""Obtains the unique domain of the children. If the
Expand Down
19 changes: 9 additions & 10 deletions pybamm/expression_tree/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@ class Matrix(pybamm.Array):
**Extends:** :class:`Array`
Parameters
----------
entries : numpy.array
the array associated with the node
name : str, optional
the name of the node
"""

def __init__(self, entries, name=None, domain=[], entries_string=None):
def __init__(
self,
entries,
name=None,
domain=None,
auxiliary_domains=None,
entries_string=None,
):
if name is None:
name = "Matrix {!s}".format(entries.shape)
if issparse(entries):
name = "Sparse " + name
super().__init__(entries, name, domain, entries_string)
super().__init__(entries, name, domain, auxiliary_domains, entries_string)
5 changes: 4 additions & 1 deletion pybamm/expression_tree/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ def __init__(self, name, *children, diff_variable=None):
self.diff_variable = diff_variable
children_list = list(children)
domain = self.get_children_domains(children_list)
super().__init__(name, children=children, domain=domain)
auxiliary_domains = self.get_children_auxiliary_domains(children)
super().__init__(
name, children=children, domain=domain, auxiliary_domains=auxiliary_domains
)

def set_id(self):
"""See :meth:`pybamm.Symbol.set_id` """
Expand Down
29 changes: 29 additions & 0 deletions pybamm/expression_tree/symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ class Symbol(anytree.NodeMixin):
domain : iterable of str, or str
list of domains over which the node is valid (empty list indicates the symbol
is valid over all domains)
auxiliary_domains : dict of str
dictionary of auxiliary domains over which the node is valid (empty dictionary
indicates no auxiliary domains). Keys can be "secondary" or "tertiary". The
symbol is broadcast over its auxiliary domains.
For example, a symbol might have domain "negative particle", secondary domain
"separator" and tertiary domain "current collector" (`domain="negative
particle", auxiliary_domains={"secondary": "separator", "tertiary": "current
collector"}`).
"""

Expand Down Expand Up @@ -160,6 +168,27 @@ def domain(self, domain):
# Update id since domain has changed
self.set_id()

def get_children_auxiliary_domains(self, children):
"Combine auxiliary domains from children, at all levels"
aux_domains = {}
for child in children:
for level in child.auxiliary_domains.keys():
if (
level not in aux_domains
or aux_domains[level] == []
or child.auxiliary_domains[level] == aux_domains[level]
):
aux_domains[level] = child.auxiliary_domains[level]
else:
raise pybamm.DomainError(
"""children must have same or empty auxiliary domains,
not {!s} and {!s}""".format(
aux_domains[level], child.auxiliary_domains[level]
)
)

return aux_domains

@property
def id(self):
return self._id
Expand Down
21 changes: 9 additions & 12 deletions pybamm/expression_tree/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@ class Vector(pybamm.Array):
**Extends:** :class:`Array`
Parameters
----------
entries : numpy.array
the array associated with the node
name : str, optional
the name of the node
domain : iterable of str, optional
list of domains the parameter is valid over, defaults to empty list
"""

def __init__(self, entries, name=None, domain=[], entries_string=None):
def __init__(
self,
entries,
name=None,
domain=None,
auxiliary_domains=None,
entries_string=None,
):
# make sure that entries are a vector (can be a column vector)
if entries.ndim == 1:
entries = entries[:, np.newaxis]
Expand All @@ -39,7 +36,7 @@ def __init__(self, entries, name=None, domain=[], entries_string=None):
if name is None:
name = "Column vector of length {!s}".format(entries.shape[0])

super().__init__(entries, name, domain, entries_string)
super().__init__(entries, name, domain, auxiliary_domains, entries_string)

def _jac(self, variable):
""" See :meth:`pybamm.Symbol._jac()`. """
Expand Down
Loading

0 comments on commit d4db5b2

Please sign in to comment.