Skip to content

Commit

Permalink
#2418 working on thermal and mechanical models
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinsulzer committed Nov 5, 2022
1 parent 563a5d5 commit a55c522
Show file tree
Hide file tree
Showing 18 changed files with 124 additions and 120 deletions.
8 changes: 4 additions & 4 deletions pybamm/models/full_battery_models/lead_acid/basic_full.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,12 @@ def __init__(self, name="Basic full model"):
######################
# Porosity
######################
beta_surf = pybamm.concatenation(
pybamm.PrimaryBroadcast(param.n.beta_surf, "negative electrode"),
Delta_V = pybamm.concatenation(
pybamm.PrimaryBroadcast(param.n.Delta_V, "negative electrode"),
pybamm.PrimaryBroadcast(0, "separator"),
pybamm.PrimaryBroadcast(param.p.beta_surf, "positive electrode"),
pybamm.PrimaryBroadcast(param.p.Delta_V, "positive electrode"),
)
deps_dt = -beta_surf * a * j / param.F
deps_dt = -Delta_V * a * j / param.F
self.rhs[eps] = deps_dt
self.initial_conditions[eps] = param.epsilon_init
self.events.extend(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ def _get_standard_active_material_change_variables(self, deps_solid_dt):

variables = {
f"{Domain} electrode {self.phase_name}"
"active material volume fraction change": deps_solid_dt,
"active material volume fraction change [s-1]": deps_solid_dt,
f"X-averaged {domain} electrode {self.phase_name}"
"active material volume fraction change": deps_solid_dt_av,
"active material volume fraction change [s-1]": deps_solid_dt_av,
}

return variables
17 changes: 10 additions & 7 deletions pybamm/models/submodels/active_material/loss_active_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,18 @@ def get_coupled_variables(self, variables):
# This is loss of active material model by mechanical effects
if self.x_average is True:
stress_t_surf = variables[
f"X-averaged {domain} particle surface tangential stress"
f"X-averaged {domain} particle surface tangential stress [Pa]"
]
stress_r_surf = variables[
f"X-averaged {domain} particle surface radial stress"
f"X-averaged {domain} particle surface radial stress [Pa]"
]
else:
stress_t_surf = variables[
f"{Domain} particle surface tangential stress"
f"{Domain} particle surface tangential stress [Pa]"
]
stress_r_surf = variables[
f"{Domain} particle surface radial stress [Pa]"
]
stress_r_surf = variables[f"{Domain} particle surface radial stress"]

beta_LAM = self.domain_param.beta_LAM
stress_critical = self.domain_param.stress_critical
Expand Down Expand Up @@ -112,7 +114,7 @@ def get_coupled_variables(self, variables):
# until other reactions are implemented
j_sei = 0

j_stress_reaction = beta_LAM_sei * a * j_sei
j_stress_reaction = beta_LAM_sei * a * j_sei / param.F
deps_solid_dt += j_stress_reaction
variables.update(
self._get_standard_active_material_change_variables(deps_solid_dt)
Expand All @@ -127,12 +129,13 @@ def set_rhs(self, variables):
f"X-averaged {domain} electrode active material volume fraction"
]
deps_solid_dt = variables[
f"X-averaged {domain} electrode active material volume fraction change"
f"X-averaged {domain} electrode active material "
"volume fraction change [s-1]"
]
else:
eps_solid = variables[f"{Domain} electrode active material volume fraction"]
deps_solid_dt = variables[
f"{Domain} electrode active material volume fraction change"
f"{Domain} electrode active material volume fraction change [s-1]"
]

self.rhs = {eps_solid: deps_solid_dt}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ def get_coupled_variables(self, variables):
for variable_template in [
f"{Domain} electrode {{}}active material volume fraction",
f"X-averaged {domain} electrode {{}}active material volume fraction",
f"{Domain} electrode {{}}active material volume fraction change",
f"X-averaged {domain} electrode {{}}active material volume fraction change",
f"{Domain} electrode {{}}active material volume fraction change [s-1]",
f"X-averaged {domain} electrode {{}}active material "
"volume fraction change [s-1]",
]:
sumvar = sum(
variables[variable_template.format(phase + " ")] for phase in phases
Expand Down
9 changes: 6 additions & 3 deletions pybamm/models/submodels/particle/base_particle.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ def _get_effective_diffusivity(self, c, T):
stress_option = getattr(self.options, domain)["stress-induced diffusion"]

if stress_option == "true":
stress_factor = 1 + domain_param.theta * (c - domain_param.c_0) / (
1 + param.Theta * T
)
# Ai2019 eq [12]
Omega = domain_param.Omega
E = domain_param.E
nu = domain_param.nu
theta_M = Omega / (param.R * T) * (2 * Omega * E) / (9 * (1 - nu))
stress_factor = 1 + theta_M * (c - domain_param.c_0)
else:
stress_factor = 1

Expand Down
1 change: 1 addition & 0 deletions pybamm/models/submodels/particle/fickian_diffusion.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ def get_coupled_variables(self, variables):
)

if self.size_distribution is True:
R = variables[f"{Domain} {phase_name}particle sizes [m]"]
# Size-dependent flux variables
variables.update(self._get_standard_flux_distribution_variables(N_s))
f_a_dist = self.phase_param.f_a_dist(R)
Expand Down
63 changes: 31 additions & 32 deletions pybamm/models/submodels/particle_mechanics/base_mechanics.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,59 +57,59 @@ def _get_mechanical_results(self, variables):
T_xav = variables["X-averaged cell temperature [K]"]
eps_s = variables[f"{Domain} electrode active material volume fraction"]

if "Cell thickness change [m]" not in variables:
# thermal expansion
cell_thickness_change = T_xav * self.param.alpha_T_cell
else:
cell_thickness_change = variables["Cell thickness change [m]"]

Omega = domain_param.Omega
R0 = domain_param.prim.R
c_0 = domain_param.c_0
E0 = domain_param.E
nu = domain_param.nu
L0 = domain_param.L
c_init = pybamm.r_average(domain_param.prim.c_init)
v_change = pybamm.x_average(
eps_s * domain_param.prim.t_change(c_s_rav)
) - pybamm.x_average(eps_s * domain_param.prim.t_change(c_init))

cell_thickness_change += self.param.n_electrodes_parallel * v_change
electrode_thickness_change = self.param.n_electrodes_parallel * v_change
# Ai2019 eq [10]
disp_surf_dim = Omega * R0 / 3 * (c_s_rav - c_0)
# c0 reference concentration for no deformation
# stress evaluated at the surface of the particles
# Ai2019 eq [7] with r=R
stress_r_surf = pybamm.Scalar(0)
# c_s_rav is already multiplied by 3/R^3
# Ai2019 eq [8] with r=R
# c_s_rav is already multiplied by 3/R^3 inside r_average
stress_t_surf = Omega * E0 / 3.0 / (1.0 - nu) * (c_s_rav - c_s_surf)

return {
# Averages
stress_r_surf_av = pybamm.x_average(stress_r_surf)
stress_t_surf_av = pybamm.x_average(stress_t_surf)

variables = {
f"{Domain} particle surface tangential stress [Pa]": stress_t_surf,
f"{Domain} particle surface radial stress [Pa]": stress_r_surf,
f"{Domain} particle surface displacement [m]": disp_surf,
f"X-averaged {domain} particle surface "
"radial stress [Pa]": stress_r_surf_av,
f"X-averaged {domain} particle surface "
"tangential stress [Pa]": stress_t_surf_av,
"Cell thickness change [m]": cell_thickness_change,
f"{Domain} electrode thickness change [m]": electrode_thickness_change,
}

if (
"Negative electrode thickness change [m]" in variables
and "Positive electrode thickness change [m]" in variables
):
# thermal expansion
# Ai2019 eq [13]
thermal_expansion = self.param.alpha_T_cell * (T_xav - self.param.T_ref)
# calculate total cell thickness change
neg_thickness_change = variables["Negative electrode thickness change [m]"]
pos_thickness_change = variables["Positive electrode thickness change [m]"]
variables["Cell thickness change [m]"] = (
neg_thickness_change + pos_thickness_change + thermal_expansion
)

return variables

def _get_standard_surface_variables(self, variables):
"""
A private function to obtain the standard variables which
can be derived from the local particle crack surfaces.
Parameters
----------
l_cr : :class:`pybamm.Symbol`
The crack length in electrode particles.
a0 : :class:`pybamm.Symbol`
Smooth surface area to volume ratio.
Returns
-------
variables : dict
The variables which can be derived from the crack length.
"""
domain, Domain = self.domain_Domain
phase_name = self.phase_name

Expand All @@ -119,14 +119,13 @@ def _get_standard_surface_variables(self, variables):
]
R0 = self.domain_param.prim.R
rho_cr = self.domain_param.rho_cr
roughness = l_cr * 2 * rho_cr + 1 # the ratio of cracks to normal surface
a_cr = (roughness - 1) * a # normalised crack surface area
a_cr_dim = a_cr / R0 # crack surface area to volume ratio [m-1]
w_cr = self.domain_param.w_cr
roughness = 1 + 2 * l_cr * rho_cr * w_cr # ratio of cracks to normal surface
a_cr = (roughness - 1) * a # crack surface area to volume ratio

roughness_xavg = pybamm.x_average(roughness)
variables = {
f"{Domain} crack surface to volume ratio [m-1]": a_cr_dim,
f"{Domain} crack surface to volume ratio": a_cr,
f"{Domain} crack surface to volume ratio [m-1]": a_cr,
f"{Domain} electrode roughness ratio": roughness,
f"X-averaged {domain} electrode roughness ratio": roughness_xavg,
}
Expand Down
24 changes: 12 additions & 12 deletions pybamm/models/submodels/particle_mechanics/crack_propagation.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,17 @@ def get_coupled_variables(self, variables):
k_cr = self.domain_param.k_cr(T)
m_cr = self.domain_param.m_cr
b_cr = self.domain_param.b_cr
stress_t_surf = variables[f"{Domain} particle surface tangential stress"]
stress_t_surf = variables[f"{Domain} particle surface tangential stress [Pa]"]
l_cr = variables[f"{Domain} particle crack length [m]"]
# # compressive stress will not lead to crack propagation
dK_SIF = stress_t_surf * b_cr * pybamm.Sqrt(np.pi * l_cr) * (stress_t_surf >= 0)
dK_SIF = stress_t_surf * b_cr * pybamm.sqrt(np.pi * l_cr) * (stress_t_surf >= 0)
dl_cr = k_cr * (dK_SIF**m_cr) / self.param.t0_cr
variables.update(
{
f"{Domain} particle cracking rate": dl_cr,
f"X-averaged {domain} particle cracking rate": pybamm.x_average(dl_cr),
f"{Domain} particle cracking rate [m.s-1]": dl_cr,
f"X-averaged {domain} particle cracking rate [m.s-1]": pybamm.x_average(
dl_cr
),
}
)
return variables
Expand All @@ -84,22 +86,22 @@ def set_rhs(self, variables):

if self.x_average is True:
l_cr = variables[f"X-averaged {domain} particle crack length [m]"]
dl_cr = variables[f"X-averaged {domain} particle cracking rate"]
dl_cr = variables[f"X-averaged {domain} particle cracking rate [m.s-1]"]
else:
l_cr = variables[f"{Domain} particle crack length [m]"]
dl_cr = variables[f"{Domain} particle cracking rate"]
dl_cr = variables[f"{Domain} particle cracking rate [m.s-1]"]
self.rhs = {l_cr: dl_cr}

def set_initial_conditions(self, variables):
domain, Domain = self.domain_Domain

l_cr_0 = self.domain_param.l_cr_0
if self.x_average is True:
l_cr = variables[f"X-averaged {domain} particle crack length [m]"]
l0 = 1
else:
l_cr = variables[f"{Domain} particle crack length [m]"]
l0 = pybamm.PrimaryBroadcast(1, f"{domain} electrode")
self.initial_conditions = {l_cr: l0}
l_cr_0 = pybamm.PrimaryBroadcast(l_cr_0, f"{domain} electrode")
self.initial_conditions = {l_cr: l_cr_0}

def set_events(self, variables):
domain, Domain = self.domain_Domain
Expand All @@ -111,8 +113,6 @@ def set_events(self, variables):
self.events.append(
pybamm.Event(
f"{domain} particle crack length larger than particle radius",
self.domain_param.prim.R_typ / self.domain_param.l_cr_0
- pybamm.max(l_cr),
pybamm.EventType.TERMINATION,
self.domain_param.prim.R - pybamm.max(l_cr),
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def get_fundamental_variables(self):
return variables

def get_coupled_variables(self, variables):
param = self.param

depsdt_dict = {}
for domain in self.options.whole_cell_domains:
Expand All @@ -59,12 +60,14 @@ def get_coupled_variables(self, variables):
j_k_av = variables[
f"X-averaged {domain} interfacial current density"
]
depsdt_k_av = -domain_param.beta_surf * j_k_av
depsdt_k_av = (
-domain_param.DeltaV * domain_param.a * j_k_av / param.F
)
depsdt_k = pybamm.PrimaryBroadcast(depsdt_k_av, domain)
else:
Domain = domain.capitalize()
j_k = variables[f"{Domain} interfacial current density [A.m-2]"]
depsdt_k = -domain_param.beta_surf * j_k
depsdt_k = -domain_param.DeltaV * domain_param.a * j_k / param.F

depsdt_dict[domain] = depsdt_k
variables.update(self._get_standard_porosity_change_variables(depsdt_dict))
Expand Down
12 changes: 6 additions & 6 deletions pybamm/models/submodels/thermal/base_thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ def _get_standard_coupled_variables(self, variables):
else:
T_n = variables["Negative electrode temperature [K]"]
dUdT_n = variables["Negative electrode entropic change [V.K-1]"]
Q_rev_n = a_j_n * (param.Theta ** (-1) + T_n) * dUdT_n
Q_rev_p = a_j_p * (param.Theta ** (-1) + T_p) * dUdT_p
Q_rev_n = a_j_n * T_n * dUdT_n
Q_rev_p = a_j_p * T_p * dUdT_p
Q_rev = pybamm.concatenation(
*[
Q_rev_n,
Expand Down Expand Up @@ -231,10 +231,10 @@ def _x_average(self, var, var_cn, var_cp):
and positive current collectors in the geometry).
"""
out = (
self.param.n.l_cc * var_cn
+ self.param.l_x * pybamm.x_average(var)
+ self.param.p.l_cc * var_cp
) / self.param.l
self.param.n.L_cc * var_cn
+ self.param.L_x * pybamm.x_average(var)
+ self.param.p.L_cc * var_cp
) / self.param.L
return out

def _yz_average(self, var):
Expand Down
5 changes: 3 additions & 2 deletions pybamm/models/submodels/thermal/lumped.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ def set_rhs(self, variables):

self.rhs = {
T_vol_av: (
self.param.B * Q_vol_av + total_cooling_coefficient * (T_vol_av - T_amb)
self.lambda_eff(T_vol_av) * Q_vol_av
+ total_cooling_coefficient * (T_vol_av - T_amb)
)
/ (self.param.C_th * self.param.rho(T_vol_av))
/ self.param.rho_c_p_eff(T_vol_av)
}

def set_initial_conditions(self, variables):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ def set_rhs(self, variables):
self.rhs = {
T_av: (
pybamm.laplacian(T_av)
+ self.param.B * Q_av
+ Q_av
+ total_cooling_coefficient * (T_av - T_amb)
)
/ (self.param.C_th * self.param.rho(T_av))
/ self.param.rho_c_p(T_av)
}

def set_boundary_conditions(self, variables):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ def set_rhs(self, variables):
self.rhs = {
T_av: (
pybamm.laplacian(T_av)
+ self.param.B * pybamm.source(Q_av, T_av)
+ pybamm.source(Q_av, T_av)
+ yz_surface_cooling_coefficient * pybamm.source(T_av - T_amb, T_av)
- edge_cooling_coefficient
* pybamm.source(T_av - T_amb, T_av, boundary=True)
)
/ (self.param.C_th * self.param.rho(T_av))
/ self.param.rho_c_p(T_av)
}

# TODO: Make h_edge a function of position to have bottom/top/side cooled cells.
Expand Down
Loading

0 comments on commit a55c522

Please sign in to comment.