Repository: pybamm-team/PyBaMM

Issue:
Override __bool__ on a pybamm object to raise NotImplementedError

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96edd382c..41a7728a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
 
 ## Bug fixes
 
+-   Raise explicit `NotImplementedError` if trying to call `bool()` on a pybamm Symbol (e.g. in an if statement condition) ([#2141](https://github.com/pybamm-team/PyBaMM/pull/2141))
 -   Fixed bug causing cut-off voltage to change after setting up a simulation with a model ([#2138](https://github.com/pybamm-team/PyBaMM/pull/2138))
 -   A single solution cycle can now be used as a starting solution for a simulation ([#2138](https://github.com/pybamm-team/PyBaMM/pull/2138))
 
diff --git a/pybamm/expression_tree/functions.py b/pybamm/expression_tree/functions.py
index 006fb3318..38f10594f 100644
--- a/pybamm/expression_tree/functions.py
+++ b/pybamm/expression_tree/functions.py
@@ -84,7 +84,7 @@ class Function(pybamm.Symbol):
                     ) * child.diff(variable)
 
             # remove None entries
-            partial_derivatives = list(filter(None, partial_derivatives))
+            partial_derivatives = [x for x in partial_derivatives if x is not None]
 
             derivative = sum(partial_derivatives)
             if derivative == 0:
diff --git a/pybamm/expression_tree/symbol.py b/pybamm/expression_tree/symbol.py
index 4538ab694..f0c7f166e 100644
--- a/pybamm/expression_tree/symbol.py
+++ b/pybamm/expression_tree/symbol.py
@@ -656,6 +656,9 @@ class Symbol:
         """return an :class:`Modulo` object."""
         return pybamm.simplify_if_constant(pybamm.Modulo(self, other))
 
+    def __bool__(self):
+        raise NotImplementedError("Boolean operator not defined for Symbols.")
+
     def diff(self, variable):
         """
         Differentiate a symbol with respect to a variable. For any symbol that can be
diff --git a/pybamm/models/base_model.py b/pybamm/models/base_model.py
index feb44a607..53123be62 100644
--- a/pybamm/models/base_model.py
+++ b/pybamm/models/base_model.py
@@ -746,7 +746,7 @@ class BaseModel:
         div = "-----------------------------------------"
         symbol = find_symbol_in_model(self, symbol_name)
 
-        if not symbol:
+        if symbol is None:
             return None
 
         print(div)
@@ -1034,14 +1034,14 @@ def find_symbol_in_tree(tree, name):
     elif len(tree.children) > 0:
         for child in tree.children:
             child_return = find_symbol_in_tree(child, name)
-            if child_return:
+            if child_return is not None:
                 return child_return
 
 
 def find_symbol_in_dict(dic, name):
     for tree in dic.values():
         tree_return = find_symbol_in_tree(tree, name)
-        if tree_return:
+        if tree_return is not None:
             return tree_return
 
 
@@ -1049,7 +1049,7 @@ def find_symbol_in_model(model, name):
     dics = [model.rhs, model.algebraic, model.variables]
     for dic in dics:
         dic_return = find_symbol_in_dict(dic, name)
-        if dic_return:
+        if dic_return is not None:
             return dic_return
 
 
diff --git a/pybamm/models/submodels/particle/base_particle.py b/pybamm/models/submodels/particle/base_particle.py
index e7d839fbe..0d1514f55 100644
--- a/pybamm/models/submodels/particle/base_particle.py
+++ b/pybamm/models/submodels/particle/base_particle.py
@@ -39,16 +39,20 @@ class BaseParticle(pybamm.BaseSubModel):
 
         # Get surface concentration if not provided as fundamental variable to
         # solve for
-        c_s_surf = c_s_surf or pybamm.surf(c_s)
+        if c_s_surf is None:
+            c_s_surf = pybamm.surf(c_s)
         c_s_surf_av = pybamm.x_average(c_s_surf)
 
         c_scale = self.domain_param.c_max
 
         # Get average concentration(s) if not provided as fundamental variable to
         # solve for
-        c_s_xav = c_s_xav or pybamm.x_average(c_s)
-        c_s_rav = c_s_rav or pybamm.r_average(c_s)
-        c_s_av = c_s_av or pybamm.r_average(c_s_xav)
+        if c_s_xav is None:
+            c_s_xav = pybamm.x_average(c_s)
+        if c_s_rav is None:
+            c_s_rav = pybamm.r_average(c_s)
+        if c_s_av is None:
+            c_s_av = pybamm.r_average(c_s_xav)
 
         variables = {
             self.domain + " particle concentration": c_s,


Test patch:
diff --git a/tests/unit/test_expression_tree/test_symbol.py b/tests/unit/test_expression_tree/test_symbol.py
index 4beb4e59e..f31611f96 100644
--- a/tests/unit/test_expression_tree/test_symbol.py
+++ b/tests/unit/test_expression_tree/test_symbol.py
@@ -495,6 +495,15 @@ class TestIsZero(unittest.TestCase):
         self.assertFalse(pybamm.is_matrix_zero(b))
         self.assertFalse(pybamm.is_matrix_zero(c))
 
+    def test_bool(self):
+        a = pybamm.Symbol("a")
+        with self.assertRaisesRegex(NotImplementedError, "Boolean"):
+            bool(a)
+        # if statement calls Boolean
+        with self.assertRaisesRegex(NotImplementedError, "Boolean"):
+            if a > 1:
+                print("a is greater than 1")
+
 
 if __name__ == "__main__":
     print("Add -v for more debug output")