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.

Changing the input current when solving PyBaMM models#

This notebook shows you how to change the input current when solving PyBaMM models. It also explains how to load in current data from a file, and how to add a user-defined current function. For more examples of different drive cycles see here.

Table of Contents#

  1. Constant current

  2. Loading in current data

  3. Adding your own current function

Constant current#

In this notebook we will use the SPM as the example model, and change the input current from the default option. If you are not familiar with running a model in PyBaMM, please see this notebook for more details.

In PyBaMM, the current function is set using the parameter “Current function [A]”. Below we load the SPM with the default parameters, and then change the the current function to be an input parameter, so that we can change it easily later.

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

os.chdir(pybamm.__path__[0] + "/..")

# create the model
model = pybamm.lithium_ion.DFN()

# set the default model parameters
param = model.default_parameter_values

# change the current function to be an input parameter
param["Current function [A]"] = "[input]"
Note: you may need to restart the kernel to use updated packages.

We can set up a simulation in the usual way, making sure we pass in our updated parameters. We choose to solve with a 1.6A current. In order to do this we must pass a dictionary of inputs whose keys are the parameter names and values are the values we want to use for that call to solve

[2]:
# set up simlation
simulation = pybamm.Simulation(model, parameter_values=param)

# solve the model at the given time points, passing the current as an input
t_eval = np.linspace(0, 600, 300)
simulation.solve(t_eval, inputs={"Current function [A]": 1.6})

# plot
simulation.plot()

PyBaMM can also simulate rest behaviour by setting the current function to zero:

[3]:
# solve the model at the given time points
simulation.solve(t_eval, inputs={"Current function [A]": 0})

# plot
simulation.plot()

Loading in current data#

To run drive cycles from data we can create an interpolant and pass it as the current function.

[4]:
import pandas as pd  # needed to read the csv data file

model = pybamm.lithium_ion.DFN()

# import drive cycle from file
drive_cycle = pd.read_csv(
    "pybamm/input/drive_cycles/US06.csv", comment="#", header=None
).to_numpy()

# load parameter values
param = model.default_parameter_values

# create interpolant - must be a function of *dimensional* time
current_interpolant = pybamm.Interpolant(drive_cycle[:, 0], drive_cycle[:, 1], pybamm.t)

# set drive cycle
param["Current function [A]"] = current_interpolant

# set up simulation - for drive cycles we recommend using the CasadiSolver in "fast" mode
solver = pybamm.CasadiSolver(mode="fast")
simulation = pybamm.Simulation(model, parameter_values=param, solver=solver)

Note that when simulating drive cycles there is no need to pass a list of times at which to return the solution, the results are automatically returned at the time points in the data. If you would like the solution returned at times different to those in the data then you can pass an array of times t_eval to solve in the usual way.

[5]:
# simulate US06 drive cycle (duration 600 seconds)
simulation.solve()

# plot
simulation.plot()

Note that some solvers try to evaluate the model equations at a very large value of t during the first step. This may raise a warning if the time requested by the solver is outside of the range of the data provided. However, this does not affect the solve since this large timestep is rejected by the solver, and a suitable shorter initial step is taken.

Adding your own current function#

A user defined current function can be passed to any model by specifying either a function or a set of data points for interpolation.

For example, you may want to simulate a sinusoidal current with amplitude A and frequency omega. In order to do so you must first define the method

[6]:
# create user-defined function


def my_fun(A, omega):
    def current(t):
        return A * pybamm.sin(2 * np.pi * omega * t)

    return current

Note that the function returns a function which takes the input time. Then the model may be loaded and the “Current function” parameter updated to my_fun called with a specific value of A and omega

[7]:
model = pybamm.lithium_ion.SPM()

# load default parameter values
param = model.default_parameter_values

# set user defined current function
A = model.param.I_typ
omega = 0.1
param["Current function [A]"] = my_fun(A, omega)

Note that when my_fun is evaluated with A and omega, this creates a new function current(t) which can then be used in the expression tree. The model may then be solved in the usual way

[8]:
# set up simulation
simulation = pybamm.Simulation(model, parameter_values=param)

# Example: simulate for 30 seconds
simulation_time = 30  # end time in seconds
npts = int(50 * simulation_time * omega)  # need enough timesteps to resolve output
t_eval = np.linspace(0, simulation_time, npts)
solution = simulation.solve(t_eval)
label = [f"Frequency: {omega} Hz"]

# plot current and voltage
output_variables = ["Current [A]", "Voltage [V]"]
simulation.plot(output_variables, labels=label)

References#

The relevant papers for this notebook are:

[9]:
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). ECSarXiv. February, 2020. doi:10.1149/osf.io/67ckj.