Skip to content

Commit

Permalink
Merge pull request #1497 from pybamm-team/other-changes-julia-branch
Browse files Browse the repository at this point in the history
"Other" changes from the julia branch
  • Loading branch information
valentinsulzer committed Jun 3, 2021
2 parents 28de127 + 2e4f5e4 commit 08de417
Show file tree
Hide file tree
Showing 20 changed files with 436 additions and 333 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_on_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}

- name: Install Linux system dependencies
if: matrix.os == 'ubuntu-latest'
run: |
Expand Down
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,5 @@ test.c
# tox
.tox/

# julia
Manifest.toml

# vcpkg
vcpkg_installed/
vcpkg_installed/
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Features

- Added `print_name` to some symbols ([#1495](https://github.com/pybamm-team/PyBaMM/pull/1497), [#1495](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))
- Added a new "reaction-driven" model for LAM from Reniers et al (2019) ([#1490](https://github.com/pybamm-team/PyBaMM/pull/1490))
- Some features ("loss of active material" and "particle mechanics") can now be specified separately for the negative electrode and positive electrode by passing a 2-tuple ([#1490](https://github.com/pybamm-team/PyBaMM/pull/1490))
Expand Down
8 changes: 4 additions & 4 deletions pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,16 @@ def version(formatted=False):
from .expression_tree.exceptions import *

# Operations
from .expression_tree.operations.evaluate import (
from .expression_tree.operations.evaluate_python import (
find_symbols,
id_to_python_variable,
to_python,
EvaluatorPython,
)

if system() != "Windows":
from .expression_tree.operations.evaluate import EvaluatorJax
from .expression_tree.operations.evaluate import JaxCooMatrix
from .expression_tree.operations.evaluate_python import EvaluatorJax
from .expression_tree.operations.evaluate_python import JaxCooMatrix

from .expression_tree.operations.jacobian import Jacobian
from .expression_tree.operations.convert_to_casadi import CasadiConverter
Expand All @@ -115,7 +115,7 @@ def version(formatted=False):
# Model classes
#
from .models.base_model import BaseModel
from .models import standard_variables
from .models.standard_variables import standard_variables
from .models.event import Event
from .models.event import EventType

Expand Down
10 changes: 10 additions & 0 deletions pybamm/expression_tree/concatenations.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,16 @@ def __init__(self, *children):
np.min([child.bounds[1] for child in children]),
)

if not any(c.print_name is None for c in children):
print_name = intersect(children[0].print_name, children[1].print_name)
for child in children[2:]:
print_name = intersect(print_name, child.print_name)
if print_name.endswith("_"):
print_name = print_name[:-1]
else:
print_name = None
self.print_name = print_name


def substrings(s):
for i in range(len(s)):
Expand Down
18 changes: 16 additions & 2 deletions pybamm/expression_tree/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,20 +358,34 @@ def log10(child):
return log(child, base=10)


class Max(SpecificFunction):
""" Max function """

def __init__(self, child):
super().__init__(np.max, child)


def max(child):
"""
Returns max function of child. Not to be confused with :meth:`pybamm.maximum`, which
returns the larger of two objects.
"""
return pybamm.simplify_if_constant(Function(np.max, child))
return pybamm.simplify_if_constant(Max(child))


class Min(SpecificFunction):
""" Min function """

def __init__(self, child):
super().__init__(np.min, child)


def min(child):
"""
Returns min function of child. Not to be confused with :meth:`pybamm.minimum`, which
returns the smaller of two objects.
"""
return pybamm.simplify_if_constant(Function(np.min, child))
return pybamm.simplify_if_constant(Min(child))


def sech(child):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,23 +313,23 @@ def find_symbols(symbol, constant_symbols, variable_symbols, output_jax=False):

elif isinstance(symbol, pybamm.Concatenation):

# don't bother to concatenate if there is only a single child
# no need to concatenate if there is only a single child
if isinstance(symbol, pybamm.NumpyConcatenation):
if len(children_vars) > 1:
symbol_str = "np.concatenate(({}))".format(",".join(children_vars))
if len(children_vars) == 1:
symbol_str = children_vars[0]
else:
symbol_str = "{}".format(",".join(children_vars))
symbol_str = "np.concatenate(({}))".format(",".join(children_vars))

elif isinstance(symbol, pybamm.SparseStack):
if len(children_vars) > 1:
if len(children_vars) == 1:
symbol_str = children_vars[0]
else:
if output_jax:
raise NotImplementedError
else:
symbol_str = "scipy.sparse.vstack(({}))".format(
",".join(children_vars)
)
else:
symbol_str = "{}".format(",".join(children_vars))

# DomainConcatenation specifies a particular ordering for the concatenation,
# which we must follow
Expand Down Expand Up @@ -376,7 +376,9 @@ def find_symbols(symbol, constant_symbols, variable_symbols, output_jax=False):

else:
raise NotImplementedError(
"Not implemented for a symbol of type '{}'".format(type(symbol))
"Conversion to python not implemented for a symbol of type '{}'".format(
type(symbol)
)
)

variable_symbols[symbol.id] = symbol_str
Expand Down
38 changes: 34 additions & 4 deletions pybamm/expression_tree/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import numbers
import numpy as np
import pybamm
import sys


class Parameter(pybamm.Symbol):
Expand Down Expand Up @@ -62,13 +63,17 @@ class FunctionParameter(pybamm.Symbol):
if diff_variable is specified, the FunctionParameter node will be replaced by a
:class:`pybamm.Function` and then differentiated with respect to diff_variable.
Default is None.
print_name : str, optional
The name to show when printing. Default is 'calculate', in which case the name
is calculated using sys._getframe().
"""

def __init__(
self,
name,
inputs,
diff_variable=None,
print_name="calculate",
):
# assign diff variable
self.diff_variable = diff_variable
Expand All @@ -90,6 +95,23 @@ def __init__(

self.input_names = list(inputs.keys())

# Use the inspect module to find the function's "short name" from the
# Parameters module that called it
if print_name != "calculate":
self.print_name = print_name
else:
frame = sys._getframe().f_back
print_name = frame.f_code.co_name
if print_name.startswith("_"):
self.print_name = None
else:
if print_name.endswith("_dimensional"):
self.print_name = print_name[: -len("_dimensional")]
elif print_name.endswith("_dim"):
self.print_name = print_name[: -len("_dim")]
else:
self.print_name = print_name

@property
def input_names(self):
return self._input_names
Expand Down Expand Up @@ -159,9 +181,14 @@ def diff(self, variable):

def new_copy(self):
""" See :meth:`pybamm.Symbol.new_copy()`. """
return self._function_parameter_new_copy(self._input_names, self.orphans)
out = self._function_parameter_new_copy(
self._input_names, self.orphans, print_name=self.print_name
)
return out

def _function_parameter_new_copy(self, input_names, children):
def _function_parameter_new_copy(
self, input_names, children, print_name="calculate"
):
"""Returns a new copy of the function parameter.
Inputs
Expand All @@ -173,14 +200,17 @@ def _function_parameter_new_copy(self, input_names, children):
Returns
-------
: :pybamm.FunctionParameter
:class:`pybamm.FunctionParameter`
A new copy of the function parameter
"""

input_dict = {input_names[i]: children[i] for i in range(len(input_names))}

return FunctionParameter(
self.name, input_dict, diff_variable=self.diff_variable
self.name,
input_dict,
diff_variable=self.diff_variable,
print_name=print_name,
)

def _evaluate_for_shape(self):
Expand Down
3 changes: 3 additions & 0 deletions pybamm/expression_tree/scalar.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ def __init__(self, value, name=None, domain=[]):

super().__init__(name, domain=domain)

def __str__(self):
return str(self.value)

@property
def value(self):
"""the value returned by the node when evaluated"""
Expand Down
5 changes: 4 additions & 1 deletion pybamm/expression_tree/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ def __init__(self, name, domain=None, auxiliary_domains=None, bounds=None):
+ "Lower bound should be strictly less than upper bound."
)
self.bounds = bounds
self.print_name = None

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

return self.__class__(
out = self.__class__(
self.name, self.domain, self.auxiliary_domains, self.bounds
)
out.print_name = self.print_name
return out

def _evaluate_for_shape(self):
""" See :meth:`pybamm.Symbol.evaluate_for_shape_using_domain()` """
Expand Down
29 changes: 17 additions & 12 deletions pybamm/models/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,22 @@ def info(self, symbol_name):

print(div)

def check_discretised_or_discretise_inplace_if_0D(self):
"""
Discretise model if it isn't already discretised
This only works with purely 0D models, as otherwise the mesh and spatial
method should be specified by the user
"""
if self.is_discretised is False:
try:
disc = pybamm.Discretisation()
disc.process_model(self)
except pybamm.DiscretisationError as e:
raise pybamm.DiscretisationError(
"Cannot automatically discretise model, model should be "
"discretised before exporting casadi functions ({})".format(e)
)

def export_casadi_objects(self, variable_names, input_parameter_order=None):
"""
Export the constituent parts of the model (rhs, algebraic, initial conditions,
Expand All @@ -793,18 +809,7 @@ def export_casadi_objects(self, variable_names, input_parameter_order=None):
Dictionary of {str: casadi object} pairs representing the model in casadi
format
"""
# Discretise model if it isn't already discretised
# This only works with purely 0D models, as otherwise the mesh and spatial
# method should be specified by the user
if self.is_discretised is False:
try:
disc = pybamm.Discretisation()
disc.process_model(self)
except pybamm.DiscretisationError as e:
raise pybamm.DiscretisationError(
"Cannot automatically discretise model, model should be "
"discretised before exporting casadi functions ({})".format(e)
)
self.check_discretised_or_discretise_inplace_if_0D()

# Create casadi functions for the model
t_casadi = casadi.MX.sym("t")
Expand Down
Loading

0 comments on commit 08de417

Please sign in to comment.