Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

## Bug fixes

- Heat of mixing can now be built with quadratic and quartic particle profiles; their radial concentration gradients are evaluated analytically instead of applying a finite-volume gradient to a reconstructed profile. ([#5902](https://github.com/pybamm-team/PyBaMM/pull/5902))

- `"intercalation kinetics": "Marcus"` now gives a positive current for a positive overpotential, as the other kinetics do, and converts the reorganization energy from eV with F/RT, as Marcus-Hush-Chidsey does. Previously the oxidation and reduction terms were swapped and the energy was used in mixed units, so models with Marcus kinetics failed to solve. ([#5872](https://github.com/pybamm-team/PyBaMM/pull/5872))
- Evaluating a processed variable at a 0-d array time, e.g. `solution["Voltage [V]"](np.array(10.0))`, now returns the same value as passing the float rather than raising an `IndexError`. ([#5762](https://github.com/pybamm-team/PyBaMM/pull/5762))
- Fixed the particle concentration of the `"quartic profile"` particle model in models that resolve the electrode (e.g. DFN), which was missing a factor of the particle radius on the concentration gradient term and diverged to unphysical values. ([#5893](https://github.com/pybamm-team/PyBaMM/pull/5893))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,25 @@ def _heat_of_mixing(self, variables):
F = pybamm.constants.F.value
pi = np.pi

def radial_gradient_squared(concentration):
# Polynomial profiles already define concentration as a function of
# radius; use its analytic derivative instead of a finite-volume one.
radial_variable = next(
(
symbol
for symbol in concentration.pre_order()
if isinstance(symbol, pybamm.SpatialVariable)
and symbol.coord_sys == "spherical polar"
),
None,
)
if radial_variable is not None:
derivative = concentration.diff(radial_variable)
return derivative**2

gradient = pybamm.grad(concentration)
return pybamm.inner(gradient, gradient)

# Compute heat of mixing in negative electrode
if self.options.electrode_types["negative"] == "planar":
Q_mix_s_n = pybamm.FullBroadcast(
Expand All @@ -408,7 +427,7 @@ def _heat_of_mixing(self, variables):
c_n = variables["Negative particle concentration [mol.m-3]"]
T_n = variables["Negative electrode temperature [K]"]
T_n_part = pybamm.PrimaryBroadcast(T_n, ["negative particle"])
dc_n_dr2 = pybamm.inner(pybamm.grad(c_n), pybamm.grad(c_n))
dc_n_dr2 = radial_gradient_squared(c_n)
D_n = self.param.n.prim.D(c_n, T_n_part)
dUeq_n = self.param.n.prim.U(
c_n / self.param.n.prim.c_max, T_n_part
Expand All @@ -431,7 +450,7 @@ def _heat_of_mixing(self, variables):
c_p = variables["Positive particle concentration [mol.m-3]"]
T_p = variables["Positive electrode temperature [K]"]
T_p_part = pybamm.PrimaryBroadcast(T_p, ["positive particle"])
dc_p_dr2 = pybamm.inner(pybamm.grad(c_p), pybamm.grad(c_p))
dc_p_dr2 = radial_gradient_squared(c_p)
D_p = self.param.p.prim.D(c_p, T_p_part)
dUeq_p = self.param.p.prim.U(c_p / self.param.p.prim.c_max, T_p_part).diff(
c_p
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,25 @@ def R_contact(T):
# cell heats up above the reference, so R (and hence the contact
# overpotential magnitude) is larger than the constant case
np.testing.assert_array_less(np.abs(dphi_const[1:]), np.abs(dphi_fn[1:]))

@pytest.mark.parametrize(
("model_class", "particle_profile"),
[
(pybamm.lithium_ion.SPM, "Fickian diffusion"),
(pybamm.lithium_ion.SPM, "quadratic profile"),
(pybamm.lithium_ion.SPM, "quartic profile"),
(pybamm.lithium_ion.DFN, "Fickian diffusion"),
(pybamm.lithium_ion.DFN, "quadratic profile"),
(pybamm.lithium_ion.DFN, "quartic profile"),
],
)
def test_heat_of_mixing_with_particle_profile(self, model_class, particle_profile):
model = model_class(
{
"particle": particle_profile,
"thermal": "lumped",
"heat of mixing": "true",
}
)

pybamm.Simulation(model).build()