Tip

An interactive online version of this notebook is available, which can be accessed via # 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.

1. Constant current

### 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.

:

%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__+'/..')

# 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

:

# 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:

:

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

# plot
simulation.plot()


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

:

import pandas as pd    # needed to read the csv data file

model = pybamm.lithium_ion.DFN()

# import drive cycle from file

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
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.

:

# 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.

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

:

# 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

:

model = pybamm.lithium_ion.SPM()

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

:

# 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 = ["Frequency: {} Hz".format(omega)]

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