1. Battery Cycling Simulations¶
This notebook demonstrates how to use the Thevenin model to simulate a variety of cycling experiments that are implemented in SOX. The Thevenin battery model uses PyBaMM in the backend, and adds abstractions for easier user interface.
Simply put, Thevenin model is a simple electrical representation of a battery cell with a voltage source and one or more RC branches, as outlined in the equations below. SOX provides a simple interface to create an ECM model using Thevenin class, and then use it to simulate a variety of cycling experiments using the solve method.
from sox.plant import Thevenin, default_thevenin_inputs
import sox.plant.protocol as protocol
from sox.utils import quick_plot
1.1. Thevenin Model¶
To create a Thevenin model, we need to provide a set of input parameters to it. To help with this, SOX implements a set of default input parameters that you can import as default_thevenin_inputs. These parameters are based on PyBaMM’s default parameters for ECM.
# changes default initial soc
default_thevenin_inputs.initial_soc = 0.5
# builds a battery equivalent circuit model
battery = Thevenin(default_thevenin_inputs)
1.2. Cycling Protocols¶
There are a handful of cycling protocols that are implemented in the protocol module. These protocols are used to simulate the cycling experiments. The protocols are:
cc_charge_cv_rest(CC charge, CV hold, then rest)cc_discharge_rest(CC discharge then rest)charge_discharge_cycling(combination of 1+2 with multiple cycles)single_pulse(CC charge or discharge pulse, then rest)single_pulse_train(a train of CC pulses with a single C rate, then rest)multi_pulse_train(a train of CC pulses with multiple C rates, then rest)dst_schedule(dynamic stress test schedule)
experiments = [
# 1. constant current then constant voltage charge, then rest
protocol.cc_charge_cv_rest(c_rate=2.0, cv_hold_c_rate_limit=1 / 6, rest_time_h=0.1),
# 2. constant current discharge, then rest
protocol.cc_discharge_rest(),
# 3. constant current charge and discharge cycling
protocol.charge_discharge_cycling(direction="charge", number_of_cycles=3),
# 4. constant current discharge pulse, then rest
protocol.single_pulse(direction="discharge", c_rate=2.0, pulse_time_sec=60, pulse_rest_time_sec=120),
# 5. one type of constant current discharge pulses back-to-back, with rest in between
protocol.single_pulse_train(direction="discharge", number_of_pulses=15),
# 6. two types of constant current discharge pulses back-to-back, with rest in between
protocol.multi_pulse_train(
direction=["discharge", "discharge"],
c_rate=[1.0, 0.2],
pulse_time_sec=[60, 600],
pulse_rest_time_sec=[600, 600],
number_of_pulses=9,
),
# 7. three types of constant current charge and discharge pulses back-to-back, with rest in between
protocol.multi_pulse_train(
direction=["discharge", "charge", "discharge"],
c_rate=[1.0, 1.0, 0.2],
pulse_time_sec=[60, 60, 600],
pulse_rest_time_sec=[600, 600, 600],
number_of_pulses=10,
),
# 8. DST (dynamic stress test) protocol
protocol.dst_schedule(
peak_power=3.8 * (6 * 10),
number_of_cycles=5,
sampling_time_s=1,
),
]
1.3. Perform Simulations¶
We here simulate battery response by passing experiments to the battery object as in battery.solve(experiment).
The result is a simulation Output object with the following properties: time, voltage, rc_voltage, ocv, current,
power, resistance, series_resistance, rc_resistance, rc_capacitance, soc, ambient_temperature,
cell_temperature, jig_temperature
# simulates the experiments
solutions = [battery.solve(e) for e in experiments]
1.4. Compare Results¶
Utility function quick_plot can be used to create interactive graphs of electrical and thermal battery parameters.
# generates voltage profile of all protocols
quick_plot(
time=[sol.time for sol in solutions],
data=[sol.voltage for sol in solutions],
titles=[f"Protocol {j+1}" for j in range(len(solutions))],
x_labels="Time (s)",
y_labels="Voltage (V)",
n_cols=3,
)
# generates voltage, current, temperature, and soc graphs for a single protocol
sol = solutions[2]
quick_plot(
time=[sol.time],
data=[[sol.ocv, sol.voltage], sol.current, [sol.cell_temperature, sol.jig_temperature], sol.soc],
legends=[["OCV", "voltage"], "current", ["cell", "jig"], "soc"],
x_labels="Time (s)",
y_labels=["Voltage (V)", "Current (A)", "Temperature (degC)", "SOC"],
titles=["Voltage", "Current", "Temperature", "SOC"],
)