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

Make basic models compatible with experiments #3995

Merged
merged 17 commits into from
May 9, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Features

- "Basic" models are now compatible with experiments ([#3995](https://github.com/pybamm-team/PyBaMM/pull/3995))
- Updates multiprocess `Pool` in `BaseSolver.solve()` to be constructed with context `fork`. Adds small example for multiprocess inputs. ([#3974](https://github.com/pybamm-team/PyBaMM/pull/3974))
- Added custom experiment steps ([#3835](https://github.com/pybamm-team/PyBaMM/pull/3835))
- Added support for macOS arm64 (M-series) platforms. ([#3789](https://github.com/pybamm-team/PyBaMM/pull/3789))
Expand Down
19 changes: 19 additions & 0 deletions pybamm/models/full_battery_models/lithium_ion/basic_dfn.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def __init__(self, name="Doyle-Fuller-Newman model"):
######################
# Variables that depend on time only are created without a domain
Q = pybamm.Variable("Discharge capacity [A.h]")

# Variables that vary spatially are created with a domain
c_e_n = pybamm.Variable(
"Negative electrolyte concentration [mol.m-3]",
Expand Down Expand Up @@ -240,21 +241,39 @@ def __init__(self, name="Doyle-Fuller-Newman model"):
# (Some) variables
######################
voltage = pybamm.boundary_value(phi_s_p, "right")
num_cells = pybamm.Parameter(
"Number of cells connected in series to make a battery"
)
# The `variables` dictionary contains all variables that might be useful for
# visualising the solution of the model
self.variables = {
"Negative particle concentration [mol.m-3]": c_s_n,
"Negative particle surface concentration [mol.m-3]": c_s_surf_n,
"Electrolyte concentration [mol.m-3]": c_e,
"Negative electrolyte concentration [mol.m-3]": c_e_n,
"Separator electrolyte concentration [mol.m-3]": c_e_s,
"Positive electrolyte concentration [mol.m-3]": c_e_p,
"Positive particle concentration [mol.m-3]": c_s_p,
"Positive particle surface concentration [mol.m-3]": c_s_surf_p,
"Current [A]": I,
"Current variable [A]": I, # for compatibility with pybamm.Experiment
"Negative electrode potential [V]": phi_s_n,
"Electrolyte potential [V]": phi_e,
"Negative electrolyte potential [V]": phi_e_n,
"Separator electrolyte potential [V]": phi_e_s,
"Positive electrolyte potential [V]": phi_e_p,
"Positive electrode potential [V]": phi_s_p,
"Voltage [V]": voltage,
"Battery voltage [V]": voltage * num_cells,
"Time [s]": pybamm.t,
"Discharge capacity [A.h]": Q,
}
# Events specify points at which a solution should terminate
self.events += [
pybamm.Event("Minimum voltage [V]", voltage - param.voltage_low_cut),
pybamm.Event("Maximum voltage [V]", param.voltage_high_cut - voltage),
]
# Summary variables is a list of variables that can be accessed and plotted
# per-cycle when running experiments. Typically used to track degradation
# variables (e.g LAM, LLI, capacity fade, etc.)
self.summary_variables = ["Time [s]", "Voltage [V]"]
Original file line number Diff line number Diff line change
Expand Up @@ -341,18 +341,40 @@
ocp_av_p = pybamm.x_average(ocp_p)
a_j_n_p1_av = pybamm.x_average(a_j_n_p1)
a_j_n_p2_av = pybamm.x_average(a_j_n_p2)
num_cells = pybamm.Parameter(
"Number of cells connected in series to make a battery"
)
# The `variables` dictionary contains all variables that might be useful for
# visualising the solution of the model
self.variables = {
"Negative primary particle concentration [mol.m-3]": c_s_n_p1,
"Negative secondary particle concentration [mol.m-3]": c_s_n_p2,
"R-averaged negative primary particle concentration "
"[mol.m-3]": c_s_rav_n_p1,
"R-averaged negative secondary particle concentration "
"[mol.m-3]": c_s_rav_n_p2,
"Average negative primary particle concentration "
"[mol.m-3]": c_s_xrav_n_p1,
"Average negative secondary particle concentration "
"[mol.m-3]": c_s_xrav_n_p2,
"Positive particle concentration [mol.m-3]": c_s_p,
"Average positive particle concentration [mol.m-3]": c_s_xrav_p,
"Electrolyte concentration [mol.m-3]": c_e,
"Negative electrolyte concentration [mol.m-3]": c_e_n,
"Separator electrolyte concentration [mol.m-3]": c_e_s,
"Positive electrolyte concentration [mol.m-3]": c_e_p,
"Negative electrode potential [V]": phi_s_n,
"Electrolyte potential [V]": phi_e,
"Positive electrode potential [V]": phi_s_p,
"Electrolyte potential [V]": phi_e,
"Negative electrolyte potential [V]": phi_e_n,
"Separator electrolyte potential [V]": phi_e_s,
"Positive electrolyte potential [V]": phi_e_p,
"Current [A]": I,
"Current variable [A]": I, # for compatibility with pybamm.Experiment
"Discharge capacity [A.h]": Q,
"Time [s]": pybamm.t,
"Voltage [V]": voltage,
"Battery voltage [V]": voltage * num_cells,
"Negative electrode primary open-circuit potential [V]": ocp_n_p1,
"Negative electrode secondary open-circuit potential [V]": ocp_n_p2,
"X-averaged negative electrode primary open-circuit potential "
Expand All @@ -361,15 +383,6 @@
"[V]": ocp_av_n_p2,
"Positive electrode open-circuit potential [V]": ocp_p,
"X-averaged positive electrode open-circuit potential [V]": ocp_av_p,
"R-averaged negative primary particle concentration "
"[mol.m-3]": c_s_rav_n_p1,
"R-averaged negative secondary particle concentration "
"[mol.m-3]": c_s_rav_n_p2,
"Average negative primary particle concentration "
"[mol.m-3]": c_s_xrav_n_p1,
"Average negative secondary particle concentration "
"[mol.m-3]": c_s_xrav_n_p2,
"Average positive particle concentration [mol.m-3]": c_s_xrav_p,
"Negative electrode primary interfacial current density [A.m-2]": j_n_p1,
"Negative electrode secondary interfacial current density [A.m-2]": j_n_p2,
"X-averaged negative electrode primary interfacial current density "
Expand All @@ -385,7 +398,16 @@
"X-averaged negative electrode secondary volumetric "
"interfacial current density [A.m-3]": a_j_n_p2_av,
}
# Events specify points at which a solution should terminate
self.events += [
pybamm.Event("Minimum voltage [V]", voltage - param.voltage_low_cut),
pybamm.Event("Maximum voltage [V]", param.voltage_high_cut - voltage),
]
# Summary variables is a list of variables that can be accessed and plotted
# per-cycle when running experiments. Typically used to track degradation
# variables (e.g LAM, LLI, capacity fade, etc.)
self.summary_variables = ["Time [s]", "Voltage [V]"]

@property
def default_parameter_values(self):
return pybamm.ParameterValues("Chen2020_composite")

Check warning on line 413 in pybamm/models/full_battery_models/lithium_ion/basic_dfn_composite.py

View check run for this annotation

Codecov / codecov/patch

pybamm/models/full_battery_models/lithium_ion/basic_dfn_composite.py#L413

Added line #L413 was not covered by tests
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@ def __init__(self, options=None, name="Doyle-Fuller-Newman half cell model"):
vdrop_cell = pybamm.boundary_value(phi_s_w, "right") - ref_potential
vdrop_Li = -eta_Li - delta_phis_Li
voltage = vdrop_cell + vdrop_Li
num_cells = pybamm.Parameter(
"Number of cells connected in series to make a battery"
)

c_e_total = pybamm.x_average(eps * c_e)
c_s_surf_w_av = pybamm.x_average(c_s_surf_w)

Expand Down Expand Up @@ -286,16 +290,26 @@ def __init__(self, options=None, name="Doyle-Fuller-Newman half cell model"):
"Positive particle concentration [mol.m-3]": c_s_w,
"Total lithium in positive electrode [mol]": c_s_vol_av * L_w * param.A_cc,
"Electrolyte concentration [mol.m-3]": c_e,
"Separator electrolyte concentration [mol.m-3]": c_e_s,
"Positive electrolyte concentration [mol.m-3]": c_e_w,
"Total lithium in electrolyte [mol]": c_e_total * param.L_x * param.A_cc,
"Current [A]": I,
"Current variable [A]": I, # for compatibility with pybamm.Experiment
"Current density [A.m-2]": i_cell,
"Positive electrode potential [V]": phi_s_w,
"Positive electrode open-circuit potential [V]": U_w(sto_surf_w, T),
"Electrolyte potential [V]": phi_e,
"Separator electrolyte potential [V]": phi_e_s,
"Positive electrolyte potential [V]": phi_e_w,
"Voltage drop in the cell [V]": vdrop_cell,
"Negative electrode exchange current density [A.m-2]": j_Li,
"Negative electrode reaction overpotential [V]": eta_Li,
"Negative electrode potential drop [V]": delta_phis_Li,
"Voltage [V]": voltage,
"Battery voltage [V]": voltage * num_cells,
"Instantaneous power [W.m-2]": i_cell * voltage,
}
# Summary variables is a list of variables that can be accessed and plotted
# per-cycle when running experiments. Typically used to track degradation
# variables (e.g LAM, LLI, capacity fade, etc.)
self.summary_variables = ["Time [s]", "Voltage [V]"]
13 changes: 13 additions & 0 deletions pybamm/models/full_battery_models/lithium_ion/basic_spm.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,26 +139,33 @@ def __init__(self, name="Single Particle Model"):
phi_e = -eta_n - param.n.prim.U(sto_surf_n, T)
phi_s_p = eta_p + phi_e + param.p.prim.U(sto_surf_p, T)
V = phi_s_p
num_cells = pybamm.Parameter(
"Number of cells connected in series to make a battery"
)

whole_cell = ["negative electrode", "separator", "positive electrode"]
# The `variables` dictionary contains all variables that might be useful for
# visualising the solution of the model
# Primary broadcasts are used to broadcast scalar quantities across a domain
# into a vector of the right shape, for multiplying with other vectors
self.variables = {
"Time [s]": pybamm.t,
"Discharge capacity [A.h]": Q,
"X-averaged negative particle concentration [mol.m-3]": c_s_n,
"Negative particle surface "
"concentration [mol.m-3]": pybamm.PrimaryBroadcast(
c_s_surf_n, "negative electrode"
),
"Electrolyte concentration [mol.m-3]": pybamm.PrimaryBroadcast(
param.c_e_init_av, whole_cell
),
"X-averaged positive particle concentration [mol.m-3]": c_s_p,
"Positive particle surface "
"concentration [mol.m-3]": pybamm.PrimaryBroadcast(
c_s_surf_p, "positive electrode"
),
"Current [A]": I,
"Current variable [A]": I, # for compatibility with pybamm.Experiment
"Negative electrode potential [V]": pybamm.PrimaryBroadcast(
phi_s_n, "negative electrode"
),
Expand All @@ -167,8 +174,14 @@ def __init__(self, name="Single Particle Model"):
phi_s_p, "positive electrode"
),
"Voltage [V]": V,
"Battery voltage [V]": V * num_cells,
}
# Events specify points at which a solution should terminate
self.events += [
pybamm.Event("Minimum voltage [V]", V - param.voltage_low_cut),
pybamm.Event("Maximum voltage [V]", param.voltage_high_cut - V),
]
# Summary variables is a list of variables that can be accessed and plotted
# per-cycle when running experiments. Typically used to track degradation
# variables (e.g LAM, LLI, capacity fade, etc.)
self.summary_variables = ["Time [s]", "Voltage [V]"]
6 changes: 0 additions & 6 deletions pybamm/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@ def __init__(
self._parameter_values = parameter_values or model.default_parameter_values
self._unprocessed_parameter_values = self._parameter_values

if isinstance(model, pybamm.lithium_ion.BasicDFNHalfCell):
if experiment is not None:
raise NotImplementedError(
"BasicDFNHalfCell is not compatible with experiment simulations."
)

if experiment is None:
# Check to see if the current is provided as data (i.e. drive cycle)
current = self._parameter_values.get("Current function [A]")
Expand Down
2 changes: 2 additions & 0 deletions pybamm/solvers/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,8 @@ def _get_cycle_summary_variables(cycle_solution, esoh_solver, user_inputs=None):
esoh_solver is not None
and isinstance(model, pybamm.lithium_ion.BaseModel)
and model.options.electrode_types["negative"] == "porous"
and "Negative electrode capacity [A.h]" in model.variables
and "Positive electrode capacity [A.h]" in model.variables
):
Q_n = last_state["Negative electrode capacity [A.h]"].data[0]
Q_p = last_state["Positive electrode capacity [A.h]"].data[0]
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#
# Test basic model classes
#
from tests import TestCase
import pybamm

import unittest


class BaseBasicModelTest:
def test_with_experiment(self):
model = self.model
experiment = pybamm.Experiment(
[
"Discharge at C/3 until 3.5V",
"Hold at 3.5V for 1 hour",
"Rest for 10 min",
]
)
sim = pybamm.Simulation(model, experiment=experiment)
sim.solve(calc_esoh=False)


class TestBasicSPM(BaseBasicModelTest, TestCase):
def setUp(self):
self.model = pybamm.lithium_ion.SPM()


class TestBasicDFN(BaseBasicModelTest, TestCase):
def setUp(self):
self.model = pybamm.lithium_ion.DFN()


class TestBasicDFNComposite(BaseBasicModelTest, TestCase):
def setUp(self):
self.model = pybamm.lithium_ion.BasicDFNComposite()


class TestBasicDFNHalfCell(BaseBasicModelTest, TestCase):
def setUp(self):
options = {"working electrode": "positive"}
self.model = pybamm.lithium_ion.BasicDFNHalfCell(options)


if __name__ == "__main__":
print("Add -v for more debug output")
import sys

if "-v" in sys.argv:
debug = True
unittest.main()
Loading
Loading