Skip to content

Commit f5b1e98

Browse files
Merge pull request #1476 from pybamm-team/issue-1456-concentration
Issue 1456 concentration
2 parents a31e209 + dfe802d commit f5b1e98

File tree

16 files changed

+120
-72
lines changed

16 files changed

+120
-72
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
## Bug fixes
1818

1919
## Breaking changes
20+
21+
- Changed the variable in the full diffusion model from "Electrolyte concentration" to "Porosity times concentration" ([#1476](https://github.com/pybamm-team/PyBaMM/pull/1476))
2022
- Renamed `lithium-ion` folder to `lithium_ion` and `lead-acid` folder to `lead_acid` in parameters ([#1464](https://github.com/pybamm-team/PyBaMM/pull/1464))
2123

2224
# [v0.4.0](https://github.com/pybamm-team/PyBaMM/tree/v0.4.0) - 2021-03-28

examples/notebooks/initialize-model-with-solution.ipynb

+14-5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
"name": "stdout",
2424
"output_type": "stream",
2525
"text": [
26+
"\u001b[33mWARNING: You are using pip version 21.0.1; however, version 21.1 is available.\n",
27+
"You should consider upgrading via the '/Users/vsulzer/Documents/Energy_storage/PyBaMM/.tox/dev/bin/python -m pip install --upgrade pip' command.\u001b[0m\n",
2628
"Note: you may need to restart the kernel to use updated packages.\n"
2729
]
2830
}
@@ -159,7 +161,7 @@
159161
{
160162
"data": {
161163
"application/vnd.jupyter.widget-view+json": {
162-
"model_id": "0b5f9d809e244114b29f527062decbe9",
164+
"model_id": "7ad44c260ec446e0bd04a2f7dfbf8c65",
163165
"version_major": 2,
164166
"version_minor": 0
165167
},
@@ -173,7 +175,7 @@
173175
{
174176
"data": {
175177
"text/plain": [
176-
"<pybamm.plotting.quick_plot.QuickPlot at 0x7f3292dc9710>"
178+
"<pybamm.plotting.quick_plot.QuickPlot at 0x1447078e0>"
177179
]
178180
},
179181
"execution_count": 6,
@@ -240,7 +242,7 @@
240242
{
241243
"data": {
242244
"application/vnd.jupyter.widget-view+json": {
243-
"model_id": "d1e3967157584ff3802279544b0cc442",
245+
"model_id": "aaf63750ed354d1987703fd2fdde83af",
244246
"version_major": 2,
245247
"version_minor": 0
246248
},
@@ -254,7 +256,7 @@
254256
{
255257
"data": {
256258
"text/plain": [
257-
"<pybamm.plotting.quick_plot.QuickPlot at 0x7f32818d1990>"
259+
"<pybamm.plotting.quick_plot.QuickPlot at 0x10437c370>"
258260
]
259261
},
260262
"execution_count": 8,
@@ -299,6 +301,13 @@
299301
"source": [
300302
"pybamm.print_citations()"
301303
]
304+
},
305+
{
306+
"cell_type": "code",
307+
"execution_count": null,
308+
"metadata": {},
309+
"outputs": [],
310+
"source": []
302311
}
303312
],
304313
"metadata": {
@@ -317,7 +326,7 @@
317326
"name": "python",
318327
"nbconvert_exporter": "python",
319328
"pygments_lexer": "ipython3",
320-
"version": "3.7.4"
329+
"version": "3.8.8"
321330
},
322331
"toc": {
323332
"base_numbering": 1,

pybamm/expression_tree/binary_operators.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,10 @@ def simplified_matrix_multiplication(left, right):
11921192
if right.right.evaluates_to_constant_number():
11931193
r_left, r_right = right.orphans
11941194
new_left = left / r_right
1195-
return new_left @ r_left
1195+
new_mul = new_left @ r_left
1196+
# Keep the domain of the old left
1197+
new_mul.copy_domains(left)
1198+
return new_mul
11961199

11971200
# Simplify A @ (B @ c) to (A @ B) @ c if (A @ B) is constant
11981201
# This is a common construction that appears from discretisation of spatial

pybamm/models/base_model.py

-19
Original file line numberDiff line numberDiff line change
@@ -653,25 +653,6 @@ def check_ics_bcs(self):
653653
"""no initial condition given for variable '{}'""".format(var)
654654
)
655655

656-
# Boundary conditions
657-
for var, eqn in {**self.rhs, **self.algebraic}.items():
658-
if eqn.has_symbol_of_classes(
659-
(pybamm.Gradient, pybamm.Divergence)
660-
) and not eqn.has_symbol_of_classes(pybamm.Integral):
661-
# I have relaxed this check for now so that the lumped temperature
662-
# equation doesn't raise errors (this has and average in it)
663-
664-
# Variable must be in the boundary conditions
665-
if not any(
666-
var.id == x.id
667-
for symbol in self.boundary_conditions.keys()
668-
for x in symbol.pre_order()
669-
):
670-
raise pybamm.ModelError(
671-
"no boundary condition given for "
672-
"variable '{}' with equation '{}'.".format(var, eqn)
673-
)
674-
675656
def check_default_variables_dictionaries(self):
676657
"""Check that the right variables are provided."""
677658
missing_vars = []

pybamm/models/standard_variables.py

+27
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,33 @@
3131
bounds=(0, np.inf),
3232
)
3333

34+
# Electrolyte porosity times concentration
35+
eps_c_e_n = pybamm.Variable(
36+
"Negative electrode porosity times concentration",
37+
domain="negative electrode",
38+
auxiliary_domains={"secondary": "current collector"},
39+
bounds=(0, np.inf),
40+
)
41+
eps_c_e_s = pybamm.Variable(
42+
"Separator porosity times concentration",
43+
domain="separator",
44+
auxiliary_domains={"secondary": "current collector"},
45+
bounds=(0, np.inf),
46+
)
47+
eps_c_e_p = pybamm.Variable(
48+
"Positive electrode porosity times concentration",
49+
domain="positive electrode",
50+
auxiliary_domains={"secondary": "current collector"},
51+
bounds=(0, np.inf),
52+
)
53+
eps_c_e = pybamm.concatenation(eps_c_e_n, eps_c_e_s, eps_c_e_p)
54+
55+
eps_c_e_av = pybamm.Variable(
56+
"X-averaged porosity times concentration",
57+
domain="current collector",
58+
bounds=(0, np.inf),
59+
)
60+
3461
# Electrolyte potential
3562
phi_e_n = pybamm.Variable(
3663
"Negative electrolyte potential",

pybamm/models/submodels/electrolyte_diffusion/base_electrolyte_diffusion.py

+13
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ def _get_standard_concentration_variables(self, c_e_n, c_e_s, c_e_p):
7878

7979
return variables
8080

81+
def _get_standard_porosity_times_concentration_variables(
82+
self, eps_c_e_n, eps_c_e_s, eps_c_e_p
83+
):
84+
eps_c_e = pybamm.concatenation(eps_c_e_n, eps_c_e_s, eps_c_e_p)
85+
86+
variables = {
87+
"Porosity times concentration": eps_c_e,
88+
"Negative electrode porosity times concentration": eps_c_e_n,
89+
"Separator porosity times concentration": eps_c_e_s,
90+
"Positive electrode porosity times concentration": eps_c_e_p,
91+
}
92+
return variables
93+
8194
def _get_standard_flux_variables(self, N_e):
8295
"""
8396
A private function to obtain the standard variables which

pybamm/models/submodels/electrolyte_diffusion/constant_concentration.py

+13
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ def get_fundamental_variables(self):
3939
return variables
4040

4141
def get_coupled_variables(self, variables):
42+
eps_n = variables["Negative electrode porosity"]
43+
eps_s = variables["Separator porosity"]
44+
eps_p = variables["Positive electrode porosity"]
45+
c_e_n = variables["Negative electrolyte concentration"]
46+
c_e_s = variables["Separator electrolyte concentration"]
47+
c_e_p = variables["Positive electrolyte concentration"]
48+
49+
variables.update(
50+
self._get_standard_porosity_times_concentration_variables(
51+
eps_n * c_e_n, eps_s * c_e_s, eps_p * c_e_p
52+
)
53+
)
54+
4255
c_e = variables["Electrolyte concentration"]
4356
eps = variables["Porosity"]
4457

pybamm/models/submodels/electrolyte_diffusion/full_diffusion.py

+31-17
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,36 @@ def __init__(self, param):
2525
super().__init__(param)
2626

2727
def get_fundamental_variables(self):
28-
c_e_n = pybamm.standard_variables.c_e_n
29-
c_e_s = pybamm.standard_variables.c_e_s
30-
c_e_p = pybamm.standard_variables.c_e_p
28+
eps_c_e_n = pybamm.standard_variables.eps_c_e_n
29+
eps_c_e_s = pybamm.standard_variables.eps_c_e_s
30+
eps_c_e_p = pybamm.standard_variables.eps_c_e_p
3131

32-
return self._get_standard_concentration_variables(c_e_n, c_e_s, c_e_p)
32+
variables = self._get_standard_porosity_times_concentration_variables(
33+
eps_c_e_n, eps_c_e_s, eps_c_e_p
34+
)
35+
36+
return variables
3337

3438
def get_coupled_variables(self, variables):
3539

36-
tor = variables["Electrolyte tortuosity"]
40+
eps_n = variables["Negative electrode porosity"]
41+
eps_s = variables["Separator porosity"]
42+
eps_p = variables["Positive electrode porosity"]
43+
eps_c_e_n = variables["Negative electrode porosity times concentration"]
44+
eps_c_e_s = variables["Separator porosity times concentration"]
45+
eps_c_e_p = variables["Positive electrode porosity times concentration"]
46+
47+
c_e_n = eps_c_e_n / eps_n
48+
c_e_s = eps_c_e_s / eps_s
49+
c_e_p = eps_c_e_p / eps_p
50+
51+
variables.update(
52+
self._get_standard_concentration_variables(c_e_n, c_e_s, c_e_p)
53+
)
54+
3755
eps = variables["Porosity"]
3856
c_e = variables["Electrolyte concentration"]
57+
tor = variables["Electrolyte tortuosity"]
3958
i_e = variables["Electrolyte current density"]
4059
v_box = variables["Volume-averaged velocity"]
4160
T = variables["Cell temperature"]
@@ -57,8 +76,7 @@ def set_rhs(self, variables):
5776

5877
param = self.param
5978

60-
eps = variables["Porosity"]
61-
deps_dt = variables["Porosity change"]
79+
eps_c_e = variables["Porosity times concentration"]
6280
c_e = variables["Electrolyte concentration"]
6381
N_e = variables["Electrolyte flux"]
6482
div_Vbox = variables["Transverse volume-averaged acceleration"]
@@ -67,20 +85,16 @@ def set_rhs(self, variables):
6785
source_terms = sum_s_j / self.param.gamma_e
6886

6987
self.rhs = {
70-
c_e: (1 / eps)
71-
* (
72-
-pybamm.div(N_e) / param.C_e
73-
+ source_terms
74-
- c_e * deps_dt
75-
- c_e * div_Vbox
76-
)
88+
eps_c_e: -pybamm.div(N_e) / param.C_e + source_terms - c_e * div_Vbox
7789
}
7890

7991
def set_initial_conditions(self, variables):
8092

81-
c_e = variables["Electrolyte concentration"]
93+
eps_c_e = variables["Porosity times concentration"]
8294

83-
self.initial_conditions = {c_e: self.param.c_e_init}
95+
self.initial_conditions = {
96+
eps_c_e: self.param.epsilon_init * self.param.c_e_init
97+
}
8498

8599
def set_boundary_conditions(self, variables):
86100

@@ -90,5 +104,5 @@ def set_boundary_conditions(self, variables):
90104
c_e: {
91105
"left": (pybamm.Scalar(0), "Neumann"),
92106
"right": (pybamm.Scalar(0), "Neumann"),
93-
}
107+
},
94108
}

tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_compare_basic_models.py

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ def test_compare_dfns(self):
2525
sol = sim.solution
2626

2727
# Compare solution data
28-
np.testing.assert_array_almost_equal(basic_sol.y, sol.y, decimal=4)
2928
np.testing.assert_array_almost_equal(basic_sol.t, sol.t, decimal=4)
3029
# Compare variables
3130
for name in basic_dfn.variables:

tests/integration/test_solvers/test_idaklu.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_set_tol_by_variable(self):
3131
t_eval = np.linspace(0, 3600, 100)
3232
solver = pybamm.IDAKLUSolver()
3333

34-
variable_tols = {"Electrolyte concentration": 1e-3}
34+
variable_tols = {"Porosity times concentration": 1e-3}
3535
solver.set_atol_by_variable(variable_tols, model)
3636

3737
solver.solve(model, t_eval)

tests/unit/test_expression_tree/test_symbol.py

+3
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,9 @@ def test_symbol_visualise(self):
373373

374374
variables = {
375375
"Porosity": param.epsilon,
376+
"Negative electrode porosity": param.epsilon_n,
377+
"Separator porosity": param.epsilon_s,
378+
"Positive electrode porosity": param.epsilon_p,
376379
"Electrolyte tortuosity": param.epsilon ** 1.5,
377380
"Porosity change": zero_nsp,
378381
"Electrolyte current density": zero_nsp,

tests/unit/test_models/test_base_model.py

-25
Original file line numberDiff line numberDiff line change
@@ -420,24 +420,6 @@ def test_check_well_posedness_initial_boundary_conditions(self):
420420
with self.assertRaisesRegex(pybamm.ModelError, "initial condition"):
421421
model.check_well_posedness()
422422

423-
# Model with bad boundary conditions - Dirichlet (expect assertion error)
424-
d = pybamm.Variable("d", domain=whole_cell)
425-
model.initial_conditions = {c: 3}
426-
model.boundary_conditions = {
427-
d: {"left": (0, "Dirichlet"), "right": (0, "Dirichlet")}
428-
}
429-
with self.assertRaisesRegex(pybamm.ModelError, "boundary condition"):
430-
model.check_well_posedness()
431-
432-
# Model with bad boundary conditions - Neumann (expect assertion error)
433-
d = pybamm.Variable("d", domain=whole_cell)
434-
model.initial_conditions = {c: 3}
435-
model.boundary_conditions = {
436-
d: {"left": (0, "Neumann"), "right": (0, "Neumann")}
437-
}
438-
with self.assertRaisesRegex(pybamm.ModelError, "boundary condition"):
439-
model.check_well_posedness()
440-
441423
# Algebraic well-posed model
442424
whole_cell = ["negative electrode", "separator", "positive electrode"]
443425
model = pybamm.BaseModel()
@@ -451,13 +433,6 @@ def test_check_well_posedness_initial_boundary_conditions(self):
451433
}
452434
model.check_well_posedness()
453435

454-
# Algebraic model with bad boundary conditions
455-
model.boundary_conditions = {
456-
d: {"left": (0, "Dirichlet"), "right": (0, "Dirichlet")}
457-
}
458-
with self.assertRaisesRegex(pybamm.ModelError, "boundary condition"):
459-
model.check_well_posedness()
460-
461436
def test_check_well_posedness_output_variables(self):
462437
model = pybamm.BaseModel()
463438
whole_cell = ["negative electrode", "separator", "positive electrode"]

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_external_variables(self):
1717
model = pybamm.lithium_ion.SPMe(model_options)
1818
self.assertEqual(
1919
model.external_variables[0].id,
20-
model.variables["Electrolyte concentration"].id,
20+
model.variables["Porosity times concentration"].id,
2121
)
2222

2323
# a variable

tests/unit/test_models/test_submodels/test_electrolyte_diffusion/test_constant_concentration.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ class TestConstantConcentration(unittest.TestCase):
1111
def test_public_functions(self):
1212
param = pybamm.LithiumIonParameters()
1313
a = pybamm.Scalar(0)
14-
variables = {"Porosity": a, "Electrolyte concentration": a}
14+
variables = {
15+
"Porosity": a,
16+
"Negative electrode porosity": a,
17+
"Separator porosity": a,
18+
"Positive electrode porosity": a,
19+
"Electrolyte concentration": a,
20+
}
1521
submodel = pybamm.electrolyte_diffusion.ConstantConcentration(param)
1622
std_tests = tests.StandardSubModelTests(submodel, variables)
1723
std_tests.test_all()

tests/unit/test_models/test_submodels/test_electrolyte_diffusion/test_full_diffusion.py

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ def test_public_functions(self):
1818
)
1919
variables = {
2020
"Porosity": a,
21+
"Negative electrode porosity": a,
22+
"Separator porosity": a,
23+
"Positive electrode porosity": a,
2124
"Electrolyte tortuosity": a,
2225
"Porosity change": a,
2326
"Volume-averaged velocity": a,

tests/unit/test_solvers/test_idaklu_solver.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def test_set_atol(self):
5757
disc.process_model(model)
5858
solver = pybamm.IDAKLUSolver(root_method="lm")
5959

60-
variable_tols = {"Electrolyte concentration": 1e-3}
60+
variable_tols = {"Porosity times concentration": 1e-3}
6161
solver.set_atol_by_variable(variable_tols, model)
6262

6363
def test_failures(self):

0 commit comments

Comments
 (0)