Tip

An interactive online version of this notebook is available, which can be accessed via Open this notebook in Google Colab


Alternatively, you may download this notebook and run it offline.

Attention

You are viewing this notebook on the latest version of the documentation, where these notebooks may not be compatible with the stable release of PyBaMM since they can contain features that are not yet released. We recommend viewing these notebooks from the stable version of the documentation. To install the latest version of PyBaMM that is compatible with the latest notebooks, build PyBaMM from source.

Tutorial 6 - Managing simulation outputs#

In the previous tutorials we have interacted with the outputs of the simulation via the default plotting functionality. However, usually we need to access the output data to manipulate it or transfer to another software, which is the topic of this notebook.

We start by building and solving our model as shown in previous notebooks:

[1]:
%pip install "pybamm[plot,cite]" -q    # install PyBaMM if it is not installed
import pybamm

model = pybamm.lithium_ion.SPMe()
sim = pybamm.Simulation(model)
sim.solve([0, 3600])

[notice] A new release of pip is available: 23.3.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.
[1]:
<pybamm.solvers.solution.Solution at 0x7f5e5b147fd0>

Accessing solution variables#

We can now access the solved variables directly to visualise or create our own plots. We first extract the solution object:

[2]:
solution = sim.solution

Note that the solution object is also returned when calling the solve method, so this can be streamlined by running

[3]:
solution = sim.solve([0, 3600])

when solving our simulation. Once we have the solution, we can define post-processed variable for the relevant variables:

[4]:
t = solution["Time [s]"]
V = solution["Voltage [V]"]

(for a list of all the available variables see Tutorial 3). These ProcessedVariable objects contain the datapoints for the corresponding variable, which can be accessed by calling the entries variable. For example, for voltage, we can call

[5]:
V.entries
[5]:
array([3.77048098, 3.75309871, 3.74569826, 3.74040906, 3.73582978,
       3.73155017, 3.72743983, 3.72345507, 3.71958265, 3.71581858,
       3.71216287, 3.70861698, 3.7051823 , 3.70185947, 3.69864846,
       3.69554865, 3.69255894, 3.6896778 , 3.68690322, 3.68423281,
       3.68166383, 3.67919326, 3.67681781, 3.67453394, 3.67233783,
       3.6702254 , 3.66819225, 3.66623353, 3.66434383, 3.66251699,
       3.66074577, 3.65902141, 3.65733311, 3.65566717, 3.65400602,
       3.65232696, 3.6506007 , 3.64879012, 3.64684952, 3.64472566,
       3.64236191, 3.63970731, 3.63673126, 3.63344172, 3.62989992,
       3.62622171, 3.6225587 , 3.61906361, 3.61585516, 3.61299814,
       3.61050386, 3.60834443, 3.606471  , 3.60482876, 3.60336628,
       3.60203993, 3.60081505, 3.59966528, 3.59857137, 3.59751973,
       3.59650118, 3.59550993, 3.59454272, 3.59359821, 3.59267644,
       3.59177838, 3.59090556, 3.59005965, 3.58924208, 3.58845355,
       3.58769359, 3.58695999, 3.58624826, 3.58555109, 3.58485777,
       3.58415379, 3.5834204 , 3.58263444, 3.58176818, 3.58078926,
       3.57966067, 3.57834049, 3.57678113, 3.57492782, 3.57271582,
       3.57006555, 3.566875  , 3.56300793, 3.5582764 , 3.55241508,
       3.54504405, 3.53561555, 3.52333845, 3.50707266, 3.48518447,
       3.45535426, 3.41433385, 3.35766635, 3.27941791, 3.17203869])

which correspond to the data at the times

[6]:
t.entries
[6]:
array([   0.        ,   36.36363636,   72.72727273,  109.09090909,
        145.45454545,  181.81818182,  218.18181818,  254.54545455,
        290.90909091,  327.27272727,  363.63636364,  400.        ,
        436.36363636,  472.72727273,  509.09090909,  545.45454545,
        581.81818182,  618.18181818,  654.54545455,  690.90909091,
        727.27272727,  763.63636364,  800.        ,  836.36363636,
        872.72727273,  909.09090909,  945.45454545,  981.81818182,
       1018.18181818, 1054.54545455, 1090.90909091, 1127.27272727,
       1163.63636364, 1200.        , 1236.36363636, 1272.72727273,
       1309.09090909, 1345.45454545, 1381.81818182, 1418.18181818,
       1454.54545455, 1490.90909091, 1527.27272727, 1563.63636364,
       1600.        , 1636.36363636, 1672.72727273, 1709.09090909,
       1745.45454545, 1781.81818182, 1818.18181818, 1854.54545455,
       1890.90909091, 1927.27272727, 1963.63636364, 2000.        ,
       2036.36363636, 2072.72727273, 2109.09090909, 2145.45454545,
       2181.81818182, 2218.18181818, 2254.54545455, 2290.90909091,
       2327.27272727, 2363.63636364, 2400.        , 2436.36363636,
       2472.72727273, 2509.09090909, 2545.45454545, 2581.81818182,
       2618.18181818, 2654.54545455, 2690.90909091, 2727.27272727,
       2763.63636364, 2800.        , 2836.36363636, 2872.72727273,
       2909.09090909, 2945.45454545, 2981.81818182, 3018.18181818,
       3054.54545455, 3090.90909091, 3127.27272727, 3163.63636364,
       3200.        , 3236.36363636, 3272.72727273, 3309.09090909,
       3345.45454545, 3381.81818182, 3418.18181818, 3454.54545455,
       3490.90909091, 3527.27272727, 3563.63636364, 3600.        ])

In addition, post-processed variables can be called at any time, which will return the interpolated value from the data above:

[7]:
V([200, 400, 780, 1236])  # times in seconds
[7]:
array([3.729495  , 3.70861698, 3.67812431, 3.65402263])

Saving the simulation and output data#

In some cases simulations might take a long time to run so it is advisable to save in your computer so it can be analysed later without re-running the simulation. You can save the whole simulation doing:

[8]:
sim.save("SPMe.pkl")

If you now check the root directory of your notebooks you will notice that a new file called "SPMe.pkl" has appeared. We can load the stored simulation doing

[9]:
sim2 = pybamm.load("SPMe.pkl")

which allows the same manipulation as the original simulation would allow

[10]:
sim2.plot()
[10]:
<pybamm.plotting.quick_plot.QuickPlot at 0x7f5e5ac5c910>

Alternatively, we can just save the solution of the simulation in a similar way

[11]:
sol = sim.solution
sol.save("SPMe_sol.pkl")

and load it in a similar way too

[12]:
sol2 = pybamm.load("SPMe_sol.pkl")
sol2.plot()
[12]:
<pybamm.plotting.quick_plot.QuickPlot at 0x7f5e58ebb5d0>

Another option is to just save the data for some variables

[13]:
sol.save_data("sol_data.pkl", ["Current [A]", "Voltage [V]"])

or save it in .csv or .mat format

[14]:
sol.save_data("sol_data.csv", ["Current [A]", "Voltage [V]"], to_format="csv")
# matlab needs names without spaces
sol.save_data(
    "sol_data.mat",
    ["Current [A]", "Voltage [V]"],
    to_format="matlab",
    short_names={"Current [A]": "I", "Voltage [V]": "V"},
)

Note that while exporting .pkl works for all variables, exporting to .csv and .mat only works for 0D variables (i.e. variables the do not depend on space, only on time).

In this notebook we have shown how to extract and store the outputs of PyBaMM’s simulations. Next, in Tutorial 7 we will show how to change the model options.

Before finishing we will remove the data files we saved so that we leave the directory as we found it

[15]:
import os

os.remove("SPMe.pkl")
os.remove("SPMe_sol.pkl")
os.remove("sol_data.pkl")
os.remove("sol_data.csv")
os.remove("sol_data.mat")

References#

The relevant papers for this notebook are:

[16]:
pybamm.print_citations()
[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.
[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.
[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.
[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.