diff --git a/asv.conf.json b/asv.conf.json index 5117cf75d2..bf9935ce95 100644 --- a/asv.conf.json +++ b/asv.conf.json @@ -82,7 +82,6 @@ "wget": [], "cmake": [], "anytree": [], - "autograd": [], "scikit-fem": [], "imageio": [], "pybtex": [], diff --git a/pybamm/expression_tree/functions.py b/pybamm/expression_tree/functions.py index 5f686539b4..4e087e9725 100644 --- a/pybamm/expression_tree/functions.py +++ b/pybamm/expression_tree/functions.py @@ -11,7 +11,6 @@ from typing_extensions import TypeVar import pybamm -from pybamm.util import import_optional_dependency class Function(pybamm.Symbol): @@ -26,9 +25,6 @@ class Function(pybamm.Symbol): func(child0.evaluate(t, y, u), child1.evaluate(t, y, u), etc). children : :class:`pybamm.Symbol` The children nodes to apply the function to - derivative : str, optional - Which derivative to use when differentiating ("autograd" or "derivative"). - Default is "autograd". differentiated_function : method, optional The function which was differentiated to obtain this one. Default is None. """ @@ -38,7 +34,6 @@ def __init__( function: Callable, *children: pybamm.Symbol, name: str | None = None, - derivative: str | None = "autograd", differentiated_function: Callable | None = None, ): # Turn numbers into scalars @@ -57,7 +52,6 @@ def __init__( domains = self.get_children_domains(children) self.function = function - self.derivative = derivative self.differentiated_function = differentiated_function super().__init__(name, children=children, domains=domains) @@ -99,30 +93,10 @@ def _function_diff(self, children: Sequence[pybamm.Symbol], idx: float): Derivative with respect to child number 'idx'. See :meth:`pybamm.Symbol._diff()`. """ - autograd = import_optional_dependency("autograd") - # Store differentiated function, needed in case we want to convert to CasADi - if self.derivative == "autograd": - return Function( - autograd.elementwise_grad(self.function, idx), - *children, - differentiated_function=self.function, - ) - elif self.derivative == "derivative": - if len(children) > 1: - raise ValueError( - """ - differentiation using '.derivative()' not implemented for functions - with more than one child - """ - ) - else: - # keep using "derivative" as derivative - return pybamm.Function( - self.function.derivative(), # type: ignore[attr-defined] - *children, - derivative="derivative", - differentiated_function=self.function, - ) + raise NotImplementedError( + "Derivative of base Function class is not implemented. " + "Please implement in child class." + ) def _function_jac(self, children_jacs): """Calculate the Jacobian of a function.""" @@ -190,7 +164,6 @@ def create_copy( self.function, *children, name=self.name, - derivative=self.derivative, differentiated_function=self.differentiated_function, ) else: @@ -217,7 +190,6 @@ def _function_new_copy(self, children: list) -> Function: self.function, *children, name=self.name, - derivative=self.derivative, differentiated_function=self.differentiated_function, ) ) diff --git a/pybamm/expression_tree/interpolant.py b/pybamm/expression_tree/interpolant.py index 84c982342f..7b9d23b936 100644 --- a/pybamm/expression_tree/interpolant.py +++ b/pybamm/expression_tree/interpolant.py @@ -189,9 +189,7 @@ def __init__( self.x = x self.y = y self.entries_string = entries_string - super().__init__( - interpolating_function, *children, name=name, derivative="derivative" - ) + super().__init__(interpolating_function, *children, name=name) # Store information as attributes self.interpolator = interpolator @@ -311,6 +309,15 @@ def _function_evaluate(self, evaluated_children): else: # pragma: no cover raise ValueError(f"Invalid dimension: {self.dimension}") + def _function_diff(self, children: Sequence[pybamm.Symbol], idx: float): + """ + Derivative with respect to child number 'idx'. + See :meth:`pybamm.Symbol._diff()`. + """ + raise NotImplementedError( + "Cannot differentiate Interpolant symbol with respect to its children." + ) + def to_json(self): """ Method to serialise an Interpolant object into JSON. diff --git a/pyproject.toml b/pyproject.toml index 9bb2ae9c3a..7de16accaf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -121,7 +121,6 @@ jax = [ ] # Contains all optional dependencies, except for jax and dev dependencies all = [ - "autograd>=1.6.2", "scikit-fem>=8.1.0", "pybamm[examples,plot,cite,bpx,tqdm]", ] diff --git a/tests/unit/test_expression_tree/test_functions.py b/tests/unit/test_expression_tree/test_functions.py index 6c6881c37c..16626f7512 100644 --- a/tests/unit/test_expression_tree/test_functions.py +++ b/tests/unit/test_expression_tree/test_functions.py @@ -13,7 +13,6 @@ from tests import ( function_test, multi_var_function_test, - multi_var_function_cube_test, ) @@ -52,57 +51,12 @@ def test_function_of_one_variable(self): def test_diff(self): a = pybamm.StateVector(slice(0, 1)) - b = pybamm.StateVector(slice(1, 2)) - y = np.array([5]) func = pybamm.Function(function_test, a) - self.assertEqual(func.diff(a).evaluate(y=y), 2) - self.assertEqual(func.diff(func).evaluate(), 1) - func = pybamm.sin(a) - self.assertEqual(func.evaluate(y=y), np.sin(a.evaluate(y=y))) - self.assertEqual(func.diff(a).evaluate(y=y), np.cos(a.evaluate(y=y))) - func = pybamm.exp(a) - self.assertEqual(func.evaluate(y=y), np.exp(a.evaluate(y=y))) - self.assertEqual(func.diff(a).evaluate(y=y), np.exp(a.evaluate(y=y))) - - # multiple variables - func = pybamm.Function(multi_var_function_test, 4 * a, 3 * a) - self.assertEqual(func.diff(a).evaluate(y=y), 7) - func = pybamm.Function(multi_var_function_test, 4 * a, 3 * b) - self.assertEqual(func.diff(a).evaluate(y=np.array([5, 6])), 4) - self.assertEqual(func.diff(b).evaluate(y=np.array([5, 6])), 3) - func = pybamm.Function(multi_var_function_cube_test, 4 * a, 3 * b) - self.assertEqual(func.diff(a).evaluate(y=np.array([5, 6])), 4) - self.assertEqual( - func.diff(b).evaluate(y=np.array([5, 6])), 3 * 3 * (3 * 6) ** 2 - ) - - # exceptions - func = pybamm.Function( - multi_var_function_cube_test, 4 * a, 3 * b, derivative="derivative" - ) - with self.assertRaises(ValueError): + with self.assertRaisesRegex( + NotImplementedError, "Derivative of base Function class is not implemented" + ): func.diff(a) - def test_function_of_multiple_variables(self): - a = pybamm.Variable("a") - b = pybamm.Parameter("b") - func = pybamm.Function(multi_var_function_test, a, b) - self.assertEqual(func.name, "function (multi_var_function_test)") - self.assertEqual(str(func), "multi_var_function_test(a, b)") - self.assertEqual(func.children[0].name, a.name) - self.assertEqual(func.children[1].name, b.name) - - # test eval and diff - a = pybamm.StateVector(slice(0, 1)) - b = pybamm.StateVector(slice(1, 2)) - y = np.array([5, 2]) - func = pybamm.Function(multi_var_function_test, a, b) - - self.assertEqual(func.evaluate(y=y), 7) - self.assertEqual(func.diff(a).evaluate(y=y), 1) - self.assertEqual(func.diff(b).evaluate(y=y), 1) - self.assertEqual(func.diff(func).evaluate(), 1) - def test_exceptions(self): a = pybamm.Variable("a", domain="something") b = pybamm.Variable("b", domain="something else") diff --git a/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py b/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py index 2b9aa08479..20c2e40db0 100644 --- a/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py +++ b/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py @@ -314,22 +314,6 @@ def test_concatenations(self): y_eval = np.linspace(0, 1, expr.size) self.assert_casadi_equal(f(y_eval), casadi.SX(expr.evaluate(y=y_eval))) - def test_convert_differentiated_function(self): - a = pybamm.InputParameter("a") - b = pybamm.InputParameter("b") - - def myfunction(x, y): - return x + y**3 - - f = pybamm.Function(myfunction, a, b).diff(a) - self.assert_casadi_equal( - f.to_casadi(inputs={"a": 1, "b": 2}), casadi.DM(1), evalf=True - ) - f = pybamm.Function(myfunction, a, b).diff(b) - self.assert_casadi_equal( - f.to_casadi(inputs={"a": 1, "b": 2}), casadi.DM(12), evalf=True - ) - def test_convert_input_parameter(self): casadi_t = casadi.MX.sym("t") casadi_y = casadi.MX.sym("y", 10) diff --git a/tests/unit/test_expression_tree/test_operations/test_jac.py b/tests/unit/test_expression_tree/test_operations/test_jac.py index 64280fd934..bec38d7243 100644 --- a/tests/unit/test_expression_tree/test_operations/test_jac.py +++ b/tests/unit/test_expression_tree/test_operations/test_jac.py @@ -8,7 +8,6 @@ import unittest from scipy.sparse import eye from tests import get_mesh_for_testing -from tests import multi_var_function_test class TestJacobian(TestCase): @@ -213,12 +212,6 @@ def test_functions(self): dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(0, dfunc_dy) - # several children - func = pybamm.Function(multi_var_function_test, 2 * y, 3 * y) - jacobian = np.diag(5 * np.ones(4)) - dfunc_dy = func.jac(y).evaluate(y=y0) - np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) - def test_index(self): vec = pybamm.StateVector(slice(0, 5)) ind = pybamm.Index(vec, 3) diff --git a/tests/unit/test_expression_tree/test_operations/test_jac_2D.py b/tests/unit/test_expression_tree/test_operations/test_jac_2D.py index 6df2c9f775..2be71d85e4 100644 --- a/tests/unit/test_expression_tree/test_operations/test_jac_2D.py +++ b/tests/unit/test_expression_tree/test_operations/test_jac_2D.py @@ -9,7 +9,6 @@ from scipy.sparse import eye from tests import ( get_1p1d_discretisation_for_testing, - multi_var_function_test, ) @@ -200,12 +199,6 @@ def test_functions(self): dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(0, dfunc_dy) - # several children - func = pybamm.Function(multi_var_function_test, 2 * y, 3 * y) - jacobian = np.diag(5 * np.ones(8)) - dfunc_dy = func.jac(y).evaluate(y=y0) - np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) - def test_jac_of_domain_concatenation(self): # create mesh disc = get_1p1d_discretisation_for_testing()