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.

Saving PyBaMM models to file#

Models which are discretised (i.e. ready to solve/ previously solved, see this notebook for more information on the pybamm.Discretisation class) can be serialised and saved to a JSON file, ready to be read in again either in PyBaMM, or a different modelling library.

In the example below, we build a basic DFN model, and then save the model out to sim_model_example.json, which should have appear in the ‘models’ directory.

[10]:
%pip install pybamm -q    # install PyBaMM if it is not installed
import pybamm

# do the example
dfn_model = pybamm.lithium_ion.DFN()
dfn_sim = pybamm.Simulation(dfn_model)
# discretise and build the model
dfn_sim.build()

dfn_sim.save_model("sim_model_example")
Note: you may need to restart the kernel to use updated packages.

This model file can then be read in and solved by choosing a solver, and running as below.

[11]:
# Recreate the pybamm model from the JSON file
new_dfn_model = pybamm.load_model("sim_model_example.json")

sim_reloaded = pybamm.Simulation(new_dfn_model)
sim_reloaded.solve([0, 3600])
[11]:
<pybamm.solvers.solution.Solution at 0x2a4e10550>

It would be nice to plot the results of the two models, to confirm that they are producing the same result.

However, notice that running the code below generates an error stating that the model variables were not provided during the reading in of the model.

[12]:
dfn_models = [dfn_model, new_dfn_model]
sims = []
for model in dfn_models:
    plot_sim = pybamm.Simulation(model)
    plot_sim.solve([0, 3600])
    sims.append(plot_sim)

pybamm.dynamic_plot(sims, time_unit="seconds")
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/Users/pipliggins/Documents/repos/pybamm-local/docs/source/examples/notebooks/models/saving_models.ipynb Cell 7 line 8
      <a href='vscode-notebook-cell:/Users/pipliggins/Documents/repos/pybamm-local/docs/source/examples/notebooks/models/saving_models.ipynb#W6sZmlsZQ%3D%3D?line=4'>5</a>     plot_sim.solve([0, 3600])
      <a href='vscode-notebook-cell:/Users/pipliggins/Documents/repos/pybamm-local/docs/source/examples/notebooks/models/saving_models.ipynb#W6sZmlsZQ%3D%3D?line=5'>6</a>     sims.append(plot_sim)
----> <a href='vscode-notebook-cell:/Users/pipliggins/Documents/repos/pybamm-local/docs/source/examples/notebooks/models/saving_models.ipynb#W6sZmlsZQ%3D%3D?line=7'>8</a> pybamm.dynamic_plot(sims, time_unit="seconds")

File ~/Documents/repos/pybamm-local/pybamm/plotting/dynamic_plot.py:20, in dynamic_plot(*args, **kwargs)
      8 """
      9 Creates a :class:`pybamm.QuickPlot` object (with arguments 'args' and keyword
     10 arguments 'kwargs') and then calls :meth:`pybamm.QuickPlot.dynamic_plot`.
   (...)
     17     The 'QuickPlot' object that was created
     18 """
     19 kwargs_for_class = {k: v for k, v in kwargs.items() if k != "testing"}
---> 20 plot = pybamm.QuickPlot(*args, **kwargs_for_class)
     21 plot.dynamic_plot(kwargs.get("testing", False))
     22 return plot

File ~/Documents/repos/pybamm-local/pybamm/plotting/quick_plot.py:146, in QuickPlot.__init__(self, solutions, output_variables, labels, colors, linestyles, shading, figsize, n_rows, time_unit, spatial_unit, variable_limits)
    144 # check variables have been provided after any serialisation
    145 if any(len(m.variables) == 0 for m in models):
--> 146     raise AttributeError("No variables to plot")
    148 self.n_rows = n_rows or int(
    149     len(output_variables) // np.sqrt(len(output_variables))
    150 )
    151 self.n_cols = int(np.ceil(len(output_variables) / self.n_rows))

AttributeError: No variables to plot

To be able to plot the results from a serialised model, the mesh and model variables need to be saved alongside the model itself.

To do this, set the variables option to True when saving the model as in the example below; notice how the models will now plot nicely.

[13]:
# using the first simulation, save a new file which includes a list of the model variables
dfn_sim.save_model("sim_model_variables", variables=True)

# read the model back in
model_with_vars = pybamm.load_model("sim_model_variables.json")

# plot the pre- and post-serialisation models together to prove they behave the same
models = [dfn_model, model_with_vars]
sims = []
for model in models:
    sim = pybamm.Simulation(model)
    sim.solve([0, 3600])
    sims.append(sim)

pybamm.dynamic_plot(sims, time_unit="seconds")
[13]:
<pybamm.plotting.quick_plot.QuickPlot at 0x111963010>

Saving from Model#

Alternatively, the model can be saved directly from the Model class.

Note that at the moment, only models derived from the BaseBatteryModel class can be serialised; those built from scratch using pybamm.BaseModel() are currently unsupported.

First set up the model, as explained in detail for the SPM.

[14]:
# create the model
spm_model = pybamm.lithium_ion.SPM()

# set up and discretise ready to solve
geometry = spm_model.default_geometry
param = spm_model.default_parameter_values
param.process_model(spm_model)
param.process_geometry(geometry)
mesh = pybamm.Mesh(geometry, spm_model.default_submesh_types, spm_model.default_var_pts)
disc = pybamm.Discretisation(mesh, spm_model.default_spatial_methods)
disc.process_model(spm_model)
[14]:
<pybamm.models.full_battery_models.lithium_ion.spm.SPM at 0x29cf65c90>

Then save the model. Note that in this case the model variables and the mesh must be provided directly.

[15]:
# Serialise the spm_model, providing the varaibles and the mesh
spm_model.save_model("example_model", variables=spm_model.variables, mesh=mesh)

Now you can read the model back in, solve and plot.

[16]:
# read back in
new_spm_model = pybamm.load_model("example_model.json")

# select a solver and solve
new_spm_solver = new_spm_model.default_solver
new_spm_solution = new_spm_solver.solve(new_spm_model, [0, 3600])

# plot the solution
new_spm_solution.plot()
[16]:
<pybamm.plotting.quick_plot.QuickPlot at 0x29c8a3d10>

Making edits to a serialised model#

As mentioned at the begining of this notebook, only models which have already been discretised can be serialised and readh back in. This means that after serialisation, the model cannot be edited, as the non-discretised elements of the model such as the original rhs are not saved.

If you are likely to want to save a model and then edit it in the future, you may wish to use the Simulation.save() functionality to pickle your simulation, as described in tutorial 6.

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

[17]:
import os

os.remove("example_model.json")
os.remove("sim_model_example.json")
os.remove("sim_model_variables.json")

References#

The relevant papers for this notebook are:

[18]:
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] Marc Doyle, Thomas F. Fuller, and John Newman. Modeling of galvanostatic charge and discharge of the lithium/polymer/insertion cell. Journal of the Electrochemical society, 140(6):1526–1533, 1993. doi:10.1149/1.2221597.
[3] 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.
[4] 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.
[5] 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.

[ ]: