Skip to content

Commit

Permalink
Merge pull request #2063 from pybamm-team/parameter-domains
Browse files Browse the repository at this point in the history
Parameter domains
  • Loading branch information
valentinsulzer authored May 24, 2022
2 parents 134585f + c76b36f commit f649e6a
Show file tree
Hide file tree
Showing 98 changed files with 1,738 additions and 2,530 deletions.
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.

4 changes: 2 additions & 2 deletions examples/scripts/compare_lithium_ion_particle_distribution.py
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

0 comments on commit f649e6a

Please sign in to comment.