Skip to content

Commit eccdd2e

Browse files
Merge branch 'develop' into issue-2760-step
2 parents c79c5cb + 09944fd commit eccdd2e

File tree

8 files changed

+91
-20
lines changed

8 files changed

+91
-20
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ repos:
99
- id: black
1010

1111
- repo: https://github.com/charliermarsh/ruff-pre-commit
12-
rev: "v0.0.254"
12+
rev: "v0.0.255"
1313
hooks:
1414
- id: ruff
1515
args: [--ignore=E741, --exclude=__init__.py]

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
## Bug fixes
1111

12+
- Fixed electrolyte conservation in the case of concentration-dependent transference number ([#2758](https://github.com/pybamm-team/PyBaMM/pull/2758))
1213
- Fixed `plot_voltage_components` so that the sum of overpotentials is now equal to the voltage ([#2740](https://github.com/pybamm-team/PyBaMM/pull/2740))
1314

1415
## Optimizations
@@ -30,6 +31,7 @@
3031
- Added an option for using a banded jacobian and sundials banded solvers for the IDAKLU solve ([#2677](https://github.com/pybamm-team/PyBaMM/pull/2677))
3132
- The "particle size" option can now be a tuple to allow different behaviour in each electrode ([#2672](https://github.com/pybamm-team/PyBaMM/pull/2672)).
3233
- Added temperature control to experiment class. ([#2518](https://github.com/pybamm-team/PyBaMM/pull/2518))
34+
- Added method to calculate maximum theoretical energy. ([#2777](https://github.com/pybamm-team/PyBaMM/pull/2777))
3335

3436
## Bug fixes
3537

examples/notebooks/Getting Started/Tutorial 7 - Model options.ipynb

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
{
6060
"data": {
6161
"text/plain": [
62-
"<pybamm.solvers.solution.Solution at 0x7f29f1333e50>"
62+
"<pybamm.solvers.solution.Solution at 0x139461520>"
6363
]
6464
},
6565
"execution_count": 3,
@@ -70,10 +70,7 @@
7070
"source": [
7171
"model = pybamm.lithium_ion.SPMe(options=options) # loading in options\n",
7272
"\n",
73-
"parameter_values = model.default_parameter_values\n",
74-
"parameter_values[\"Current function [A]\"] = 3\n",
75-
"\n",
76-
"sim = pybamm.Simulation(model, parameter_values=parameter_values)\n",
73+
"sim = pybamm.Simulation(model)\n",
7774
"sim.solve([0, 3600])"
7875
]
7976
},
@@ -92,16 +89,26 @@
9289
{
9390
"data": {
9491
"application/vnd.jupyter.widget-view+json": {
95-
"model_id": "c00d126a3fc543829596dd24f8b9d626",
92+
"model_id": "0fc5db759e804d3fb2793222ddbec5d4",
9693
"version_major": 2,
9794
"version_minor": 0
9895
},
9996
"text/plain": [
100-
"interactive(children=(FloatSlider(value=0.0, description='t', max=800.0000000000001, step=8.000000000000002), …"
97+
"interactive(children=(FloatSlider(value=0.0, description='t', max=1.0, step=0.01), Output()), _dom_classes=('w"
10198
]
10299
},
103100
"metadata": {},
104101
"output_type": "display_data"
102+
},
103+
{
104+
"data": {
105+
"text/plain": [
106+
"<pybamm.plotting.quick_plot.QuickPlot at 0x139461fd0>"
107+
]
108+
},
109+
"execution_count": 4,
110+
"metadata": {},
111+
"output_type": "execute_result"
105112
}
106113
],
107114
"source": [
@@ -139,7 +146,8 @@
139146
"[1] Joel A. E. Andersson, Joris Gillis, Greg Horn, James B. Rawlings, and Moritz Diehl. CasADi – A software framework for nonlinear optimization and optimal control. Mathematical Programming Computation, 11(1):1–36, 2019. doi:10.1007/s12532-018-0139-4.\n",
140147
"[2] Charles R. Harris, K. Jarrod Millman, Stéfan J. van der Walt, Ralf Gommers, Pauli Virtanen, David Cournapeau, Eric Wieser, Julian Taylor, Sebastian Berg, Nathaniel J. Smith, and others. Array programming with NumPy. Nature, 585(7825):357–362, 2020. doi:10.1038/s41586-020-2649-2.\n",
141148
"[3] Scott G. Marquis, Valentin Sulzer, Robert Timms, Colin P. Please, and S. Jon Chapman. An asymptotic derivation of a single particle model with electrolyte. Journal of The Electrochemical Society, 166(15):A3693–A3706, 2019. doi:10.1149/2.0341915jes.\n",
142-
"[4] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). ECSarXiv. February, 2020. doi:10.1149/osf.io/67ckj.\n",
149+
"[4] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). Journal of Open Research Software, 9(1):14, 2021. doi:10.5334/jors.309.\n",
150+
"[5] Robert Timms, Scott G Marquis, Valentin Sulzer, Colin P. Please, and S Jonathan Chapman. Asymptotic Reduction of a Lithium-ion Pouch Cell Model. SIAM Journal on Applied Mathematics, 81(3):765–788, 2021. doi:10.1137/20M1336898.\n",
143151
"\n"
144152
]
145153
}
@@ -165,7 +173,7 @@
165173
"name": "python",
166174
"nbconvert_exporter": "python",
167175
"pygments_lexer": "ipython3",
168-
"version": "3.11.1"
176+
"version": "3.9.16"
169177
},
170178
"vscode": {
171179
"interpreter": {

pybamm/models/full_battery_models/lithium_ion/electrode_soh.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,3 +557,47 @@ def get_min_max_stoichiometries(
557557
"""
558558
esoh_solver = ElectrodeSOHSolver(parameter_values, param, known_value)
559559
return esoh_solver.get_min_max_stoichiometries()
560+
561+
562+
def calculate_theoretical_energy(
563+
parameter_values, initial_soc=1.0, final_soc=0.0, points=100
564+
):
565+
"""
566+
Calculate maximum energy possible from a cell given OCV, initial soc, and final soc
567+
given voltage limits, open-circuit potentials, etc defined by parameter_values
568+
569+
Parameters
570+
----------
571+
parameter_values : :class:`pybamm.ParameterValues`
572+
The parameter values class that will be used for the simulation.
573+
initial_soc : float
574+
The soc at begining of discharge, default 1.0
575+
final_soc : float
576+
The soc at end of discharge, default 1.0
577+
points : int
578+
The number of points at which to calculate voltage.
579+
580+
Returns
581+
-------
582+
E
583+
The total energy of the cell in Wh
584+
"""
585+
# Get initial and final stoichiometric values.
586+
n_i, p_i = get_initial_stoichiometries(initial_soc, parameter_values)
587+
n_f, p_f = get_initial_stoichiometries(final_soc, parameter_values)
588+
n_vals = np.linspace(n_i, n_f, num=points)
589+
p_vals = np.linspace(p_i, p_f, num=points)
590+
# Calculate OCV at each stoichiometry
591+
param = pybamm.LithiumIonParameters()
592+
T = param.T_amb(0)
593+
Vs = np.empty(n_vals.shape)
594+
for i in range(n_vals.size):
595+
Vs[i] = parameter_values.evaluate(
596+
param.p.prim.U(p_vals[i], T)
597+
) - parameter_values.evaluate(param.n.prim.U(n_vals[i], T))
598+
# Calculate dQ
599+
Q_p = parameter_values.evaluate(param.p.prim.Q_init) * (p_f - p_i)
600+
dQ = Q_p / (points - 1)
601+
# Integrate and convert to W-h
602+
E = np.trapz(Vs, dx=dQ)
603+
return E

pybamm/models/submodels/electrolyte_diffusion/full_diffusion.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,12 @@ def get_coupled_variables(self, variables):
8989
def set_rhs(self, variables):
9090
eps_c_e = variables["Porosity times concentration [mol.m-3]"]
9191
c_e = variables["Electrolyte concentration [mol.m-3]"]
92-
T = variables["Cell temperature [K]"]
93-
N_e_diffusion = variables["Electrolyte diffusion flux [mol.m-2.s-1]"]
94-
N_e_convection = variables["Electrolyte convection flux [mol.m-2.s-1]"]
92+
N_e = variables["Electrolyte flux [mol.m-2.s-1]"]
9593
div_Vbox = variables["Transverse volume-averaged acceleration [m.s-2]"]
9694

9795
sum_s_a_j = variables["Sum of electrolyte reaction source terms [A.m-3]"]
98-
sum_a_j = variables["Sum of volumetric interfacial current densities [A.m-3]"]
9996
sum_s_a_j.print_name = "aj"
100-
source_terms = (sum_s_a_j - self.param.t_plus(c_e, T) * sum_a_j) / self.param.F
101-
102-
N_e = N_e_diffusion + N_e_convection
97+
source_terms = sum_s_a_j / self.param.F
10398

10499
self.rhs = {eps_c_e: -pybamm.div(N_e) + source_terms - c_e * div_Vbox}
105100

tests/integration/test_models/standard_output_comparison.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,13 @@ def test_all(self):
128128
self.compare("X-averaged positive electrode open-circuit potential [V]")
129129
self.compare("Voltage [V]")
130130
self.compare("X-averaged solid phase ohmic losses [V]")
131-
self.compare("Negative electrode reaction overpotential [V]")
131+
self.compare("Negative electrode reaction overpotential [V]", atol=1e-4)
132132
self.compare("Positive electrode reaction overpotential [V]")
133133
self.compare("Negative electrode potential [V]", atol=1e-5)
134134
self.compare("Positive electrode potential [V]")
135135
self.compare("Electrolyte potential [V]")
136136
# Currents
137-
self.compare("Exchange current density [A.m-2]")
137+
self.compare("Exchange current density [A.m-2]", atol=2e-3)
138138
self.compare("Negative electrode current density [A.m-2]", atol=1e-10)
139139
self.compare("Positive electrode current density [A.m-2]", atol=1e-10)
140140

tests/integration/test_models/standard_output_tests.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,10 @@ def test_conservation(self):
545545
diff = (
546546
self.c_e_tot(self.solution.t[1:]) - self.c_e_tot(self.solution.t[:-1])
547547
) / self.c_e_tot(self.solution.t[:-1])
548-
if self.model.options["surface form"] == "differential":
548+
if self.model.options["surface form"] == "differential" or (
549+
isinstance(self.model, pybamm.lithium_ion.DFN)
550+
and self.model.options["surface form"] == "algebraic"
551+
):
549552
np.testing.assert_allclose(0, diff, atol=1e-4, rtol=1e-6)
550553
else:
551554
np.testing.assert_allclose(0, diff, atol=1e-14, rtol=1e-14)

tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_electrode_soh.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,25 @@ def test_known_solution(self):
143143
self.assertAlmostEqual(sol["Uw(x_0)"].data[0], V_min, places=5)
144144

145145

146+
class TestCalculateTheoreticalEnergy(unittest.TestCase):
147+
def test_efficiency(self):
148+
model = pybamm.lithium_ion.DFN(options={"calculate discharge energy": "true"})
149+
parameter_values = pybamm.ParameterValues("Chen2020")
150+
sim = pybamm.Simulation(model, parameter_values=parameter_values)
151+
sol = sim.solve([0, 3600], initial_soc=1.0)
152+
discharge_energy = sol["Discharge energy [W.h]"].entries[-1]
153+
theoretical_energy = (
154+
pybamm.lithium_ion.electrode_soh.calculate_theoretical_energy(
155+
parameter_values
156+
)
157+
)
158+
# Real energy should be less than discharge energy,
159+
# and both should be greater than 0
160+
self.assertLess(discharge_energy, theoretical_energy)
161+
self.assertLess(0, discharge_energy)
162+
self.assertLess(0, theoretical_energy)
163+
164+
146165
class TestGetInitialSOC(unittest.TestCase):
147166
def test_initial_soc(self):
148167
param = pybamm.LithiumIonParameters()

0 commit comments

Comments
 (0)