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

Parameter domains #2063

Merged
merged 11 commits into from
May 24, 2022
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

## Breaking changes

- Changed domain-specific parameter names to a nested attribute, e.g. `param.c_n_max` is now `param.n.c_max` ([#2063](https://github.com/pybamm-team/PyBaMM/pull/2063))

# [v22.3](https://github.com/pybamm-team/PyBaMM/tree/v22.3) - 2022-03-31

## Features
Expand Down
12 changes: 6 additions & 6 deletions examples/notebooks/models/compare-ecker-data.ipynb

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions examples/notebooks/models/electrode-state-of-health.ipynb

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions examples/notebooks/models/lithium-plating.ipynb

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions examples/notebooks/simulating-long-experiments.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
def negative_radius(x):
"Negative particle radius as a function of through-cell position (x_n [m])"
R_n_0 = params[0]["Negative particle radius [m]"]
grading = 1 + 2 * x / models[1].param.L_n
grading = 1 + 2 * x / models[1].param.n.L
return grading * R_n_0


def positive_radius(x):
"Positive particle radius as a function of through-cell position (x_p [m])"
R_p_0 = params[0]["Positive particle radius [m]"]
grading = 1 + 2 * (models[1].param.L_x - x) / models[1].param.L_p
grading = 1 + 2 * (models[1].param.L_x - x) / models[1].param.p.L
return grading * R_p_0


Expand Down
10 changes: 5 additions & 5 deletions pybamm/expression_tree/averages.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ def x_average(symbol):
isinstance(child, pybamm.Broadcast) for child in symbol.children
):
geo = pybamm.geometric_parameters
l_n = geo.l_n
l_s = geo.l_s
l_p = geo.l_p
l_n = geo.n.l
l_s = geo.s.l
l_p = geo.p.l
if symbol.domain == ["negative electrode", "separator", "positive electrode"]:
a, b, c = [orp.orphans[0] for orp in symbol.orphans]
out = (l_n * a + l_s * b + l_p * c) / (l_n + l_s + l_p)
Expand Down Expand Up @@ -341,7 +341,7 @@ def size_average(symbol, f_a_dist=None):
"R", domains=symbol.domains, coord_sys="cartesian"
)
if ["negative particle size"] in symbol.domains.values():
f_a_dist = geo.f_a_dist_n(R)
f_a_dist = geo.n.f_a_dist(R)
elif ["positive particle size"] in symbol.domains.values():
f_a_dist = geo.f_a_dist_p(R)
f_a_dist = geo.p.f_a_dist(R)
return SizeAverage(symbol, f_a_dist)
28 changes: 14 additions & 14 deletions pybamm/geometry/battery_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ def battery_geometry(

"""
geo = pybamm.geometric_parameters
l_n = geo.l_n
l_s = geo.l_s
l_n = geo.n.l
l_s = geo.s.l
l_n_l_s = l_n + l_s
# Override print_name
l_n_l_s.print_name = "l_n + l_s"
Expand All @@ -55,10 +55,10 @@ def battery_geometry(
)
# Add particle size domains
if options is not None and options["particle size"] == "distribution":
R_min_n = geo.R_min_n
R_min_p = geo.R_min_p
R_max_n = geo.R_max_n
R_max_p = geo.R_max_p
R_min_n = geo.n.R_min
R_min_p = geo.p.R_min
R_max_n = geo.n.R_max
R_max_p = geo.p.R_max
geometry.update(
{
"negative particle size": {"R_n": {"min": R_min_n, "max": R_max_n}},
Expand All @@ -73,8 +73,8 @@ def battery_geometry(
geometry["current collector"] = {
"z": {"min": 0, "max": 1},
"tabs": {
"negative": {"z_centre": geo.centre_z_tab_n},
"positive": {"z_centre": geo.centre_z_tab_p},
"negative": {"z_centre": geo.n.centre_z_tab},
"positive": {"z_centre": geo.p.centre_z_tab},
},
}
elif current_collector_dimension == 2:
Expand All @@ -83,14 +83,14 @@ def battery_geometry(
"z": {"min": 0, "max": geo.l_z},
"tabs": {
"negative": {
"y_centre": geo.centre_y_tab_n,
"z_centre": geo.centre_z_tab_n,
"width": geo.l_tab_n,
"y_centre": geo.n.centre_y_tab,
"z_centre": geo.n.centre_z_tab,
"width": geo.n.l_tab,
},
"positive": {
"y_centre": geo.centre_y_tab_p,
"z_centre": geo.centre_z_tab_p,
"width": geo.l_tab_p,
"y_centre": geo.p.centre_y_tab,
"z_centre": geo.p.centre_z_tab,
"width": geo.p.l_tab,
},
},
}
Expand Down
6 changes: 1 addition & 5 deletions pybamm/models/full_battery_models/base_battery_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1161,11 +1161,7 @@ def set_voltage_variables(self):
# Variables for calculating the equivalent circuit model (ECM) resistance
# Need to compare OCV to initial value to capture this as an overpotential
ocv_init = self.param.ocv_init
ocv_init_dim = (
self.param.U_p_ref
- self.param.U_n_ref
+ self.param.potential_scale * ocv_init
)
ocv_init_dim = self.param.ocv_ref + self.param.potential_scale * ocv_init
eta_ocv = ocv - ocv_init
eta_ocv_dim = ocv_dim - ocv_init_dim
# Current collector current density for working out euiqvalent resistance
Expand Down
44 changes: 21 additions & 23 deletions pybamm/models/full_battery_models/lead_acid/basic_full.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,22 @@ def __init__(self, name="Basic full model"):

# transport_efficiency
tor = pybamm.concatenation(
eps_n ** param.b_e_n, eps_s ** param.b_e_s, eps_p ** param.b_e_p
eps_n ** param.n.b_e, eps_s ** param.s.b_e, eps_p ** param.p.b_e
)

# Interfacial reactions
j0_n = param.j0_n(c_e_n, T)
j0_n = param.n.j0(c_e_n, T)
j_n = (
2
* j0_n
* pybamm.sinh(param.ne_n / 2 * (phi_s_n - phi_e_n - param.U_n(c_e_n, T)))
* pybamm.sinh(param.n.ne / 2 * (phi_s_n - phi_e_n - param.n.U(c_e_n, T)))
)
j0_p = param.j0_p(c_e_p, T)
j0_p = param.p.j0(c_e_p, T)
j_s = pybamm.PrimaryBroadcast(0, "separator")
j_p = (
2
* j0_p
* pybamm.sinh(param.ne_p / 2 * (phi_s_p - phi_e_p - param.U_p(c_e_p, T)))
* pybamm.sinh(param.p.ne / 2 * (phi_s_p - phi_e_p - param.p.U(c_e_p, T)))
)
j = pybamm.concatenation(j_n, j_s, j_p)

Expand All @@ -136,14 +136,14 @@ def __init__(self, name="Basic full model"):
######################
v_n = -pybamm.grad(pressure_n)
v_p = -pybamm.grad(pressure_p)
l_s = param.l_s
l_n = param.l_n
l_s = param.s.l
l_n = param.n.l
x_s = pybamm.SpatialVariable("x_s", domain="separator")

# Difference in negative and positive electrode velocities determines the
# velocity in the separator
v_n_right = param.beta_n * i_cell
v_p_left = param.beta_p * i_cell
v_n_right = param.n.beta * i_cell
v_p_left = param.p.beta * i_cell
d_v_s__dx = (v_p_left - v_n_right) / l_s

# Simple formula for velocity in the separator
Expand All @@ -159,8 +159,8 @@ def __init__(self, name="Basic full model"):
pybamm.PrimaryBroadcast(0, "positive electrode"),
)
# Simple formula for velocity in the separator
self.algebraic[pressure_n] = pybamm.div(v_n) - param.beta_n * j_n
self.algebraic[pressure_p] = pybamm.div(v_p) - param.beta_p * j_p
self.algebraic[pressure_n] = pybamm.div(v_n) - param.n.beta * j_n
self.algebraic[pressure_p] = pybamm.div(v_p) - param.p.beta * j_p
self.boundary_conditions[pressure_n] = {
"left": (pybamm.Scalar(0), "Neumann"),
"right": (pybamm.Scalar(0), "Dirichlet"),
Expand All @@ -183,13 +183,13 @@ def __init__(self, name="Basic full model"):
"left": (pybamm.Scalar(0), "Neumann"),
"right": (pybamm.Scalar(0), "Neumann"),
}
self.initial_conditions[phi_e] = -param.U_n_init
self.initial_conditions[phi_e] = -param.n.U_init

######################
# Current in the solid
######################
i_s_n = -param.sigma_n(T) * (1 - eps_n) ** param.b_s_n * pybamm.grad(phi_s_n)
sigma_eff_p = param.sigma_p(T) * (1 - eps_p) ** param.b_s_p
i_s_n = -param.n.sigma(T) * (1 - eps_n) ** param.n.b_s * pybamm.grad(phi_s_n)
sigma_eff_p = param.p.sigma(T) * (1 - eps_p) ** param.p.b_s
i_s_p = -sigma_eff_p * pybamm.grad(phi_s_p)
# The `algebraic` dictionary contains differential equations, with the key being
# the main scalar variable of interest in the equation
Expand All @@ -213,9 +213,9 @@ def __init__(self, name="Basic full model"):
# Porosity
######################
beta_surf = pybamm.concatenation(
pybamm.PrimaryBroadcast(param.beta_surf_n, "negative electrode"),
pybamm.PrimaryBroadcast(param.n.beta_surf, "negative electrode"),
pybamm.PrimaryBroadcast(0, "separator"),
pybamm.PrimaryBroadcast(param.beta_surf_p, "positive electrode"),
pybamm.PrimaryBroadcast(param.p.beta_surf, "positive electrode"),
)
deps_dt = -beta_surf * j
self.rhs[eps] = deps_dt
Expand Down Expand Up @@ -246,9 +246,9 @@ def __init__(self, name="Basic full model"):
+ param.C_e * c_e * v
)
s = pybamm.concatenation(
pybamm.PrimaryBroadcast(param.s_plus_n_S, "negative electrode"),
pybamm.PrimaryBroadcast(param.n.s_plus_S, "negative electrode"),
pybamm.PrimaryBroadcast(0, "separator"),
pybamm.PrimaryBroadcast(param.s_plus_p_S, "positive electrode"),
pybamm.PrimaryBroadcast(param.p.s_plus_S, "positive electrode"),
)
self.rhs[c_e] = (1 / eps) * (
-pybamm.div(N_e) / param.C_e
Expand Down Expand Up @@ -279,11 +279,9 @@ def __init__(self, name="Basic full model"):
"Electrolyte concentration": c_e,
"Current [A]": I,
"Negative electrode potential [V]": pot * phi_s_n,
"Electrolyte potential [V]": -param.U_n_ref + pot * phi_e,
"Positive electrode potential [V]": param.U_p_ref
- param.U_n_ref
+ pot * phi_s_p,
"Terminal voltage [V]": param.U_p_ref - param.U_n_ref + pot * voltage,
"Electrolyte potential [V]": -param.n.U_ref + pot * phi_e,
"Positive electrode potential [V]": param.ocv_ref + pot * phi_s_p,
"Terminal voltage [V]": param.ocv_ref + pot * voltage,
"Porosity": eps,
"Volume-averaged velocity": v,
"X-averaged separator transverse volume-averaged velocity": div_V_s,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def __init__(self, options=None, name="Unnamed lithium-ion model", build=False):
"negative electrode": self.param.L_x,
"separator": self.param.L_x,
"positive electrode": self.param.L_x,
"positive particle": self.param.R_p_typ,
"positive particle size": self.param.R_p_typ,
"positive particle": self.param.p.R_typ,
"positive particle size": self.param.p.R_typ,
"current collector y": self.param.L_z,
"current collector z": self.param.L_z,
}
Expand All @@ -38,8 +38,8 @@ def __init__(self, options=None, name="Unnamed lithium-ion model", build=False):
if not self.half_cell:
self.length_scales.update(
{
"negative particle": self.param.R_n_typ,
"negative particle size": self.param.R_n_typ,
"negative particle": self.param.n.R_typ,
"negative particle size": self.param.n.R_typ,
}
)
self.set_standard_output_variables()
Expand Down Expand Up @@ -79,10 +79,10 @@ def set_standard_output_variables(self):

# Particle concentration position
var = pybamm.standard_spatial_vars
self.variables.update({"r_p": var.r_p, "r_p [m]": var.r_p * self.param.R_p_typ})
self.variables.update({"r_p": var.r_p, "r_p [m]": var.r_p * self.param.p.R_typ})
if not self.half_cell:
self.variables.update(
{"r_n": var.r_n, "r_n [m]": var.r_n * self.param.R_n_typ}
{"r_n": var.r_n, "r_n [m]": var.r_n * self.param.n.R_typ}
)

def set_degradation_variables(self):
Expand All @@ -96,11 +96,11 @@ def set_degradation_variables(self):
else:
C_n = self.variables["Negative electrode capacity [A.h]"]
n_Li_n = self.variables["Total lithium in negative electrode [mol]"]
LAM_ne = (1 - C_n / param.C_n_init) * 100
LAM_ne = (1 - C_n / param.n.cap_init) * 100

C_p = self.variables["Positive electrode capacity [A.h]"]

LAM_pe = (1 - C_p / param.C_p_init) * 100
LAM_pe = (1 - C_p / param.p.cap_init) * 100

# LLI
n_Li_e = self.variables["Total lithium in electrolyte [mol]"]
Expand Down
44 changes: 22 additions & 22 deletions pybamm/models/full_battery_models/lithium_ion/basic_dfn.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,30 +115,30 @@ def __init__(self, name="Doyle-Fuller-Newman model"):

# transport_efficiency
tor = pybamm.concatenation(
eps_n ** param.b_e_n, eps_s ** param.b_e_s, eps_p ** param.b_e_p
eps_n ** param.n.b_e, eps_s ** param.s.b_e, eps_p ** param.p.b_e
)

# Interfacial reactions
# Surf takes the surface value of a variable, i.e. its boundary value on the
# right side. This is also accessible via `boundary_value(x, "right")`, with
# "left" providing the boundary value of the left side
c_s_surf_n = pybamm.surf(c_s_n)
j0_n = param.gamma_n * param.j0_n(c_e_n, c_s_surf_n, T) / param.C_r_n
j0_n = param.n.gamma * param.n.j0(c_e_n, c_s_surf_n, T) / param.n.C_r
j_n = (
2
* j0_n
* pybamm.sinh(
param.ne_n / 2 * (phi_s_n - phi_e_n - param.U_n(c_s_surf_n, T))
param.n.ne / 2 * (phi_s_n - phi_e_n - param.n.U(c_s_surf_n, T))
)
)
c_s_surf_p = pybamm.surf(c_s_p)
j0_p = param.gamma_p * param.j0_p(c_e_p, c_s_surf_p, T) / param.C_r_p
j0_p = param.p.gamma * param.p.j0(c_e_p, c_s_surf_p, T) / param.p.C_r
j_s = pybamm.PrimaryBroadcast(0, "separator")
j_p = (
2
* j0_p
* pybamm.sinh(
param.ne_p / 2 * (phi_s_p - phi_e_p - param.U_p(c_s_surf_p, T))
param.p.ne / 2 * (phi_s_p - phi_e_p - param.p.U(c_s_surf_p, T))
)
)
j = pybamm.concatenation(j_n, j_s, j_p)
Expand All @@ -159,35 +159,35 @@ def __init__(self, name="Doyle-Fuller-Newman model"):

# The div and grad operators will be converted to the appropriate matrix
# multiplication at the discretisation stage
N_s_n = -param.D_n(c_s_n, T) * pybamm.grad(c_s_n)
N_s_p = -param.D_p(c_s_p, T) * pybamm.grad(c_s_p)
self.rhs[c_s_n] = -(1 / param.C_n) * pybamm.div(N_s_n)
self.rhs[c_s_p] = -(1 / param.C_p) * pybamm.div(N_s_p)
N_s_n = -param.n.D(c_s_n, T) * pybamm.grad(c_s_n)
N_s_p = -param.p.D(c_s_p, T) * pybamm.grad(c_s_p)
self.rhs[c_s_n] = -(1 / param.n.C_diff) * pybamm.div(N_s_n)
self.rhs[c_s_p] = -(1 / param.p.C_diff) * pybamm.div(N_s_p)
# Boundary conditions must be provided for equations with spatial derivatives
self.boundary_conditions[c_s_n] = {
"left": (pybamm.Scalar(0), "Neumann"),
"right": (
-param.C_n
-param.n.C_diff
* j_n
/ param.a_R_n
/ param.gamma_n
/ param.D_n(c_s_surf_n, T),
/ param.n.a_R
/ param.n.gamma
/ param.n.D(c_s_surf_n, T),
"Neumann",
),
}
self.boundary_conditions[c_s_p] = {
"left": (pybamm.Scalar(0), "Neumann"),
"right": (
-param.C_p
-param.p.C_diff
* j_p
/ param.a_R_p
/ param.gamma_p
/ param.D_p(c_s_surf_p, T),
/ param.p.a_R
/ param.p.gamma
/ param.p.D(c_s_surf_p, T),
"Neumann",
),
}
self.initial_conditions[c_s_n] = param.c_n_init
self.initial_conditions[c_s_p] = param.c_p_init
self.initial_conditions[c_s_n] = param.n.c_init
self.initial_conditions[c_s_p] = param.p.c_init
# Events specify points at which a solution should terminate
self.events += [
pybamm.Event(
Expand All @@ -210,9 +210,9 @@ def __init__(self, name="Doyle-Fuller-Newman model"):
######################
# Current in the solid
######################
sigma_eff_n = param.sigma_n(T) * eps_s_n ** param.b_s_n
sigma_eff_n = param.n.sigma(T) * eps_s_n ** param.n.b_s
i_s_n = -sigma_eff_n * pybamm.grad(phi_s_n)
sigma_eff_p = param.sigma_p(T) * eps_s_p ** param.b_s_p
sigma_eff_p = param.p.sigma(T) * eps_s_p ** param.p.b_s
i_s_p = -sigma_eff_p * pybamm.grad(phi_s_p)
# The `algebraic` dictionary contains differential equations, with the key being
# the main scalar variable of interest in the equation
Expand Down Expand Up @@ -245,7 +245,7 @@ def __init__(self, name="Doyle-Fuller-Newman model"):
"left": (pybamm.Scalar(0), "Neumann"),
"right": (pybamm.Scalar(0), "Neumann"),
}
self.initial_conditions[phi_e] = -param.U_n_init
self.initial_conditions[phi_e] = -param.n.U_init

######################
# Electrolyte concentration
Expand Down
Loading