Repository: pybamm-team/PyBaMM

Issue:
Parameter processing for geometry
**Describe the bug**
In the case where your model has no parameters you still need to define an empty pybamm.ParameterValues() and process the geometry.

**To Reproduce**
Steps to reproduce the behaviour:
1. Go to 'training_workshop/exercise2_solving_a_pde.py'
2. Comment line 53 out
3. Run the code

**Expected behaviour**
I get the following error:
```
Traceback (most recent call last):
  File "examples/workshop_exercises/exercise2_solving_a_pde.py", line 58, in <module>
    mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
  File "/home/ferran/PyBaMM/pybamm/meshes/meshes.py", line 87, in __init__
    geometry[domain]["primary"], submesh_pts[domain]
  File "/home/ferran/PyBaMM/pybamm/meshes/submeshes.py", line 49, in __init__
    edges = np.linspace(spatial_lims["min"], spatial_lims["max"], npts + 1)
  File "<__array_function__ internals>", line 6, in linspace
  File "/home/ferran/PyBaMM/env/lib/python3.6/site-packages/numpy/core/function_base.py", line 138, in linspace
    dt = result_type(start, stop, float(num))
  File "<__array_function__ internals>", line 6, in result_type
TypeError: data type not understood

```


Discussion:

Patch:
diff --git a/pybamm/meshes/meshes.py b/pybamm/meshes/meshes.py
index 933544132..4b144f33a 100644
--- a/pybamm/meshes/meshes.py
+++ b/pybamm/meshes/meshes.py
@@ -72,6 +72,27 @@ class Mesh(dict):
             if domain not in ["negative electrode", "separator", "positive electrode"]:
                 self.domain_order.append(domain)
 
+        # evaluate any expressions in geometry
+        for domain in geometry:
+            for prim_sec_tabs, variables in geometry[domain].items():
+                # process tab information if using 2D current collectors
+                if prim_sec_tabs == "tabs":
+                    for tab, position_size in variables.items():
+                        for position_size, sym in position_size.items():
+                            if isinstance(sym, pybamm.Symbol):
+                                sym_eval = sym.evaluate()
+                                geometry[domain][prim_sec_tabs][tab][
+                                    position_size
+                                ] = sym_eval
+                else:
+                    for spatial_variable, spatial_limits in variables.items():
+                        for lim, sym in spatial_limits.items():
+                            if isinstance(sym, pybamm.Symbol):
+                                sym_eval = sym.evaluate()
+                                geometry[domain][prim_sec_tabs][spatial_variable][
+                                    lim
+                                ] = sym_eval
+
         # Create submeshes
         for domain in geometry:
             # need to pass tab information if primary domian is 2D current collector
diff --git a/pybamm/parameters/parameter_values.py b/pybamm/parameters/parameter_values.py
index 9b84f2730..115dae34c 100644
--- a/pybamm/parameters/parameter_values.py
+++ b/pybamm/parameters/parameter_values.py
@@ -178,7 +178,7 @@ class ParameterValues(dict):
 
     def process_geometry(self, geometry):
         """
-        Assign parameter values to a geometry (inplace), *and* evaluate.
+        Assign parameter values to a geometry (inplace).
 
         Parameters
         ----------
@@ -191,17 +191,15 @@ class ParameterValues(dict):
                 if prim_sec_tabs == "tabs":
                     for tab, position_size in variables.items():
                         for position_size, sym in position_size.items():
-                            sym_eval = self.process_symbol(sym).evaluate()
                             geometry[domain][prim_sec_tabs][tab][
                                 position_size
-                            ] = sym_eval
+                            ] = self.process_symbol(sym)
                 else:
                     for spatial_variable, spatial_limits in variables.items():
                         for lim, sym in spatial_limits.items():
-                            sym_eval = self.process_symbol(sym).evaluate()
                             geometry[domain][prim_sec_tabs][spatial_variable][
                                 lim
-                            ] = sym_eval
+                            ] = self.process_symbol(sym)
 
     def process_symbol(self, symbol):
         """Walk through the symbol and replace any Parameter with a Value.


Test patch:
diff --git a/tests/unit/test_meshes/test_meshes.py b/tests/unit/test_meshes/test_meshes.py
index 4e442ebd7..52fafc776 100644
--- a/tests/unit/test_meshes/test_meshes.py
+++ b/tests/unit/test_meshes/test_meshes.py
@@ -7,6 +7,35 @@ import unittest
 
 
 class TestMesh(unittest.TestCase):
+    def test_mesh_creation_no_parameters(self):
+        r = pybamm.SpatialVariable(
+            "r", domain=["negative particle"], coord_sys="spherical polar"
+        )
+
+        geometry = {
+            "negative particle": {
+                "primary": {r: {"min": pybamm.Scalar(0), "max": pybamm.Scalar(1)}}
+            }
+        }
+
+        submesh_types = {"negative particle": pybamm.Uniform1DSubMesh}
+        var_pts = {r: 20}
+        mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
+
+        # create mesh
+        mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
+
+        # check boundary locations
+        self.assertEqual(mesh["negative particle"][0].edges[0], 0)
+        self.assertEqual(mesh["negative particle"][0].edges[-1], 1)
+
+        # check number of edges and nodes
+        self.assertEqual(len(mesh["negative particle"][0].nodes), var_pts[r])
+        self.assertEqual(
+            len(mesh["negative particle"][0].edges),
+            len(mesh["negative particle"][0].nodes) + 1
+        )
+
     def test_mesh_creation(self):
         param = pybamm.ParameterValues(
             base_parameters={
diff --git a/tests/unit/test_meshes/test_scikit_fem_submesh.py b/tests/unit/test_meshes/test_scikit_fem_submesh.py
index 73c4e7041..540cdac9b 100644
--- a/tests/unit/test_meshes/test_scikit_fem_submesh.py
+++ b/tests/unit/test_meshes/test_scikit_fem_submesh.py
@@ -76,7 +76,8 @@ class TestScikitFiniteElement2DSubMesh(unittest.TestCase):
 
         var = pybamm.standard_spatial_vars
         var_pts = {var.x_n: 10, var.x_s: 10, var.x_p: 10, var.y: 10, var.z: 10}
-        with self.assertRaises(TypeError):
+        # there are parameters in the variables that need to be processed
+        with self.assertRaises(NotImplementedError):
             pybamm.Mesh(geometry, submesh_types, var_pts)
 
         lims = {var.x_n: {"min": pybamm.Scalar(0), "max": pybamm.Scalar(1)}}