diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cade77684..069093015a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ ## Breaking changes +- Integrated the `[latexify]` extra into the core PyBaMM package, deprecating the `pybamm[latexify]` set of optional dependencies. SymPy is now a required dependency and will be installed upon installing PyBaMM ([#3848](https://github.com/pybamm-team/PyBaMM/pull/3848)) - Renamed "testing" argument for plots to "show_plot" and flipped its meaning (show_plot=True is now the default and shows the plot) ([#3842](https://github.com/pybamm-team/PyBaMM/pull/3842)) - Dropped support for BPX version 0.3.0 and below ([#3414](https://github.com/pybamm-team/PyBaMM/pull/3414)) diff --git a/docs/source/user_guide/installation/index.rst b/docs/source/user_guide/installation/index.rst index bf83e38835..1a773c65a5 100644 --- a/docs/source/user_guide/installation/index.rst +++ b/docs/source/user_guide/installation/index.rst @@ -59,15 +59,17 @@ Required dependencies PyBaMM requires the following dependencies. -================================================================ ========================== -Package Minimum supported version -================================================================ ========================== -`NumPy `__ 1.23.5 -`SciPy `__ 1.9.3 -`CasADi `__ 3.6.3 -`Xarray `__ 2022.6.0 -`Anytree `__ 2.8.0 -================================================================ ========================== +=================================================================== ========================== +Package Minimum supported version +=================================================================== ========================== +`NumPy `__ 1.23.5 +`SciPy `__ 1.9.3 +`CasADi `__ 3.6.3 +`Xarray `__ 2022.6.0 +`Anytree `__ 2.8.0 +`SymPy `__ 1.9.3 +`typing-extensions `__ 4.10.0 +=================================================================== ========================== .. _install.optional_dependencies: @@ -174,19 +176,6 @@ Dependency Minimum Version p `pybtex `__ 0.24.0 cite BibTeX-compatible bibliography processor. =========================================================== ================== ================== ========================================= -.. _install.latexify_dependencies: - -Latexify dependencies -^^^^^^^^^^^^^^^^^^^^^ - -Installable with ``pip install "pybamm[latexify]"`` - -=========================================================== ================== ================== ========================= -Dependency Minimum Version pip extra Notes -=========================================================== ================== ================== ========================= -`sympy `__ 1.9.3 latexify For symbolic mathematics. -=========================================================== ================== ================== ========================= - .. _install.bpx_dependencies: bpx dependencies diff --git a/pybamm/expression_tree/array.py b/pybamm/expression_tree/array.py index 0bb6168a7c..dbaa5cd144 100644 --- a/pybamm/expression_tree/array.py +++ b/pybamm/expression_tree/array.py @@ -4,14 +4,10 @@ from __future__ import annotations import numpy as np from scipy.sparse import csr_matrix, issparse -from typing import TYPE_CHECKING import pybamm -from pybamm.util import have_optional_dependency from pybamm.type_definitions import DomainType, AuxiliaryDomainType, DomainsType - -if TYPE_CHECKING: # pragma: no cover - import sympy +import sympy class Array(pybamm.Symbol): @@ -157,7 +153,6 @@ def is_constant(self): def to_equation(self) -> sympy.Array: """Returns the value returned by the node when evaluated.""" - sympy = have_optional_dependency("sympy") entries_list = self.entries.tolist() return sympy.Array(entries_list) diff --git a/pybamm/expression_tree/binary_operators.py b/pybamm/expression_tree/binary_operators.py index d10844798b..a8086ebdd1 100644 --- a/pybamm/expression_tree/binary_operators.py +++ b/pybamm/expression_tree/binary_operators.py @@ -5,11 +5,11 @@ import numbers import numpy as np +import sympy from scipy.sparse import csr_matrix, issparse import functools import pybamm -from pybamm.util import have_optional_dependency from typing import Callable, cast @@ -180,7 +180,6 @@ def _sympy_operator(self, left, right): def to_equation(self): """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: @@ -388,7 +387,6 @@ def _binary_evaluate(self, left, right): def _sympy_operator(self, left, right): """Override :meth:`pybamm.BinaryOperator._sympy_operator`""" - sympy = have_optional_dependency("sympy") left = sympy.Matrix(left) right = sympy.Matrix(right) return left * right @@ -737,7 +735,6 @@ def _binary_new_copy( def _sympy_operator(self, left, right): """Override :meth:`pybamm.BinaryOperator._sympy_operator`""" - sympy = have_optional_dependency("sympy") return sympy.Min(left, right) @@ -782,7 +779,6 @@ def _binary_new_copy( def _sympy_operator(self, left, right): """Override :meth:`pybamm.BinaryOperator._sympy_operator`""" - sympy = have_optional_dependency("sympy") return sympy.Max(left, right) diff --git a/pybamm/expression_tree/concatenations.py b/pybamm/expression_tree/concatenations.py index 5e0bb5544e..c00a0a08a6 100644 --- a/pybamm/expression_tree/concatenations.py +++ b/pybamm/expression_tree/concatenations.py @@ -6,11 +6,11 @@ from collections import defaultdict import numpy as np +import sympy from scipy.sparse import issparse, vstack from typing import Sequence import pybamm -from pybamm.util import have_optional_dependency class Concatenation(pybamm.Symbol): @@ -159,7 +159,6 @@ def is_constant(self): def _sympy_operator(self, *children): """Apply appropriate SymPy operators.""" - sympy = have_optional_dependency("sympy") self.concat_latex = tuple(map(sympy.latex, children)) if self.print_name is not None: diff --git a/pybamm/expression_tree/functions.py b/pybamm/expression_tree/functions.py index 72c9d4074a..7f0986441f 100644 --- a/pybamm/expression_tree/functions.py +++ b/pybamm/expression_tree/functions.py @@ -5,6 +5,7 @@ import numpy as np from scipy import special +import sympy from typing import Sequence, Callable from typing_extensions import TypeVar @@ -210,7 +211,6 @@ def _sympy_operator(self, child): def to_equation(self): """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: @@ -275,7 +275,6 @@ def _function_new_copy(self, children): def _sympy_operator(self, child): """Apply appropriate SymPy operators.""" - sympy = have_optional_dependency("sympy") class_name = self.__class__.__name__.lower() sympy_function = getattr(sympy, class_name) return sympy_function(child) @@ -332,7 +331,6 @@ def _function_diff(self, children, idx): def _sympy_operator(self, child): """Override :meth:`pybamm.Function._sympy_operator`""" - sympy = have_optional_dependency("sympy") return sympy.asinh(child) @@ -360,7 +358,6 @@ def _function_diff(self, children, idx): def _sympy_operator(self, child): """Override :meth:`pybamm.Function._sympy_operator`""" - sympy = have_optional_dependency("sympy") return sympy.atan(child) diff --git a/pybamm/expression_tree/independent_variable.py b/pybamm/expression_tree/independent_variable.py index 0dca6dba46..01e9dd661a 100644 --- a/pybamm/expression_tree/independent_variable.py +++ b/pybamm/expression_tree/independent_variable.py @@ -6,7 +6,6 @@ import numpy as np import pybamm -from pybamm.util import have_optional_dependency from pybamm.type_definitions import DomainType, AuxiliaryDomainType, DomainsType KNOWN_COORD_SYS = ["cartesian", "cylindrical polar", "spherical polar"] @@ -58,7 +57,6 @@ def _jac(self, variable) -> pybamm.Scalar: def to_equation(self) -> sympy.Symbol: """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: @@ -102,7 +100,6 @@ def _evaluate_for_shape(self): def to_equation(self): """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") return sympy.Symbol("t") diff --git a/pybamm/expression_tree/operations/latexify.py b/pybamm/expression_tree/operations/latexify.py index 5f8eb1b6aa..26e421818f 100644 --- a/pybamm/expression_tree/operations/latexify.py +++ b/pybamm/expression_tree/operations/latexify.py @@ -9,7 +9,7 @@ import pybamm from pybamm.expression_tree.printing.sympy_overrides import custom_print_func -from pybamm.util import have_optional_dependency +import sympy def get_rng_min_max_name(rng, min_or_max): @@ -89,7 +89,6 @@ def _get_bcs_displays(self, var): Returns a list of boundary condition equations with ranges in front of the equations. """ - sympy = have_optional_dependency("sympy") bcs_eqn_list = [] bcs = self.model.boundary_conditions.get(var, None) @@ -120,7 +119,6 @@ def _get_bcs_displays(self, var): def _get_param_var(self, node): """Returns a list of parameters and a list of variables.""" - sympy = have_optional_dependency("sympy") param_list = [] var_list = [] dfs_nodes = [node] @@ -163,7 +161,6 @@ def _get_param_var(self, node): return param_list, var_list def latexify(self, output_variables=None): - sympy = have_optional_dependency("sympy") # Voltage is the default output variable if it exists if output_variables is None: if "Voltage [V]" in self.model.variables: diff --git a/pybamm/expression_tree/parameter.py b/pybamm/expression_tree/parameter.py index e646ff234d..4294d7ebc1 100644 --- a/pybamm/expression_tree/parameter.py +++ b/pybamm/expression_tree/parameter.py @@ -5,13 +5,11 @@ import sys import numpy as np -from typing import TYPE_CHECKING, Literal +from typing import Literal -if TYPE_CHECKING: # pragma: no cover - import sympy +import sympy import pybamm -from pybamm.util import have_optional_dependency class Parameter(pybamm.Symbol): @@ -48,7 +46,6 @@ def is_constant(self) -> Literal[False]: def to_equation(self) -> sympy.Symbol: """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: @@ -244,7 +241,6 @@ def _evaluate_for_shape(self): def to_equation(self) -> sympy.Symbol: """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: diff --git a/pybamm/expression_tree/scalar.py b/pybamm/expression_tree/scalar.py index 26bbabfcf0..a860ae45ec 100644 --- a/pybamm/expression_tree/scalar.py +++ b/pybamm/expression_tree/scalar.py @@ -3,10 +3,10 @@ # from __future__ import annotations import numpy as np +import sympy from typing import Literal import pybamm -from pybamm.util import have_optional_dependency from pybamm.type_definitions import Numeric @@ -87,7 +87,6 @@ def is_constant(self) -> Literal[True]: def to_equation(self): """Returns the value returned by the node when evaluated.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: diff --git a/pybamm/expression_tree/symbol.py b/pybamm/expression_tree/symbol.py index 531f97b7db..1d0d880ce6 100644 --- a/pybamm/expression_tree/symbol.py +++ b/pybamm/expression_tree/symbol.py @@ -5,6 +5,7 @@ import numbers import numpy as np +import sympy from scipy.sparse import csr_matrix, issparse from functools import cached_property from typing import TYPE_CHECKING, Sequence, cast @@ -1058,7 +1059,6 @@ def print_name(self, name): self._print_name = prettify_print_name(name) def to_equation(self): - sympy = have_optional_dependency("sympy") return sympy.Symbol(str(self.name)) def to_json(self): diff --git a/pybamm/expression_tree/unary_operators.py b/pybamm/expression_tree/unary_operators.py index 319499a9fc..cb5bc905fd 100644 --- a/pybamm/expression_tree/unary_operators.py +++ b/pybamm/expression_tree/unary_operators.py @@ -5,6 +5,7 @@ import numpy as np from scipy.sparse import csr_matrix, issparse +import sympy import pybamm from pybamm.util import have_optional_dependency from pybamm.type_definitions import DomainsType @@ -108,7 +109,6 @@ def _sympy_operator(self, child): def to_equation(self): """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: @@ -672,7 +672,6 @@ def _evaluates_on_edges(self, dimension: str) -> bool: def _sympy_operator(self, child): """Override :meth:`pybamm.UnaryOperator._sympy_operator`""" - sympy = have_optional_dependency("sympy") return sympy.Integral(child, sympy.Symbol("xn")) @@ -996,7 +995,6 @@ def _unary_new_copy(self, child): def _sympy_operator(self, child): """Override :meth:`pybamm.UnaryOperator._sympy_operator`""" - sympy = have_optional_dependency("sympy") if ( self.child.domain[0] in ["negative particle", "positive particle"] and self.side == "right" diff --git a/pybamm/expression_tree/variable.py b/pybamm/expression_tree/variable.py index eb0d90cdb6..238dab05fc 100644 --- a/pybamm/expression_tree/variable.py +++ b/pybamm/expression_tree/variable.py @@ -5,7 +5,7 @@ import numpy as np import numbers import pybamm -from pybamm.util import have_optional_dependency +import sympy from pybamm.type_definitions import ( DomainType, AuxiliaryDomainType, @@ -135,7 +135,6 @@ def _evaluate_for_shape(self): def to_equation(self): """Convert the node and its subtree into a SymPy equation.""" - sympy = have_optional_dependency("sympy") if self.print_name is not None: return sympy.Symbol(self.print_name) else: diff --git a/pybamm/models/base_model.py b/pybamm/models/base_model.py index edccb4af32..3a27249083 100644 --- a/pybamm/models/base_model.py +++ b/pybamm/models/base_model.py @@ -13,7 +13,7 @@ import pybamm from pybamm.expression_tree.operations.serialise import Serialise -from pybamm.util import have_optional_dependency +import sympy class BaseModel: @@ -1185,7 +1185,6 @@ def latexify(self, filename=None, newline=True, output_variables=None): This will return first five model equations >>> model.latexify(newline=False)[1:5] """ - sympy = have_optional_dependency("sympy") if sympy: from pybamm.expression_tree.operations.latexify import Latexify diff --git a/pyproject.toml b/pyproject.toml index 1b97b21ea0..6d2f925cba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,8 @@ dependencies = [ "casadi>=3.6.3", "xarray>=2022.6.0", "anytree>=2.8.0", + "sympy>=1.12", + "typing-extensions>=4.10.0", ] [project.urls] @@ -86,10 +88,6 @@ plot = [ cite = [ "pybtex>=0.24.0", ] -# To generate LaTeX strings -latexify = [ - "sympy>=1.12", -] # Battery Parameter eXchange format bpx = [ "bpx>=0.4.0", diff --git a/tests/unit/test_expression_tree/test_binary_operators.py b/tests/unit/test_expression_tree/test_binary_operators.py index b6cbe093eb..9efcbb90f2 100644 --- a/tests/unit/test_expression_tree/test_binary_operators.py +++ b/tests/unit/test_expression_tree/test_binary_operators.py @@ -9,7 +9,7 @@ from scipy.sparse import coo_matrix import pybamm -from pybamm.util import have_optional_dependency +import sympy EMPTY_DOMAINS = { "primary": [], @@ -790,7 +790,6 @@ def test_inner_simplifications(self): self.assertEqual(pybamm.inner(a3, a3).evaluate(), 9) def test_to_equation(self): - sympy = have_optional_dependency("sympy") # Test print_name pybamm.Addition.print_name = "test" self.assertEqual(pybamm.Addition(1, 2).to_equation(), sympy.Symbol("test")) diff --git a/tests/unit/test_expression_tree/test_concatenations.py b/tests/unit/test_expression_tree/test_concatenations.py index 691b6a7ee2..03a4b5a894 100644 --- a/tests/unit/test_expression_tree/test_concatenations.py +++ b/tests/unit/test_expression_tree/test_concatenations.py @@ -8,7 +8,7 @@ import numpy as np import pybamm -from pybamm.util import have_optional_dependency +import sympy from tests import get_discretisation_for_testing, get_mesh_for_testing @@ -371,7 +371,6 @@ def test_numpy_concatenation(self): ) def test_to_equation(self): - sympy = have_optional_dependency("sympy") a = pybamm.Symbol("a", domain="test a") b = pybamm.Symbol("b", domain="test b") func_symbol = sympy.Symbol(r"\begin{cases}a\\b\end{cases}") diff --git a/tests/unit/test_expression_tree/test_functions.py b/tests/unit/test_expression_tree/test_functions.py index 33e11459ab..df42280929 100644 --- a/tests/unit/test_expression_tree/test_functions.py +++ b/tests/unit/test_expression_tree/test_functions.py @@ -9,7 +9,7 @@ from scipy import special import pybamm -from pybamm.util import have_optional_dependency +import sympy def test_function(arg): @@ -121,7 +121,6 @@ def test_function_unnamed(self): self.assertEqual(fun.name, "function (cos)") def test_to_equation(self): - sympy = have_optional_dependency("sympy") a = pybamm.Symbol("a", domain="test") # Test print_name diff --git a/tests/unit/test_expression_tree/test_independent_variable.py b/tests/unit/test_expression_tree/test_independent_variable.py index b748a6fbe9..f747b60d40 100644 --- a/tests/unit/test_expression_tree/test_independent_variable.py +++ b/tests/unit/test_expression_tree/test_independent_variable.py @@ -6,7 +6,7 @@ import pybamm -from pybamm.util import have_optional_dependency +import sympy class TestIndependentVariable(TestCase): @@ -64,7 +64,6 @@ def test_spatial_variable_edge(self): self.assertTrue(x.evaluates_on_edges("primary")) def test_to_equation(self): - sympy = have_optional_dependency("sympy") # Test print_name func = pybamm.IndependentVariable("a") func.print_name = "test" diff --git a/tests/unit/test_expression_tree/test_parameter.py b/tests/unit/test_expression_tree/test_parameter.py index 6940ac38fe..bd5c680723 100644 --- a/tests/unit/test_expression_tree/test_parameter.py +++ b/tests/unit/test_expression_tree/test_parameter.py @@ -6,7 +6,7 @@ import unittest import pybamm -from pybamm.util import have_optional_dependency +import sympy class TestParameter(TestCase): @@ -20,7 +20,6 @@ def test_evaluate_for_shape(self): self.assertIsInstance(a.evaluate_for_shape(), numbers.Number) def test_to_equation(self): - sympy = have_optional_dependency("sympy") func = pybamm.Parameter("test_string") func1 = pybamm.Parameter("test_name") @@ -107,7 +106,6 @@ def _myfun(x): self.assertEqual(_myfun(x).print_name, None) def test_function_parameter_to_equation(self): - sympy = have_optional_dependency("sympy") func = pybamm.FunctionParameter("test", {"x": pybamm.Scalar(1)}) func1 = pybamm.FunctionParameter("func", {"var": pybamm.Variable("var")}) diff --git a/tests/unit/test_expression_tree/test_printing/test_sympy_overrides.py b/tests/unit/test_expression_tree/test_printing/test_sympy_overrides.py index de3ff08c43..ed029d73c6 100644 --- a/tests/unit/test_expression_tree/test_printing/test_sympy_overrides.py +++ b/tests/unit/test_expression_tree/test_printing/test_sympy_overrides.py @@ -6,12 +6,11 @@ import pybamm from pybamm.expression_tree.printing.sympy_overrides import custom_print_func -from pybamm.util import have_optional_dependency +import sympy class TestCustomPrint(TestCase): def test_print_Derivative(self): - sympy = have_optional_dependency("sympy") # Test force_partial der1 = sympy.Derivative("y", "x") der1.force_partial = True diff --git a/tests/unit/test_expression_tree/test_symbol.py b/tests/unit/test_expression_tree/test_symbol.py index ef7668aa59..f8db6b6bbd 100644 --- a/tests/unit/test_expression_tree/test_symbol.py +++ b/tests/unit/test_expression_tree/test_symbol.py @@ -12,7 +12,7 @@ import pybamm from pybamm.expression_tree.binary_operators import _Heaviside -from pybamm.util import have_optional_dependency +import sympy class TestSymbol(TestCase): @@ -485,7 +485,6 @@ def test_test_shape(self): (y1 + y2).test_shape() def test_to_equation(self): - sympy = have_optional_dependency("sympy") self.assertEqual(pybamm.Symbol("test").to_equation(), sympy.Symbol("test")) def test_numpy_array_ufunc(self): diff --git a/tests/unit/test_expression_tree/test_unary_operators.py b/tests/unit/test_expression_tree/test_unary_operators.py index 6ae6b62d05..960bb63038 100644 --- a/tests/unit/test_expression_tree/test_unary_operators.py +++ b/tests/unit/test_expression_tree/test_unary_operators.py @@ -7,9 +7,11 @@ import numpy as np from scipy.sparse import diags +import sympy +from sympy.vector.operators import Divergence as sympy_Divergence +from sympy.vector.operators import Gradient as sympy_Gradient import pybamm -from pybamm.util import have_optional_dependency class TestUnaryOperators(TestCase): @@ -678,12 +680,6 @@ def test_not_constant(self): self.assertFalse((2 * a).is_constant()) def test_to_equation(self): - sympy = have_optional_dependency("sympy") - sympy_Divergence = have_optional_dependency( - "sympy.vector.operators", "Divergence" - ) - sympy_Gradient = have_optional_dependency("sympy.vector.operators", "Gradient") - a = pybamm.Symbol("a", domain="negative particle") b = pybamm.Symbol("b", domain="current collector") c = pybamm.Symbol("c", domain="test") diff --git a/tests/unit/test_expression_tree/test_variable.py b/tests/unit/test_expression_tree/test_variable.py index 0d5aa251d2..42ab2c0e22 100644 --- a/tests/unit/test_expression_tree/test_variable.py +++ b/tests/unit/test_expression_tree/test_variable.py @@ -7,7 +7,7 @@ import numpy as np import pybamm -from pybamm.util import have_optional_dependency +import sympy class TestVariable(TestCase): @@ -55,7 +55,6 @@ def test_variable_bounds(self): pybamm.Variable("var", bounds=(1, 1)) def test_to_equation(self): - sympy = have_optional_dependency("sympy") # Test print_name func = pybamm.Variable("test_string") func.print_name = "test"