Repository: pybamm-team/PyBaMM (python)

Issue:
Add method to evaluate parameters
Add method `ParameterValues.evaluate` which processes a symbol and then evaluates it. Just saves a tiny bit of ugly syntax.

Pull request:
#668 add evaluate function
# Description

Add function to evaluate parameters more easily.
Fixes #668 

## Type of change

Please add a line in the relevant section of [CHANGELOG.md](https://github.com/pybamm-team/PyBaMM/blob/master/CHANGELOG.md) to document the change (include PR #) - note reverse order of PR #s.

- [x] New feature (non-breaking change which adds functionality)
- [ ] Optimization (back-end change that speeds up the code)
- [ ] Bug fix (non-breaking change which fixes an issue)


# Key checklist:

- [x] No style issues: `$ flake8`
- [x] All tests pass: `$ python run-tests.py --unit`
- [x] The documentation builds: `$ cd docs` and then `$ make clean; make html`

You can run all three at once, using `$ python run-tests.py --quick`.

## Further checks:

- [x] Code is commented, particularly in hard-to-understand areas
- [x] Tests added that prove fix is effective or that feature works


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb312ad6e..342d6bd17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,15 +2,16 @@
 
 ## Features
 
-- Add `Interpolant` class to interpolate experimental data (e.g. OCP curves) (#661)
-- Allow parameters to be set by material or by specifying a particular paper (#647)
-- Set relative and absolute tolerances independently in solvers (#645)
-- Add some non-uniform meshes in 1D and 2D (#617)
+- Add method to evaluate parameters more easily (#669 )
+- Add `Interpolant` class to interpolate experimental data (e.g. OCP curves) (#661 )
+- Allow parameters to be set by material or by specifying a particular paper (#647 )
+- Set relative and absolute tolerances independently in solvers (#645 )
+- Add some non-uniform meshes in 1D and 2D (#617 )
 
 ## Optimizations
 
-- Avoid re-checking size when making a copy of an `Index` object (#656)
-- Avoid recalculating `_evaluation_array` when making a copy of a `StateVector` object (#653)
+- Avoid re-checking size when making a copy of an `Index` object (#656 )
+- Avoid recalculating `_evaluation_array` when making a copy of a `StateVector` object (#653 )
 
 ## Bug fixes
 
diff --git a/examples/scripts/compare_comsol/compare_comsol_DFN.py b/examples/scripts/compare_comsol/compare_comsol_DFN.py
index 07081efae..817f34665 100644
--- a/examples/scripts/compare_comsol/compare_comsol_DFN.py
+++ b/examples/scripts/compare_comsol/compare_comsol_DFN.py
@@ -57,7 +57,7 @@ solution = pybamm_model.default_solver.solve(pybamm_model, time)
 # Make Comsol 'model' for comparison
 whole_cell = ["negative electrode", "separator", "positive electrode"]
 comsol_t = comsol_variables["time"]
-L_x = param.process_symbol(pybamm.standard_parameters_lithium_ion.L_x).evaluate()
+L_x = param.evaluate(pybamm.standard_parameters_lithium_ion.L_x)
 
 
 def get_interp_fun(variable, domain):
diff --git a/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py b/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py
index 0d3b0a643..793adeff0 100644
--- a/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py
+++ b/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py
@@ -123,15 +123,15 @@ class EffectiveResistance2D(pybamm.BaseModel):
         """
         # Get required processed parameters
         param = self.param
-        l_cn = param_values.process_symbol(param.l_cn).evaluate()
-        l_cp = param_values.process_symbol(param.l_cp).evaluate()
-        l_y = param_values.process_symbol(param.l_y).evaluate()
-        l_z = param_values.process_symbol(param.l_z).evaluate()
-        sigma_cn_prime = param_values.process_symbol(param.sigma_cn_prime).evaluate()
-        sigma_cp_prime = param_values.process_symbol(param.sigma_cp_prime).evaluate()
-        alpha = param_values.process_symbol(param.alpha).evaluate()
-        pot_scale = param_values.process_symbol(param.potential_scale).evaluate()
-        U_ref = param_values.process_symbol(param.U_p_ref - param.U_n_ref).evaluate()
+        l_cn = param_values.evaluate(param.l_cn)
+        l_cp = param_values.evaluate(param.l_cp)
+        l_y = param_values.evaluate(param.l_y)
+        l_z = param_values.evaluate(param.l_z)
+        sigma_cn_prime = param_values.evaluate(param.sigma_cn_prime)
+        sigma_cp_prime = param_values.evaluate(param.sigma_cp_prime)
+        alpha = param_values.evaluate(param.alpha)
+        pot_scale = param_values.evaluate(param.potential_scale)
+        U_ref = param_values.evaluate(param.U_p_ref - param.U_n_ref)
 
         # Process psi and W, and their (average) values at the negative tab
         psi = pybamm.ProcessedVariable(
diff --git a/pybamm/parameters/parameter_values.py b/pybamm/parameters/parameter_values.py
index 05f4b883e..5aff085d3 100644
--- a/pybamm/parameters/parameter_values.py
+++ b/pybamm/parameters/parameter_values.py
@@ -502,3 +502,23 @@ class ParameterValues(dict):
                         x.function.interpolate()
 
         return symbol
+
+    def evaluate(self, symbol):
+        """
+        Process and evaluate a symbol.
+
+        Parameters
+        ----------
+        symbol : :class:`pybamm.Symbol`
+            Symbol or Expression tree to evaluate
+
+        Returns
+        -------
+        number of array
+            The evaluated symbol
+        """
+        processed_symbol = self.process_symbol(symbol)
+        if processed_symbol.is_constant() and processed_symbol.evaluates_to_number():
+            return processed_symbol.evaluate()
+        else:
+            raise ValueError("symbol must evaluate to a constant scalar")
diff --git a/results/2plus1D/compare_lithium_ion_2plus1D.py b/results/2plus1D/compare_lithium_ion_2plus1D.py
index fb7c51b31..cce573d2d 100644
--- a/results/2plus1D/compare_lithium_ion_2plus1D.py
+++ b/results/2plus1D/compare_lithium_ion_2plus1D.py
@@ -79,8 +79,8 @@ plt.xlabel("Time [h]")
 plt.ylabel("Terminal voltage [V]")
 plt.legend()
 # add C-rate, delta, and alpha to title
-delta = param.process_symbol(pybamm.standard_parameters_lithium_ion.delta).evaluate()
-alpha = param.process_symbol(pybamm.standard_parameters_lithium_ion.alpha).evaluate()
+delta = param.evaluate(pybamm.standard_parameters_lithium_ion.delta)
+alpha = param.evaluate(pybamm.standard_parameters_lithium_ion.alpha)
 plt.title(
     r"C-rate = {:3d}, $\alpha$ = {:.6f} , $\delta$ = {:.6f}".format(
         C_rate, alpha, delta
diff --git a/results/2plus1D/compare_spmecc.py b/results/2plus1D/compare_spmecc.py
index 68dec7154..2f4cd2f13 100644
--- a/results/2plus1D/compare_spmecc.py
+++ b/results/2plus1D/compare_spmecc.py
@@ -63,9 +63,7 @@ for name in ["Average SPMe", "2+1D SPMe"]:
     # add current collector Ohmic losses to average SPMEe to get SPMeCC voltage
     if model.name == "Average SPMe":
         current = pybamm.ProcessedVariable(model.variables["Current [A]"], t, y)(t)
-        delta = param.process_symbol(
-            pybamm.standard_parameters_lithium_ion.delta
-        ).evaluate()
+        delta = param.evaluate(pybamm.standard_parameters_lithium_ion.delta)
         R_cc = param.process_symbol(
             cc_model.variables["Effective current collector resistance [Ohm]"]
         ).evaluate(
diff --git a/results/2plus1D/spm_2plus1D_tab_grid.py b/results/2plus1D/spm_2plus1D_tab_grid.py
index b4211bb40..88fa3e5dd 100644
--- a/results/2plus1D/spm_2plus1D_tab_grid.py
+++ b/results/2plus1D/spm_2plus1D_tab_grid.py
@@ -22,7 +22,7 @@ param = model.default_parameter_values
 # adjust current to correspond to a typical current density of 24 [A.m-2]
 C_rate = 1
 param["Typical current [A]"] = (
-    C_rate * 24 * param.process_symbol(pybamm.geometric_parameters.A_cc).evaluate()
+    C_rate * 24 * param.evaluate(pybamm.geometric_parameters.A_cc)
 )
 param.process_model(model)
 param.process_geometry(geometry)
@@ -39,9 +39,7 @@ var_pts = {
     var.z: 5,
 }
 submesh_types = model.default_submesh_types
-submesh_types[
-    "current collector"
-] = pybamm.ScikitExponential2DSubMesh
+submesh_types["current collector"] = pybamm.ScikitExponential2DSubMesh
 # depnding on number of points in y-z plane may need to increase recursion depth...
 sys.setrecursionlimit(10000)
 mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
diff --git a/results/2plus1D/spmecc.py b/results/2plus1D/spmecc.py
index 26776b15c..89360c571 100644
--- a/results/2plus1D/spmecc.py
+++ b/results/2plus1D/spmecc.py
@@ -41,7 +41,7 @@ t, y = solution.t, solution.y
 time = pybamm.ProcessedVariable(cell_model.variables["Time [h]"], t, y)(t)
 voltage = pybamm.ProcessedVariable(cell_model.variables["Terminal voltage [V]"], t, y)
 current = pybamm.ProcessedVariable(cell_model.variables["Current [A]"], t, y)(t)
-delta = param.process_symbol(pybamm.standard_parameters_lithium_ion.delta).evaluate()
+delta = param.evaluate(pybamm.standard_parameters_lithium_ion.delta)
 R_cc = param.process_symbol(
     cc_model.variables["Effective current collector resistance [Ohm]"]
 ).evaluate(t=cc_solution.t, y=cc_solution.y)[0][0]
diff --git a/results/2plus1D/user_mesh_spm_1plus1D.py b/results/2plus1D/user_mesh_spm_1plus1D.py
index 811ee2f98..a63950026 100644
--- a/results/2plus1D/user_mesh_spm_1plus1D.py
+++ b/results/2plus1D/user_mesh_spm_1plus1D.py
@@ -19,7 +19,7 @@ geometry = model.default_geometry
 # load parameter values and process model and geometry
 param = model.default_parameter_values
 C_rate = 1
-current_1C = 24 * param.process_symbol(pybamm.geometric_parameters.A_cc).evaluate()
+current_1C = 24 * param.evaluate(pybamm.geometric_parameters.A_cc)
 param.update(
     {
         "Typical current [A]": C_rate * current_1C,


Test patch:
diff --git a/tests/integration/test_models/standard_output_tests.py b/tests/integration/test_models/standard_output_tests.py
index 5c100105f..b019737fc 100644
--- a/tests/integration/test_models/standard_output_tests.py
+++ b/tests/integration/test_models/standard_output_tests.py
@@ -90,8 +90,8 @@ class BaseOutputTest(object):
             self.r_p_edge = disc.mesh["positive particle"][0].edges
 
         # Useful parameters
-        self.l_n = param.process_symbol(pybamm.geometric_parameters.l_n).evaluate()
-        self.l_p = param.process_symbol(pybamm.geometric_parameters.l_p).evaluate()
+        self.l_n = param.evaluate(pybamm.geometric_parameters.l_n)
+        self.l_p = param.evaluate(pybamm.geometric_parameters.l_p)
 
         if isinstance(self.model, pybamm.lithium_ion.BaseModel):
             current_param = pybamm.standard_parameters_lithium_ion.current_with_time
@@ -635,9 +635,9 @@ class VelocityTests(BaseOutputTest):
         t, x_n, x_p = self.t, self.x_n, self.x_p
 
         beta_n = pybamm.standard_parameters_lead_acid.beta_n
-        beta_n = self.param.process_symbol(beta_n).evaluate()
+        beta_n = self.param.evaluate(beta_n)
         beta_p = pybamm.standard_parameters_lead_acid.beta_p
-        beta_p = self.param.process_symbol(beta_p).evaluate()
+        beta_p = self.param.evaluate(beta_p)
 
         np.testing.assert_array_almost_equal(
             self.v_box(t, x_n), beta_n * self.i_e(t, x_n)
diff --git a/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py b/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py
index 555da6a43..73ad08911 100644
--- a/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py
+++ b/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py
@@ -21,122 +21,82 @@ class TestDimensionlessParameterValues(unittest.TestCase):
         "particle geometry"
         # a_n dimensional
         np.testing.assert_almost_equal(
-            values.process_symbol(param.a_n_dim).evaluate(None, None),
-            0.18 * 10 ** (6),
-            2,
+            values.evaluate(param.a_n_dim), 0.18 * 10 ** (6), 2
         )
         # R_n dimensional
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.R_n).evaluate(None, None), 1 * 10 ** (-5), 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.R_n), 1 * 10 ** (-5), 2)
 
         # a_n
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.a_n).evaluate(None, None), 1.8, 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.a_n), 1.8, 2)
 
         # a_p dimensional
         np.testing.assert_almost_equal(
-            values.process_symbol(param.a_p_dim).evaluate(None, None),
-            0.15 * 10 ** (6),
-            2,
+            values.evaluate(param.a_p_dim), 0.15 * 10 ** (6), 2
         )
 
         # R_p dimensional
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.R_n).evaluate(None, None), 1 * 10 ** (-5), 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.R_n), 1 * 10 ** (-5), 2)
 
         # a_p
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.a_p).evaluate(None, None), 1.5, 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.a_p), 1.5, 2)
 
         "reaction rates"
         # m_n*
         np.testing.assert_almost_equal(
-            values.process_symbol(param.m_n_dimensional(param.T_ref)).evaluate(
-                None, None
-            ),
-            2 * 10 ** (-5),
-            8,
+            values.evaluate(param.m_n_dimensional(param.T_ref)), 2 * 10 ** (-5), 8
         )
 
         np.testing.assert_almost_equal(
-            values.process_symbol(1 / param.C_r_n * c_rate).evaluate(None, None),
-            26.6639,
-            3,
+            values.evaluate(1 / param.C_r_n * c_rate), 26.6639, 3
         )
 
         # m_p*
         np.testing.assert_almost_equal(
-            values.process_symbol(param.m_p_dimensional(param.T_ref)).evaluate(
-                None, None
-            ),
-            6 * 10 ** (-7),
-            8,
+            values.evaluate(param.m_p_dimensional(param.T_ref)), 6 * 10 ** (-7), 8
         )
 
         # gamma_p / C_r_p
         np.testing.assert_almost_equal(
-            values.process_symbol(param.gamma_p / param.C_r_p * c_rate).evaluate(
-                None, None
-            ),
-            1.366,
-            3,
+            values.evaluate(param.gamma_p / param.C_r_p * c_rate), 1.366, 3
         )
 
         "particle dynamics"
         # neg diffusion coefficient
         np.testing.assert_almost_equal(
-            values.process_symbol(
-                param.D_n_dimensional(param.c_n_init, param.T_ref)
-            ).evaluate(None, None),
+            values.evaluate(param.D_n_dimensional(param.c_n_init, param.T_ref)),
             3.9 * 10 ** (-14),
             2,
         )
 
         # neg diffusion timescale
         np.testing.assert_almost_equal(
-            values.process_symbol(param.tau_diffusion_n).evaluate(None, None),
-            2.5641 * 10 ** (3),
-            2,
+            values.evaluate(param.tau_diffusion_n), 2.5641 * 10 ** (3), 2
         )
 
         # tau_n / tau_d (1/gamma_n in Scott's transfer)
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.C_n / c_rate).evaluate(None, None), 0.11346, 3
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.C_n / c_rate), 0.11346, 3)
 
         # pos diffusion coefficient
         np.testing.assert_almost_equal(
-            values.process_symbol(
-                param.D_p_dimensional(param.c_p_init, param.T_ref)
-            ).evaluate(None, None),
+            values.evaluate(param.D_p_dimensional(param.c_p_init, param.T_ref)),
             1 * 10 ** (-13),
             2,
         )
 
         # pos diffusion timescale
         np.testing.assert_almost_equal(
-            values.process_symbol(param.tau_diffusion_p).evaluate(None, None),
-            1 * 10 ** (3),
-            2,
+            values.evaluate(param.tau_diffusion_p), 1 * 10 ** (3), 2
         )
 
         # tau_p / tau_d (1/gamma_p in Scott's transfer)
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.C_p / c_rate).evaluate(None, None), 0.044249, 3
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.C_p / c_rate), 0.044249, 3)
 
         "electrolyte dynamics"
         # typical diffusion coefficient (we should change the typ value in paper to
         # match this one. We take this parameter excluding the exp(-0.65) in the
         # paper at the moment
         np.testing.assert_almost_equal(
-            values.process_symbol(
-                param.D_e_dimensional(param.c_e_typ, param.T_ref)
-            ).evaluate(None, None),
+            values.evaluate(param.D_e_dimensional(param.c_e_typ, param.T_ref)),
             5.34 * 10 ** (-10) * np.exp(-0.65),
             10,
         )
@@ -144,21 +104,15 @@ class TestDimensionlessParameterValues(unittest.TestCase):
         # electrolyte diffusion timescale (accounting for np.exp(-0.65) in
         # diffusion_typ). Change value in paper to this.
         np.testing.assert_almost_equal(
-            values.process_symbol(param.tau_diffusion_e).evaluate(None, None),
-            181.599,
-            3,
+            values.evaluate(param.tau_diffusion_e), 181.599, 3
         )
 
         # C_e
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.C_e / c_rate).evaluate(None, None), 0.008, 3
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.C_e / c_rate), 0.008, 3)
 
         # electrolyte conductivity
         np.testing.assert_almost_equal(
-            values.process_symbol(
-                param.kappa_e_dimensional(param.c_e_typ, param.T_ref)
-            ).evaluate(None, None),
+            values.evaluate(param.kappa_e_dimensional(param.c_e_typ, param.T_ref)),
             1.1045,
             3,
         )
@@ -167,32 +121,26 @@ class TestDimensionlessParameterValues(unittest.TestCase):
         # F R / T (should be equal to old 1 / Lambda)
         old_Lambda = 38
         np.testing.assert_almost_equal(
-            values.process_symbol(param.potential_scale).evaluate(None, None),
-            1 / old_Lambda,
-            3,
+            values.evaluate(param.potential_scale), 1 / old_Lambda, 3
         )
 
         "electrode conductivities"
         # neg dimensional
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.sigma_n_dim).evaluate(None, None), 100, 3
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.sigma_n_dim), 100, 3)
 
         # neg dimensionless (old sigma_n / old_Lambda ) (this is different to values
         # in paper so check again, it is close enough though for now)
         np.testing.assert_almost_equal(
-            values.process_symbol(param.sigma_n * c_rate).evaluate(None, None), 475.7, 1
+            values.evaluate(param.sigma_n * c_rate), 475.7, 1
         )
 
         # neg dimensional
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.sigma_p_dim).evaluate(None, None), 10, 3
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.sigma_p_dim), 10, 3)
 
         # neg dimensionless (old sigma_n / old_Lambda ) (this is different to values in
         # paper so check again, it is close enough for now though)
         np.testing.assert_almost_equal(
-            values.process_symbol(param.sigma_p * c_rate).evaluate(None, None), 47.57, 1
+            values.evaluate(param.sigma_p * c_rate), 47.57, 1
         )
 
     def test_thermal_parameters(self):
@@ -201,72 +149,48 @@ class TestDimensionlessParameterValues(unittest.TestCase):
         c_rate = param.i_typ / 24
 
         # Density
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.rho_cn).evaluate(), 1.9019, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.rho_n).evaluate(), 0.6403, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.rho_s).evaluate(), 0.1535, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.rho_p).evaluate(), 1.2605, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.rho_cp).evaluate(), 1.3403, 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.rho_cn), 1.9019, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.rho_n), 0.6403, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.rho_s), 0.1535, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.rho_p), 1.2605, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.rho_cp), 1.3403, 2)
 
         # Thermal conductivity
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.lambda_cn).evaluate(), 6.7513, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.lambda_n).evaluate(), 0.0296, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.lambda_s).evaluate(), 0.0027, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.lambda_p).evaluate(), 0.0354, 2
-        )
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.lambda_cp).evaluate(), 3.9901, 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.lambda_cn), 6.7513, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.lambda_n), 0.0296, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.lambda_s), 0.0027, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.lambda_p), 0.0354, 2)
+        np.testing.assert_almost_equal(values.evaluate(param.lambda_cp), 3.9901, 2)
 
         # other thermal parameters
 
         # note: in paper this is 0.0534 * c_rate which conflicts with this
         # if we do C_th * c_rate we get 0.0534 so probably error in paper
         # np.testing.assert_almost_equal(
-        #     values.process_symbol(param.C_th / c_rate).evaluate(), 0.0253, 2
+        #     values.evaluate(param.C_th / c_rate), 0.0253, 2
         # )
 
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.Theta / c_rate).evaluate(), 0.008, 2
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.Theta / c_rate), 0.008, 2)
 
-        np.testing.assert_almost_equal(
-            values.process_symbol(param.h).evaluate(), 3.7881 * 10 ** (-5), 7
-        )
+        np.testing.assert_almost_equal(values.evaluate(param.h), 3.7881 * 10 ** (-5), 7)
 
         # np.testing.assert_almost_equal(
-        #     values.process_symbol(param.B / c_rate).evaluate(), 36.216, 2
+        #     values.evaluate(param.B / c_rate), 36.216, 2
         # )
 
-        np.testing.assert_equal(values.process_symbol(param.T_init).evaluate(), 0)
+        np.testing.assert_equal(values.evaluate(param.T_init), 0)
 
         # test timescale
         # np.testing.assert_almost_equal(
-        #     values.process_symbol(param.tau_th_yz).evaluate(), 1.4762 * 10 ** (3), 2
+        #     values.evaluate(param.tau_th_yz), 1.4762 * 10 ** (3), 2
         # )
 
         # thermal = pybamm.thermal_parameters
         # np.testing.assert_almost_equal(
-        # values.process_symbol(thermal.rho_eff_dim).evaluate(), 1.8116 * 10 ** (6), 2
+        # values.evaluate(thermal.rho_eff_dim), 1.8116 * 10 ** (6), 2
         # )
         # np.testing.assert_almost_equal(
-        #     values.process_symbol(thermal.lambda_eff_dim).evaluate(), 59.3964, 2
+        #     values.evaluate(thermal.lambda_eff_dim), 59.3964, 2
         # )
 
     def test_parameter_functions(self):
@@ -276,17 +200,17 @@ class TestDimensionlessParameterValues(unittest.TestCase):
         c_test = pybamm.Scalar(0.5)
         T_test = pybamm.Scalar(0)
 
-        values.process_symbol(param.U_n(c_test, T_test)).evaluate()
-        values.process_symbol(param.U_p(c_test, T_test)).evaluate()
-        values.process_symbol(param.dUdT_n(c_test)).evaluate()
-        values.process_symbol(param.dUdT_p(c_test)).evaluate()
+        values.evaluate(param.U_n(c_test, T_test))
+        values.evaluate(param.U_p(c_test, T_test))
+        values.evaluate(param.dUdT_n(c_test))
+        values.evaluate(param.dUdT_p(c_test))
 
-        values.process_symbol(param.D_p(c_test, T_test)).evaluate()
-        values.process_symbol(param.D_n(c_test, T_test)).evaluate()
+        values.evaluate(param.D_p(c_test, T_test))
+        values.evaluate(param.D_n(c_test, T_test))
 
         c_e_test = pybamm.Scalar(1)
-        values.process_symbol(param.D_e(c_e_test, T_test)).evaluate()
-        values.process_symbol(param.kappa_e(c_e_test, T_test)).evaluate()
+        values.evaluate(param.D_e(c_e_test, T_test))
+        values.evaluate(param.kappa_e(c_e_test, T_test))
 
 
 if __name__ == "__main__":
diff --git a/tests/unit/test_parameters/test_parameter_values.py b/tests/unit/test_parameters/test_parameter_values.py
index db92388f9..fca7caf83 100644
--- a/tests/unit/test_parameters/test_parameter_values.py
+++ b/tests/unit/test_parameters/test_parameter_values.py
@@ -451,6 +451,21 @@ class TestParameterValues(unittest.TestCase):
         ):
             parameter_values.process_model(model)
 
+    def test_evaluate(self):
+        parameter_values = pybamm.ParameterValues({"a": 1, "b": 2, "c": 3})
+        a = pybamm.Parameter("a")
+        b = pybamm.Parameter("b")
+        c = pybamm.Parameter("c")
+        self.assertEqual(parameter_values.evaluate(a), 1)
+        self.assertEqual(parameter_values.evaluate(a + (b * c)), 7)
+
+        y = pybamm.StateVector(slice(0, 1))
+        with self.assertRaises(ValueError):
+            parameter_values.evaluate(y)
+        array = pybamm.Array(np.array([1, 2, 3]))
+        with self.assertRaises(ValueError):
+            parameter_values.evaluate(array)
+
 
 if __name__ == "__main__":
     print("Add -v for more debug output")