diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b428edc3..5f46b4b175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Features - Added the `num_steps_no_progress` and `t_no_progress` options in the `IDAKLUSolver` to early terminate the simulation if little progress is detected. ([#5201](https://github.com/pybamm-team/PyBaMM/pull/5201)) +- EvaluateAt symbol: add support for children evaluated at edges ([#5190](https://github.com/pybamm-team/PyBaMM/pull/5190)) - Added helper functions to import external 3D meshes in PyBaMM ([#5162](https://github.com/pybamm-team/PyBaMM/pull/5162)) - Added support for algebraic and differential surface form in composite models. ([#5165](https://github.com/pybamm-team/PyBaMM/pull/5165)) - Adds a composite electrode electrode soh model ([#5160](https://github.com/pybamm-team/PyBaMM/pull/5129)) diff --git a/src/pybamm/expression_tree/unary_operators.py b/src/pybamm/expression_tree/unary_operators.py index b4610898a3..bb771fa7db 100644 --- a/src/pybamm/expression_tree/unary_operators.py +++ b/src/pybamm/expression_tree/unary_operators.py @@ -1288,6 +1288,9 @@ def _evaluate_for_shape(self): """See :meth:`pybamm.Symbol.evaluate_for_shape_using_domain()`""" return pybamm.evaluate_for_shape_using_domain(self.domains) + def _evaluates_on_edges(self, dimension: str) -> bool: + return False + class UpwindDownwind(SpatialOperator): """ diff --git a/src/pybamm/spatial_methods/finite_volume.py b/src/pybamm/spatial_methods/finite_volume.py index e5ea4055a2..ce1cde56bd 100644 --- a/src/pybamm/spatial_methods/finite_volume.py +++ b/src/pybamm/spatial_methods/finite_volume.py @@ -1357,7 +1357,10 @@ def evaluate_at(self, symbol, discretised_child, position): # Get mesh nodes domain = discretised_child.domain mesh = self.mesh[domain] - nodes = mesh.nodes + if symbol.children[0].evaluates_on_edges("primary"): + nodes = mesh.edges + else: + nodes = mesh.nodes if hasattr(mesh, "length"): domain = discretised_child.domain raise NotImplementedError( @@ -1369,7 +1372,7 @@ def evaluate_at(self, symbol, discretised_child, position): index = np.argmin(np.abs(nodes - position.value)) # Create a sparse matrix with a 1 at the index - sub_matrix = csr_matrix(([1], ([0], [index])), shape=(1, mesh.npts)) + sub_matrix = csr_matrix(([1], ([0], [index])), shape=(1, len(nodes))) # repeat across auxiliary domains matrix = csr_matrix(kron(eye(repeats), sub_matrix)) diff --git a/tests/unit/test_spatial_methods/test_finite_volume/test_finite_volume.py b/tests/unit/test_spatial_methods/test_finite_volume/test_finite_volume.py index 5f311c75d4..218506b6f9 100644 --- a/tests/unit/test_spatial_methods/test_finite_volume/test_finite_volume.py +++ b/tests/unit/test_spatial_methods/test_finite_volume/test_finite_volume.py @@ -673,6 +673,22 @@ def test_evaluate_at(self): y = np.arange(n)[:, np.newaxis] assert evaluate_at_disc.evaluate(y=y) == y[idx] + disc.bcs = { + var: { + "left": (pybamm.Scalar(0), "Dirichlet"), + "right": (pybamm.Scalar(n - 1), "Dirichlet"), + } + } + position = pybamm.Scalar(mesh["negative electrode"].edges[-1]) + downwind_var = pybamm.downwind(var) + evaluate_at = pybamm.EvaluateAt(downwind_var, position) + + assert evaluate_at.evaluates_on_edges("primary") is False + + evaluate_at_disc = disc.process_symbol(evaluate_at) + + assert evaluate_at_disc.evaluate(y=y) == n - 1 + mesh = get_mesh_for_testing_symbolic() spatial_methods = {"domain": pybamm.FiniteVolume()} var = pybamm.Variable("var", domain="domain")