Skip to content

Commit

Permalink
linted libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
alasdairwilson committed Jul 15, 2024
1 parent 0a3bbc5 commit b1e8617
Show file tree
Hide file tree
Showing 14 changed files with 249 additions and 260 deletions.
54 changes: 27 additions & 27 deletions libraries/pybamm-developer/01_ode.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
---
name: ODE models in PyBaMM
dependsOn: [
libraries.pybamm
]
dependsOn: [libraries.pybamm]
tags: [pybamm]
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
---

# A simple ODE battery model
Expand Down Expand Up @@ -40,6 +38,7 @@ class. For example, if you wanted to define a state variable with name "x", you
would write

```python
import pybamm
x = pybamm.Variable("x")
```

Expand Down Expand Up @@ -150,7 +149,7 @@ model.initial_conditions[x_n] = x_n_0
model.rhs[x_p] = i / Q_p
model.initial_conditions[x_p] = x_p_0

model.variables["Voltage [V]"] = U_p - U_n - i * R
model.variables["Voltage [V]"] = U_p - U_n - i * R
model.variables["Negative electrode stochiometry"] = x_n
model.variables["Positive electrode stochiometry"] = x_p
```
Expand Down Expand Up @@ -306,27 +305,28 @@ following values:
- The OCV functions are the LGM50 OCP from the Chen2020 model, which are given by the functions:

```python
import numpy as np
def graphite_LGM50_ocp_Chen2020(sto):
u_eq = (
1.9793 * np.exp(-39.3631 * sto)
+ 0.2482
- 0.0909 * np.tanh(29.8538 * (sto - 0.1234))
- 0.04478 * np.tanh(14.9159 * (sto - 0.2769))
- 0.0205 * np.tanh(30.4444 * (sto - 0.6103))
)
u_eq = (
1.9793 * np.exp(-39.3631 * sto)
+ 0.2482
- 0.0909 * np.tanh(29.8538 * (sto - 0.1234))
- 0.04478 * np.tanh(14.9159 * (sto - 0.2769))
- 0.0205 * np.tanh(30.4444 * (sto - 0.6103))
)

return u_eq
return u_eq

def nmc_LGM50_ocp_Chen2020(sto):
u_eq = (
-0.8090 * sto
+ 4.4875
- 0.0428 * np.tanh(18.5138 * (sto - 0.5542))
- 17.7326 * np.tanh(15.7890 * (sto - 0.3117))
+ 17.5842 * np.tanh(15.9308 * (sto - 0.3120))
)
return u_eq
u_eq = (
-0.8090 * sto
+ 4.4875
- 0.0428 * np.tanh(18.5138 * (sto - 0.5542))
- 17.7326 * np.tanh(15.7890 * (sto - 0.3117))
+ 17.5842 * np.tanh(15.9308 * (sto - 0.3120))
)

return u_eq
```

:::solution
Expand Down
44 changes: 23 additions & 21 deletions libraries/pybamm-developer/02_pde.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
---
name: PDE models in PyBaMM
dependsOn: [
libraries.pybamm-developer.01_ode
]
dependsOn: [libraries.pybamm-developer.01_ode]
tags: [pybamm]
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
---

# Creating a simple PDE model
Expand Down Expand Up @@ -40,6 +38,7 @@ This argument is a string and we will later on define the geometry of
the domain.

```python
import pybamm
model = pybamm.BaseModel()

c = pybamm.Variable("Concentration", domain="negative particle")
Expand Down Expand Up @@ -130,7 +129,7 @@ mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
Here we have used the [`pybamm.Uniform1DSubMesh`](https://docs.pybamm.org/en/stable/source/api/meshes/one_dimensional_submeshes.html#pybamm.Uniform1DSubMesh) class to create a uniform mesh.
This class does not require any parameters, and so we can pass it directly to
the `submesh_types` dictionary. However, many other submesh types can take
additional parameters. Example of meshes that do require parameters include the
additional parameters. Example of meshes that do require parameters include the
[`pybamm.Exponential1DSubMesh`](https://docs.pybamm.org/en/stable/source/api/meshes/one_dimensional_submeshes.html#pybamm.Exponential1DSubMesh) which clusters points close to one or both
boundaries using an exponential rule. It takes a parameter which sets how
closely the points are clustered together, and also lets the users select the
Expand Down Expand Up @@ -158,7 +157,7 @@ into matrix-vector multiplications.
```python
spatial_methods = {"negative particle": pybamm.FiniteVolume()}
disc = pybamm.Discretisation(mesh, spatial_methods)
disc.process_model(model);
disc.process_model(model)
```

Now that the model has been discretised we are ready to solve.
Expand All @@ -168,6 +167,9 @@ Now that the model has been discretised we are ready to solve.
As before, we choose a solver and times at which we want the solution returned. We then solve, extract the variables we are interested in, and plot the result.

```python
import matplotlib.pyplot as plt
import numpy as np
import pybamm
# solve
solver = pybamm.ScipySolver()
t = np.linspace(0, 1, 100)
Expand Down Expand Up @@ -211,13 +213,13 @@ density, $F$ Faraday's constant, and $c_0$ the initial concentration.

We use the following parameters:

| Symbol | Units | Value |
|:-------|:-------------------|:-----------------------------------------------|
| $R$ | m | $10 \times 10^{-6}$ |
| $D$ | m${^2}$ s$^{-1}$ | $3.9 \times 10^{-14}$ |
| $j$ | A m$^{-2}$ | $1.4$ |
| $F$ | C mol$^{-1}$ | $96485$ |
| $c_0$ | mol m$^{-3}$ | $2.5 \times 10^{4}$ |
| Symbol | Units | Value |
| :----- | :--------------- | :-------------------- |
| $R$ | m | $10 \times 10^{-6}$ |
| $D$ | m${^2}$ s$^{-1}$ | $3.9 \times 10^{-14}$ |
| $j$ | A m$^{-2}$ | $1.4$ |
| $F$ | C mol$^{-1}$ | $96485$ |
| $c_0$ | mol m$^{-3}$ | $2.5 \times 10^{4}$ |

Create a model for this problem, discretise it and solve it. Use a uniform mesh
with 20 points, and discretise the domain using the Finite Volume Method. Solve
Expand Down Expand Up @@ -246,14 +248,14 @@ c = pybamm.Variable("Concentration [mol.m-3]", domain="negative particle")
# governing equations
N = -D * pybamm.grad(c) # flux
dcdt = -pybamm.div(N)
model.rhs = {c: dcdt}
model.rhs = {c: dcdt}

# boundary conditions
# boundary conditions
lbc = pybamm.Scalar(0)
rbc = -j / F / D
model.boundary_conditions = {c: {"left": (lbc, "Neumann"), "right": (rbc, "Neumann")}}

# initial conditions
# initial conditions
model.initial_conditions = {c: c0}

model.variables = {
Expand Down
25 changes: 12 additions & 13 deletions libraries/pybamm-developer/03_spm.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
---
name: Single Particle Model
dependsOn: [
libraries.pybamm-developer.02_pde
]
dependsOn: [libraries.pybamm-developer.02_pde]
tags: [pybamm]
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
---

# The Single Particle Model
Expand Down Expand Up @@ -62,6 +60,7 @@ other parameters we have seen so far, it is a function of time. We can define
this using `pybamm.FunctionParameter`:

```python
import pybamm
I = pybamm.FunctionParameter("Current function [A]", {"Time [s]": pybamm.t})
```

Expand Down Expand Up @@ -204,10 +203,10 @@ c_n_surf = pybamm.boundary_value(c_n, "right")
The OCPs $U_i$ are functions of the surface stoichiometries $x_i^s$, and we can
define them using `pybamm.FunctionParameter` in a similar way to the applied
current $I$. For example, to define the OCP of the positive electrode as a
function of the surface stoichiometry $x_p^s$:
function of the surface stoichiometry $x_p^s$:

```python
U_p = pybamm.FunctionParameter("Positive electrode OCP [V]", {"stoichiometry": x_p_s})
U_p = pybamm.FunctionParameter("Positive electrode OCP [V]", {"stoichiometry": "x_p_s"})
```

### PyBaMM's built-in functions
Expand Down Expand Up @@ -266,8 +265,8 @@ U_i = [pybamm.FunctionParameter(f"{e.capitalize()} electrode OCP [V]", {"stoichi
[U_n_plus_eta, U_p_plus_eta] = [U_i[i] + eta_i[i] for i in [0, 1]]
V = U_p_plus_eta - U_n_plus_eta
model.variables = {
"Voltage [V]": V,
"Negative particle surface concentration [mol.m-3]": c_i_s[0],
"Voltage [V]": V,
"Negative particle surface concentration [mol.m-3]": c_i_s[0],
}
```

Expand Down
44 changes: 22 additions & 22 deletions libraries/pybamm-developer/04_spm_class.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
---
name: Single Particle Model (now as a class)
dependsOn: [
libraries.pybamm-developer.03_spm
]
dependsOn: [libraries.pybamm-developer.03_spm]
tags: [pybamm]
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
---

# The Single Particle Model (now as a class)
Expand All @@ -34,7 +32,7 @@ Next, we see that the class has an `__init__` method. All classes have an `__ini

The next line

```python
```python nolint
super().__init__(name=name)
```

Expand Down Expand Up @@ -73,6 +71,7 @@ If you want to integrate your model into PyBaMM you should stick to the PyBaMM n
In this case we only need to define two variables: the concentrations in the positive and negative particle, respectively.

```python
import pybamm
electrodes = ["negative", "positive"]
c_i = [pybamm.Variable(f"{e.capitalize()} particle concentration [mol.m-3]", domain=f"{e} particle") for e in electrodes]
```
Expand All @@ -87,7 +86,7 @@ Next we need to define the parameters used in our model. Similarly to the variab

```python
# define parameters
I = pybamm.FunctionParameter("Current function [A]", {"Time [s]": pybamm.t})
I = pybamm.FunctionParameter("Current function [A]", {"Time [s]": pybamm.t})
D_i = [pybamm.Parameter(f"{e.capitalize()} electrode diffusivity [m2.s-1]") for e in electrodes]
R_i = [pybamm.Parameter(f"{e.capitalize()} particle radius [m]") for e in electrodes]
c0_i = [pybamm.Parameter(f"Initial concentration in {e} electrode [mol.m-3]") for e in electrodes]
Expand Down Expand Up @@ -117,7 +116,7 @@ Once we have defined the variables and the parameters we can write the governing

:::solution

```python
```python nolint
# governing equations
dcdt_i = [pybamm.div(D_i[i] * pybamm.grad(c_i[i])) for i in [0, 1]]
self.rhs = {c_i[i]: dcdt_i[i] for i in [0, 1]}
Expand All @@ -139,7 +138,7 @@ Finally, we can define the output variables. Here we want to define all the vari

:::solution

```python
```python nolint
# define intermediate variables and OCP function parameters
c_i_s = [pybamm.surf(c_i[i]) for i in [0, 1]]
x_i_s = [c_i_s[i] / c_i_max[i] for i in [0, 1]]
Expand All @@ -151,13 +150,13 @@ eta_i = [2 * R * T / F * pybamm.arcsinh(j_i[i] * F / (2 * i_0_i[i])) for i in [0
[U_n_plus_eta, U_p_plus_eta] = [pybamm.surf(U_i[i]) + eta_i[i] for i in [0, 1]]
V = U_p_plus_eta - U_n_plus_eta
self.variables = {
"Time [s]": pybamm.t,
"Voltage [V]": V,
"Current [A]": I,
"Negative particle concentration [mol.m-3]": c_i[0],
"Positive particle concentration [mol.m-3]": c_i[1],
"Negative particle surface concentration [mol.m-3]": c_i_s[0],
"Positive particle surface concentration [mol.m-3]": c_i_s[1],
"Time [s]": pybamm.t,
"Voltage [V]": V,
"Current [A]": I,
"Negative particle concentration [mol.m-3]": c_i[0],
"Positive particle concentration [mol.m-3]": c_i[1],
"Negative particle surface concentration [mol.m-3]": c_i_s[0],
"Positive particle surface concentration [mol.m-3]": c_i_s[1],
}
```

Expand Down Expand Up @@ -187,7 +186,7 @@ def default_submesh_types(self):
@property
def default_var_pts(self):
domains = ["negative particle", "positive particle"]
r_i = [pybamm.SpatialVariable("r", domain=[d], coord_sys="spherical polar") for d in domains]
r_i = [pybamm.SpatialVariable("r", domain=[d], coord_sys="spherical polar") for d in domains]
return {r: 20 for r in r_i}

@property
Expand Down Expand Up @@ -261,7 +260,8 @@ pybamm.expression_tree.exceptions.DomainError: children must have same or empty
This means that at some point in your expression tree an operator takes two nodes (i.e. children) that have incompatible domains. The error message will tell you which line in your model triggered the error, so a good way is to set a debug breakpoint there and analyse the domains of the various symbols in the expression by running

```python
symbol.domains
from pybamm import Symbol
Symbol.domains
```

Sometimes the issue is further down the expression tree, remember you can visualise the expression tree (see [ODE models in PyBaMM](./01_ode.md)). To access the list of children of a node, you can call the `children` command. You can then access the relevant element in the list and call the `children` command again to navigate down the tree.
Expand Down
23 changes: 12 additions & 11 deletions libraries/pybamm-developer/05_spm_acid.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
---
name: SPM with Acid Dissolution
dependsOn: [
libraries.pybamm-developer.04_spm_class
]
dependsOn: [libraries.pybamm-developer.04_spm_class]
tags: [pybamm]
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
attribution:
- citation: >
PyBaMM documentation by the PyBaMM Team
url: https://docs.pybamm.org
image: https://raw.githubusercontent.com/pybamm-team/pybamm.org/main/static/images/pybamm_logo.svg
license: BSD-3
---

# The Single Particle Model with Acid Dissolution

The next step will be to extend the Single Particle Model to include acid dissolution. We will use the model introduced by [Kindermann et al (2017)](https://iopscience.iop.org/article/10.1149/2.0321712jes), in particular equations [8]-[10]. Rewritten to match our notation, we have
The next step will be to extend the Single Particle Model to include acid dissolution. We will use the model introduced by [Kindermann et al (2017)](https://iopscience.iop.org/article/10.1149/2.0321712jes), in particular equations [8]-[10]. Rewritten to match our notation, we have

$$
\frac{\mathrm{d} \epsilon_p}{\mathrm{d} t} = - \frac{i_{0,\mathrm{diss}} \exp \left( \frac{F \eta_\mathrm{diss}}{R T} \right)}{c_p^{max} \delta_p F}
$$

with

$$
\eta_\mathrm{diss} = \phi_p - U_\mathrm{diss},
$$

where $i_{0,\mathrm{diss}}$ is the dissolution exchange current density and $U_\mathrm{diss}$ is the dissolution open-circuit potential. The positive electrode potential is given by $\phi_p = U_p + \eta_p$.

::::challenge{id="spm-acid" title="Write SPM with acid dissolution"}
Expand All @@ -31,7 +32,7 @@ The challenge for this lesson is to write a new class for SPM with acid dissolut
:::solution
To extend the SPM model to account for acid dissolution we need to add some additional lines in various parts of the code. Below we include these lines with a hint on which part of the code they should be.

```python
```python nolint
# variables
epsilon_s_p = pybamm.Variable("Positive electrode active material volume fraction")

Expand Down
Loading

0 comments on commit b1e8617

Please sign in to comment.