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

separate boundary grad and value extrapolation, make grad default quadratic #4614

Merged
merged 8 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion examples/scripts/compare_extrapolations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
sim_lin.solve([0, 3600])

model_quad = pybamm.lead_acid.Full()
method_options = {"extrapolation": {"order": "quadratic", "use bcs": False}}
method_options = {
"extrapolation": {
"order": {"gradient": "quadratic", "value": "quadratic"},
"use bcs": False,
}
}
spatial_methods = {
"negative particle": pybamm.FiniteVolume(method_options),
"positive particle": pybamm.FiniteVolume(method_options),
Expand Down
19 changes: 10 additions & 9 deletions src/pybamm/spatial_methods/finite_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,8 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
if bcs is None:
bcs = {}

extrap_order = self.options["extrapolation"]["order"]
extrap_order_gradient = self.options["extrapolation"]["order"]["gradient"]
extrap_order_value = self.options["extrapolation"]["order"]["value"]
use_bcs = self.options["extrapolation"]["use bcs"]

nodes = submesh.nodes
Expand All @@ -850,7 +851,7 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
additive = bcs[child][symbol.side][0]

elif symbol.side == "left":
if extrap_order == "linear":
if extrap_order_value == "linear":
# to find value at x* use formula:
# f(x*) = f_1 - (dx0 / dx1) (f_2 - f_1)

Expand All @@ -868,7 +869,7 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
)
additive = pybamm.Scalar(0)

elif extrap_order == "quadratic":
elif extrap_order_value == "quadratic":
if use_bcs and pybamm.has_bc_of_form(
child, symbol.side, bcs, "Neumann"
):
Expand All @@ -895,7 +896,7 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
raise NotImplementedError

elif symbol.side == "right":
if extrap_order == "linear":
if extrap_order_value == "linear":
if use_bcs and pybamm.has_bc_of_form(
child, symbol.side, bcs, "Neumann"
):
Expand All @@ -917,7 +918,7 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
shape=(1, prim_pts),
)
additive = pybamm.Scalar(0)
elif extrap_order == "quadratic":
elif extrap_order_value == "quadratic":
if use_bcs and pybamm.has_bc_of_form(
child, symbol.side, bcs, "Neumann"
):
Expand Down Expand Up @@ -958,14 +959,14 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
additive = bcs[child][symbol.side][0]

elif symbol.side == "left":
if extrap_order == "linear":
if extrap_order_gradient == "linear":
# f'(x*) = (f_2 - f_1) / dx1
sub_matrix = (1 / dx1) * csr_matrix(
([-1, 1], ([0, 0], [0, 1])), shape=(1, prim_pts)
)
additive = pybamm.Scalar(0)

elif extrap_order == "quadratic":
elif extrap_order_gradient == "quadratic":
a = -(2 * dx0 + 2 * dx1 + dx2) / (dx1**2 + dx1 * dx2)
b = (2 * dx0 + dx1 + dx2) / (dx1 * dx2)
c = -(2 * dx0 + dx1) / (dx1 * dx2 + dx2**2)
Expand All @@ -978,7 +979,7 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
raise NotImplementedError

elif symbol.side == "right":
if extrap_order == "linear":
if extrap_order_gradient == "linear":
# use formula:
# f'(x*) = (f_N - f_Nm1) / dxNm1
sub_matrix = (1 / dxNm1) * csr_matrix(
Expand All @@ -987,7 +988,7 @@ def boundary_value_or_flux(self, symbol, discretised_child, bcs=None):
)
additive = pybamm.Scalar(0)

elif extrap_order == "quadratic":
elif extrap_order_gradient == "quadratic":
a = (2 * dxN + 2 * dxNm1 + dxNm2) / (dxNm1**2 + dxNm1 * dxNm2)
b = -(2 * dxN + dxNm1 + dxNm2) / (dxNm1 * dxNm2)
c = (2 * dxN + dxNm1) / (dxNm1 * dxNm2 + dxNm2**2)
Expand Down
7 changes: 6 additions & 1 deletion src/pybamm/spatial_methods/spatial_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ class SpatialMethod:
"""

def __init__(self, options=None):
self.options = {"extrapolation": {"order": "linear", "use bcs": False}}
self.options = {
"extrapolation": {
"order": {"gradient": "quadratic", "value": "linear"},
kratman marked this conversation as resolved.
Show resolved Hide resolved
"use bcs": False,
}
}

# update double-layered dict
if options:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ def test_leading_order_convergence(self):
var_pts = {"x_n": 3, "x_s": 3, "x_p": 3}
mesh = pybamm.Mesh(geometry, full_model.default_submesh_types, var_pts)

method_options = {"extrapolation": {"order": "linear", "use bcs": False}}
method_options = {
"extrapolation": {
"order": {"gradient": "linear", "value": "linear"},
"use bcs": False,
}
}
spatial_methods = {
"macroscale": pybamm.FiniteVolume(method_options),
"current collector": pybamm.ZeroDimensionalSpatialMethod(method_options),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ def get_errors(function, method_options, pts, bcs=None):
class TestExtrapolation:
def test_convergence_without_bcs(self):
# all tests are performed on x in [0, 1]
linear = {"extrapolation": {"order": "linear"}}
quad = {"extrapolation": {"order": "quadratic"}}
linear = {"extrapolation": {"order": {"gradient": "linear", "value": "linear"}}}
quad = {
"extrapolation": {"order": {"gradient": "quadratic", "value": "quadratic"}}
}

def x_squared(x):
y = x**2
Expand Down Expand Up @@ -147,8 +149,18 @@ def x_cubed(x):

bcs = {"left": (left_val, "Dirichlet"), "right": (right_flux, "Neumann")}

linear = {"extrapolation": {"order": "linear", "use bcs": True}}
quad = {"extrapolation": {"order": "quadratic", "use bcs": True}}
linear = {
"extrapolation": {
"order": {"gradient": "linear", "value": "linear"},
"use bcs": True,
}
}
quad = {
"extrapolation": {
"order": {"gradient": "quadratic", "value": "quadratic"},
"use bcs": True,
}
}
l_errors_lin_no_bc, r_errors_lin_no_bc = get_errors(x_cubed, linear, pts)
l_errors_quad_no_bc, r_errors_quad_no_bc = get_errors(x_cubed, quad, pts)

Expand Down Expand Up @@ -202,8 +214,18 @@ def x_cubed(x):

bcs = {"left": (left_flux, "Neumann"), "right": (right_val, "Dirichlet")}

linear = {"extrapolation": {"order": "linear", "use bcs": True}}
quad = {"extrapolation": {"order": "quadratic", "use bcs": True}}
linear = {
"extrapolation": {
"order": {"gradient": "linear", "value": "linear"},
"use bcs": True,
}
}
quad = {
"extrapolation": {
"order": {"gradient": "quadratic", "value": "quadratic"},
"use bcs": True,
}
}
l_errors_lin_no_bc, r_errors_lin_no_bc = get_errors(x_cubed, linear, pts)
l_errors_quad_no_bc, r_errors_quad_no_bc = get_errors(x_cubed, quad, pts)

Expand Down Expand Up @@ -237,7 +259,12 @@ def x_cubed(x):
def test_linear_extrapolate_left_right(self):
# create discretisation
mesh = get_mesh_for_testing()
method_options = {"extrapolation": {"order": "linear", "use bcs": True}}
method_options = {
"extrapolation": {
"order": {"gradient": "linear", "value": "linear"},
"use bcs": True,
}
}
spatial_methods = {
"macroscale": pybamm.FiniteVolume(method_options),
"negative particle": pybamm.FiniteVolume(method_options),
Expand Down Expand Up @@ -308,7 +335,12 @@ def test_linear_extrapolate_left_right(self):
def test_quadratic_extrapolate_left_right(self):
# create discretisation
mesh = get_mesh_for_testing()
method_options = {"extrapolation": {"order": "quadratic", "use bcs": False}}
method_options = {
"extrapolation": {
"order": {"gradient": "quadratic", "value": "quadratic"},
"use bcs": False,
}
}
spatial_methods = {
"macroscale": pybamm.FiniteVolume(method_options),
"negative particle": pybamm.FiniteVolume(method_options),
Expand Down Expand Up @@ -402,7 +434,12 @@ def test_extrapolate_on_nonuniform_grid(self):
rpts = 10
var_pts = {"r_n": rpts, "r_p": rpts}
mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
method_options = {"extrapolation": {"order": "linear", "use bcs": False}}
method_options = {
"extrapolation": {
"order": {"gradient": "linear", "value": "linear"},
"use bcs": False,
}
}
spatial_methods = {"negative particle": pybamm.FiniteVolume(method_options)}
disc = pybamm.Discretisation(mesh, spatial_methods)

Expand All @@ -429,7 +466,12 @@ def test_extrapolate_on_nonuniform_grid(self):
def test_extrapolate_2d_models(self):
# create discretisation
mesh = get_p2d_mesh_for_testing()
method_options = {"extrapolation": {"order": "linear", "use bcs": False}}
method_options = {
"extrapolation": {
"order": {"gradient": "linear", "value": "linear"},
"use bcs": False,
}
}
spatial_methods = {
"macroscale": pybamm.FiniteVolume(method_options),
"negative particle": pybamm.FiniteVolume(method_options),
Expand Down