Dynamic analysis II¶
In this example we simulate different SOC breakpoints for the baseline and virtual cell with 5% less NPratio, and compare the capacity and DCIR.
from breathe_design import api_interface as api
from breathe_design import Cycler
from breathe_design import enable_notebook_plotly
import plotly.express as px
enable_notebook_plotly()
As before, we first import the necessary modules and define the base battery, cycler, and designs.
base_params = api.get_design_parameters("Molicel P45B")
eqm_results = api.get_eqm_kpis("Molicel P45B")
designs = [{"designName": "Lower NP", "NPratio": base_params["NPratio"] * 0.95}]
baseline_capacity = eqm_results.capacity
cycler = Cycler(selected_unit="C", cell_capacity=baseline_capacity)
🔐 No active session. Please sign in to continue. 🚀 Open this URL in a browser and verify the code shown is VTSB-TBRC 🔗 https://breathe-platform.uk.auth0.com/activate?user_code=VTSB-TBRC ⏳ Waiting for user authorization... ✅ Authentication successful!
We can pass a list of SOC breakpoints to the initialSoC parameter of the run_sim function to simulate different SOCs.
# define some SOC breakpoints we want to simulate
soc_bps = [0.25, 0.5, 0.75]
# run a batch of simulations for different SOC breakpoints
output = api.run_sim(
base_battery="Molicel P45B",
cycler=cycler.cc_chg(1.0, 4.2),
designs=designs,
initialSoC=soc_bps,
initialTemperature_degC=21.0,
)
The dynamic output data is now returned as a list of dictionaries, where each dictionary contains the simulation results for a given SOC breakpoint.
output.plot_voltage_response()
Let's also take this a step further and run a DCIR test. Here we can define different arguments that can be tailored to your specific requirements.
cycler_dict = cycler.dcir(
I_dch=-1.0, t_dur=60.0, t_rest_before=3.0, t_rest_after=200.0, v_min=2.5, v_max=4.2
)
Lets run this simulation at 50% SOC with an initial temperature of 25°C.
output = api.run_sim(
base_battery="Molicel P45B",
cycler=cycler_dict,
designs=designs,
initialSoC=0.5,
initialTemperature_degC=25.0,
)
Lets take a look at the current profile, the discharge current for the baseline cell is lower since it has a lower nominal capacity compared to the virtual cell we have decided to call "Lower NP".
output.plot_dynamic_response("currModel")
output.plot_voltage_response()
output.dynamic_kpis("DCIR")
| Design | Resistance (Ω) | |
|---|---|---|
| 0 | Baseline | 0.021555 |
| 1 | Lower NP | 0.019601 |
Now lets look at the rate capacity for different discharging rates down to 2.6 V, stoarting from 100% SOC.
rate_capacity_results = []
for rate in [1.0, 2.0, 3.0]:
cycler_input = cycler.cc_dch(-1 * rate, 2.6)
output = api.run_sim(
base_battery="Molicel P45B",
cycler=cycler_input,
designs=designs,
initialSoC=1.0,
initialTemperature_degC=50.0,
)
dynamic_kpis = output.dynamic_kpis("RateCap")
rate_capacity_results.append(
{
"Rate": rate,
"Baseline": dynamic_kpis.query("Design == 'Baseline'")[
"Capacity (Ah)"
].values[0],
"Lower NP": dynamic_kpis.query("Design == 'Lower NP'")[
"Capacity (Ah)"
].values[0],
}
)
print(rate_capacity_results)
[{'Rate': 1.0, 'Baseline': np.float64(4.40072093194797), 'Lower NP': np.float64(4.567765025125162)}, {'Rate': 2.0, 'Baseline': np.float64(4.3456503336818475), 'Lower NP': np.float64(4.511104393796408)}, {'Rate': 3.0, 'Baseline': np.float64(4.28984186508177), 'Lower NP': np.float64(4.454216444458762)}]
Lets compare the rated capacity over C-Rate
# Create a line plot using Plotly Express
fig = px.line(
rate_capacity_results, x="Rate", y=["Baseline", "Lower NP"], title="Rate Capacity"
)
# Show the plot
fig.show()