Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds gradient_squared method to FiniteVolume #4540

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
45 changes: 45 additions & 0 deletions src/pybamm/spatial_methods/finite_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,51 @@

return pybamm.Matrix(matrix)

def gradient_squared(self, symbol, discretised_symbol, boundary_conditions):
"""
Computes the square of the gradient of a symbol.

Parameters
----------
symbol : :class:`pybamm.Symbol`
The symbol for which to compute the gradient squared.
discretised_symbol : :class:`pybamm.Vector`
The discretised variable for which to compute the gradient squared.
medha-14 marked this conversation as resolved.
Show resolved Hide resolved
boundary_conditions : dict
Boundary conditions for the symbol.

Returns
-------
float
The gradient squared of the symbol.
"""
domain = symbol.domain

Check warning on line 149 in src/pybamm/spatial_methods/finite_volume.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/spatial_methods/finite_volume.py#L149

Added line #L149 was not covered by tests

if symbol in boundary_conditions:
bcs = boundary_conditions[symbol]
if any(bc[1] == "Dirichlet" for bc in bcs.values()):
discretised_symbol, domain = self.add_ghost_nodes(

Check warning on line 154 in src/pybamm/spatial_methods/finite_volume.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/spatial_methods/finite_volume.py#L151-L154

Added lines #L151 - L154 were not covered by tests
symbol, discretised_symbol, bcs
)
medha-14 marked this conversation as resolved.
Show resolved Hide resolved

gradient_matrix = self.gradient_matrix(domain, symbol.domains)

Check warning on line 158 in src/pybamm/spatial_methods/finite_volume.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/spatial_methods/finite_volume.py#L158

Added line #L158 was not covered by tests

# Compute gradient squared matrix: (∇u)^2 = u^T (L^T L) u
gradient_squared_matrix = gradient_matrix.T @ gradient_matrix
gradient_squared_result = (

Check warning on line 162 in src/pybamm/spatial_methods/finite_volume.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/spatial_methods/finite_volume.py#L161-L162

Added lines #L161 - L162 were not covered by tests
discretised_symbol.T @ gradient_squared_matrix @ discretised_symbol
)

# Add Neumann boundary conditions if defined
if symbol in boundary_conditions:
bcs = boundary_conditions[symbol]
if any(bc[1] == "Neumann" for bc in bcs.values()):
gradient_squared_result = self.add_neumann_values(

Check warning on line 170 in src/pybamm/spatial_methods/finite_volume.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/spatial_methods/finite_volume.py#L167-L170

Added lines #L167 - L170 were not covered by tests
symbol, gradient_squared_result, bcs, domain
)
medha-14 marked this conversation as resolved.
Show resolved Hide resolved

return gradient_squared_result.item()

Check warning on line 174 in src/pybamm/spatial_methods/finite_volume.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/spatial_methods/finite_volume.py#L174

Added line #L174 was not covered by tests

def divergence(self, symbol, discretised_symbol, boundary_conditions):
"""Matrix-vector multiplication to implement the divergence operator.
See :meth:`pybamm.SpatialMethod.divergence`
Expand Down
48 changes: 48 additions & 0 deletions tests/unit/test_spatial_methods/test_scikit_finite_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,54 @@ def test_gradient(self):
ans = eqn_disc.evaluate(None, 3 * y**2)
np.testing.assert_array_less(0, ans)

def test_gradient_squared(self):
mesh = get_unit_2p1D_mesh_for_testing(ypts=32, zpts=32, include_particles=False)
spatial_methods = {
"macroscale": pybamm.FiniteVolume(),
"current collector": pybamm.ScikitFiniteElement(),
}
disc = pybamm.Discretisation(mesh, spatial_methods)

var = pybamm.Variable("var", domain="current collector")
disc.set_variable_slices([var])

y = mesh["current collector"].coordinates[0, :]
z = mesh["current collector"].coordinates[1, :]

gradient = pybamm.grad(var)
grad_disc = disc.process_symbol(gradient)
grad_disc_y, grad_disc_z = grad_disc.children

gradient_squared = pybamm.grad_squared(var)
gradient_squared_disc = disc.process_symbol(gradient_squared)

inner_product_y = grad_disc_y.evaluate(None, 5 * y + 6 * z)
inner_product_z = grad_disc_z.evaluate(None, 5 * y + 6 * z)
inner_product = inner_product_y**2 + inner_product_z**2

grad_squared_result = gradient_squared_disc.evaluate(None, 5 * y + 6 * z)
np.testing.assert_array_almost_equal(grad_squared_result, inner_product)
np.testing.assert_array_less(0, grad_squared_result)

gradient_squared_disc_dirichlet = disc.process_symbol(gradient_squared)
grad_squared_result_dirichlet = gradient_squared_disc_dirichlet.evaluate(
None, 5 * y + 6 * z
)

np.testing.assert_array_almost_equal(
grad_squared_result_dirichlet, inner_product
)
np.testing.assert_array_less(0, grad_squared_result_dirichlet)

gradient_squared_disc_neumann = disc.process_symbol(gradient_squared)
grad_squared_result_neumann = gradient_squared_disc_neumann.evaluate(
None, 5 * y + 6 * z
)

np.testing.assert_array_almost_equal(grad_squared_result_neumann, inner_product)

np.testing.assert_array_less(0, grad_squared_result_neumann)

def test_manufactured_solution(self):
mesh = get_unit_2p1D_mesh_for_testing(ypts=32, zpts=32, include_particles=False)
spatial_methods = {
Expand Down
Loading