Skip to content

Commit

Permalink
#3844 initial improvements notebook 1
Browse files Browse the repository at this point in the history
  • Loading branch information
brosaplanella committed May 20, 2024
1 parent c74b5e5 commit 2c144fe
Showing 1 changed file with 109 additions and 7 deletions.
116 changes: 109 additions & 7 deletions docs/source/examples/notebooks/creating_models/1-an-ode-model.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@
"source": [
"# Creating a simple ODE model\n",
"\n",
"In this series of notebooks, we will run through the steps involved in creating a new model within pybamm. Before using pybamm we recommend following the [Getting Started](../getting_started/tutorial-1-how-to-run-a-model.ipynb) guides.\n",
"In the [Getting Started](../getting_started/tutorial-1-how-to-run-a-model.ipynb) series, we learnt how to use in-built PyBaMM models. In this series, our focus will be on how to build PyBaMM models from scratch, from the very simple reservoir model all the way up to the Doyle-Fuller-Newman model. We strongly advise to familiarise yourself with the Getting Started notebooks, if you have not done so, before following this series.\n",
"\n",
"In this notebook we create and solve the following simple ODE model:\n",
"We will start creating and solving the reservoir model. This model sits at the interface between equivalent circuit models and physics-based models (can be seen as an instance of either) and it is a very good starting point as it is composed only of ordinary differential equations (ODEs). The model is described by the following equations:\n",
"\n",
"$$\n",
" \\frac{\\textrm{d}x}{\\textrm{d} t} = 4x - 2y, \\quad x(0) = 1,\n",
"$$\n",
"\n",
"\n",
"In this notebook we create and solve the following simple ODE model:\n",
"$$\n",
" \\frac{\\textrm{d}y}{\\textrm{d} t} = 3x - y, \\quad y(0) = 2.\n",
"\\begin{align*}\n",
"\\frac{dx_n}{dt} &= -\\frac{I(t)}{Q_n}, \\\\\n",
"\\frac{dx_p}{dt} &= \\frac{I(t)}{Q_p}, \\\\\n",
"V(t) &= U_p(x_p) - U_n(x_n) - I(t)R, \\\\\n",
"x_n(0) &= x_{n0}, \\\\\n",
"x_p(0) &= x_{p0}, \\\\\n",
"\\end{align*}\n",
"$$\n",
"where $x_n$ and $x_p$ are the dimensionless stochiometries of the negative and positive electrodes, $I(t)$ is the current, $Q_n$ and $Q_p$ are the capacities of the negative and positive electrodes, $U_p(x_p)$ and $U_n(x_n)$ are the open circuit potentials of the positive and negative electrodes, and $R$ is the internal resistance of the battery.\n",
"\n",
"We begin by importing the PyBaMM library into this notebook, along with NumPy and Matplotlib, which we use for plotting:\n"
]
Expand Down Expand Up @@ -47,7 +53,98 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setting up the model"
"## Setting up the model\n",
"\n",
"In this section we will set up our model. There will be multiple steps involved. First, we will define the variables and parameters of the model. Next, we will define the model itself. Finally, we will discuss events (conditions that can be used to stop the solver), which are optional but very useful in battery modelling."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Variables\n",
"First we need to define the variables of the model, which are the quantities we want to solve for ([state variables](https://en.wikipedia.org/wiki/State-space_representation#State_variables)) and the quantities they depend on (independent variables). In this case, we only need to define two state variables: the stoichiometry of each electrode. The independent variable is time, but this variable is already built in PyBaMM so we do not need to define it. Voltage can be computed directly from the stoichiometries so it is not a state variable and we do not need to define it (we will say more on this when we define the model).\n",
"\n",
"In PyBaMM a state variable can be defined using the `pybamm.Variable` class, which takes as argument the name of the variable as a string. In this case, we define the two stoichiometries as variables:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x_n = pybamm.Variable(\"Negative electrode stochiometry\")\n",
"x_p = pybamm.Variable(\"Positive electrode stochiometry\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is worth clarifying the difference between the Python object name (e.g. `x_n`) and the PyBaMM variable name (e.g. Negative electrode stochiometry). The former is used to call the latter within the script/notebook. The variable name is used to identify the variable in the expression tree (more on expression trees [later](#expression-trees)), which is very useful when debugging the code, so it is advisable to make the name as informative as possible."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Parameters\n",
"Next we need to define the parameters of the model. [Parameters](https://en.wikipedia.org/wiki/Parameter) are known quantities that define the specific system we are modelling. For example, the electrode capacities are parameters of the reservoir model: they are known and they determine the specific battery we are modelling. In PyBaMM, parameters act as placeholders in the model and their specific values are passed at a later stage, when simulating the model.\n",
"\n",
"PyBaMM parameters are defined very similarly to variables, but now using the class `pybamm.Parameter`. For example, we can define:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Q_n = pybamm.Parameter(\"Negative electrode capacity [A.h]\")\n",
"Q_p = pybamm.Parameter(\"Positive electrode capacity [A.h]\")\n",
"R = pybamm.Parameter(\"Electrode resistance [Ohm]\")\n",
"x_n_0 = pybamm.Parameter(\"Initial negative electrode stochiometry\")\n",
"x_p_0 = pybamm.Parameter(\"Initial positive electrode stochiometry\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, it is worth highlighting the difference between the Python object name (e.g `Q_n`) and the PyBaMM parameter name (e.g. Negative electrode capacity [A.h]). The names of the parameters need to match those in the keys of the parameter values dictionary, which are passed when simulating the model as you might recall from the [Tutorial 4 - Setting parameter values](../getting_started/tutorial-4-setting-parameter-values.ipynb) notebook."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sometimes we need to define parameters that, even though they are known, they depend on variables of the model. For example, in the reservoir model we observe that the open-circuit potentials $U_n$ and $U_p$ depend on the stoichiometries. In this case, we need to use the `pybamm.FunctionParameter` class which in addition to the parameter name it takes as argument a dictionary with the inputs of the function parameter:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = pybamm.FunctionParameter(\"Current function [A]\", {\"Time [s]\": pybamm.t})\n",
"U_p = pybamm.FunctionParameter(\"Positive electrode OCV\", {\"x_p\": x_p})\n",
"U_n = pybamm.FunctionParameter(\"Negative electrode OCV\", {\"x_n\": x_n})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we mentioned earlier, the time variable is already built in PyBaMM as `pybamm.t`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The model"
]
},
{
Expand All @@ -58,6 +155,11 @@
"We first initialise the model using the `BaseModel` class. This sets up the required structure for our model. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 2,
Expand Down

0 comments on commit 2c144fe

Please sign in to comment.