Dynamic Analysis Controls¶
In this notebook we demonstrate the optional dynamic-analysis controls available through breathe_simulate. The first example is an anode potential controlled charge example, while the other examples include a charge sequence followed by a 2C discharge so the charge and discharge behaviour can be reviewed in the same simulation.
from breathe_simulate import api_interface as api
from breathe_simulate import enable_notebook_plotly
enable_notebook_plotly()
We start from the baseline Molicel P45B cell and define one shared set of operating conditions so every example can be compared directly.
base_battery = "Molicel P45B"
eqm_results = api.get_eqm_kpis(base_battery)
capacity_ah = eqm_results.capacity
initial_soc = 0.2
initial_temperature_degC = 25.0
ambient_temperature_degC = 25.0
charge_2c_A = 2.0 * capacity_ah
charge_1p2c_A = 1.2 * capacity_ah
charge_0p6c_A = 0.6 * capacity_ah
discharge_2c_A = 2.0 * capacity_ah
plot_variables = [
"Charge current [A]",
"Voltage [V]",
"Cell temperature [°C]",
"SoC",
"Anode voltage [V]",
]
capacity_ah
np.float64(4.499999999999997)
Anode potential limited CC_CHG charge¶
The charge phase uses an anode-potential threshold, causing the current to automatically derate if the anode potential reaches the specified limit.
anode_limited_cycle = {
"cycle_type": "CC_CHG",
"selected_unit": "C",
"control_parameters": {
"I_chg": 2,
"V_max": 4.2,
"anode_potential_threshold_mV": 50.0,
},
}
anode_limited_output = api.run_sim(
base_battery=base_battery,
cycler=anode_limited_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
anode_limited_output.plot_dynamic_response(plot_variables)
Anode potential limited CCCV charge followed by rest and a 2C discharge¶
The charge phase uses an anode-potential threshold so the current derates if the anode potential reaches the limit.
anode_limited_cycle = {
"cycle_type": "CCCV",
"selected_unit": "C",
"control_parameters": {
"I_chg": 2.0,
"I_dch": -2.0,
"I_cut": 0.05,
"V_max": 4.2,
"V_min": 3.1,
"t_restC": 600.0,
"t_restD": 600.0,
"anode_potential_threshold_mV": 50.0,
},
}
anode_limited_output = api.run_sim(
base_battery=base_battery,
cycler=anode_limited_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
anode_limited_output.plot_dynamic_response(plot_variables)
Temperature limited CCCV charge followed by a rest and a 2C discharge¶
The charge phase uses a temperature threshold so the current derates if the cell temperature reaches the limit.
temperature_limited_cycle = {
"cycle_type": "CCCV",
"selected_unit": "C",
"control_parameters": {
"I_chg": 2.0,
"I_dch": -2.0,
"I_cut": 0.05,
"V_max": 4.2,
"V_min": 3.1,
"t_restC": 600.0,
"t_restD": 600.0,
"temperature_threshold_K": 303.15,
},
}
temperature_limited_output = api.run_sim(
base_battery=base_battery,
cycler=temperature_limited_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
temperature_limited_output.plot_dynamic_response(plot_variables)
Combined anode potential and temperature limited CCCV charge followed by a rest and a 2C discharge¶
The charge phase can enforce both anode-potential and temperature limits at the same time.
combined_threshold_cycle = {
"cycle_type": "CCCV",
"selected_unit": "C",
"control_parameters": {
"I_chg": 2.0,
"I_dch": -2.0,
"I_cut": 0.05,
"V_max": 4.2,
"V_min": 3.1,
"t_restC": 600.0,
"t_restD": 600.0,
"anode_potential_threshold_mV": 50.0,
"temperature_threshold_K": 303.15,
},
}
combined_threshold_output = api.run_sim(
base_battery=base_battery,
cycler=combined_threshold_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
combined_threshold_output.plot_dynamic_response(plot_variables)
Step charge with SoC setpoints followed by a 2C discharge with SoC setpoints. Uses CUSTOM cycler type¶
This custom profile changes current when SoC milestones are reached during charge, then uses a 2C discharge step that also ends on an SoC target.
soc_step_cycle = {
"cycle_type": "CUSTOM",
"selected_unit": "A",
"control_parameters": {
"experiment_text": [
{
"type": "soc_current_profile",
"steps": [
{
"type": "soc_current",
"mode": "charge",
"current_a": charge_2c_A,
"until_soc": 0.40,
},
{
"type": "soc_current",
"mode": "charge",
"current_a": charge_1p2c_A,
"until_soc": 0.60,
},
{
"type": "soc_current",
"mode": "charge",
"current_a": charge_0p6c_A,
"until_soc": 0.80,
},
{
"type": "soc_current",
"mode": "discharge",
"current_a": discharge_2c_A,
"until_soc": 0.20,
},
],
}
],
"period": "1s",
},
}
soc_step_output = api.run_sim(
base_battery=base_battery,
cycler=soc_step_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
soc_step_output.plot_dynamic_response(plot_variables)
Step charge with voltage setpoints followed by 2C discharge with voltage setpoints. Uses CUSTOM cycler type¶
This custom profile changes current when voltage thresholds are reached during charge, then uses a 2C discharge step that ends on a voltage cut-off.
voltage_step_cycle = {
"cycle_type": "CUSTOM",
"selected_unit": "A",
"control_parameters": {
"experiment_text": [
{
"type": "step_current_profile",
"steps": [
{
"type": "step_current",
"mode": "charge",
"current_a": charge_2c_A,
"until_voltage_v": 3.80,
},
{
"type": "step_current",
"mode": "charge",
"current_a": charge_1p2c_A,
"until_voltage_v": 4.00,
},
{
"type": "step_current",
"mode": "charge",
"current_a": charge_0p6c_A,
"until_voltage_v": 4.15,
},
{
"type": "step_current",
"mode": "discharge",
"current_a": discharge_2c_A,
"until_voltage_v": 3.10,
},
],
}
],
"period": "1s",
},
}
voltage_step_output = api.run_sim(
base_battery=base_battery,
cycler=voltage_step_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
voltage_step_output.plot_dynamic_response(plot_variables)
Step charge with SoC or voltage setpoints followed by a 2C discharge. Uses CUSTOM cycler type¶
Each step_current below includes both an SoC target and a voltage cut-off. The step ends on whichever threshold is reached first, and that same rule is also used for the final 2C discharge step.
dual_target_step_cycle = {
"cycle_type": "CUSTOM",
"selected_unit": "A",
"control_parameters": {
"experiment_text": [
{
"type": "step_current_profile",
"steps": [
{
"type": "step_current",
"mode": "charge",
"current_a": charge_2c_A,
"until_soc": 0.40,
"until_voltage_v": 3.70,
},
{
"type": "step_current",
"mode": "charge",
"current_a": charge_1p2c_A,
"until_soc": 0.60,
"until_voltage_v": 4.00,
},
{
"type": "step_current",
"mode": "charge",
"current_a": charge_0p6c_A,
"until_soc": 0.80,
"until_voltage_v": 4.10,
},
{
"type": "step_current",
"mode": "discharge",
"current_a": discharge_2c_A,
"until_soc": 0.20,
"until_voltage_v": 3.10,
},
],
}
],
"period": "1s",
},
}
dual_target_step_output = api.run_sim(
base_battery=base_battery,
cycler=dual_target_step_cycle,
designs=[],
initialSoC=initial_soc,
initialTemperature_degC=initial_temperature_degC,
ambientTemperature_degC=ambient_temperature_degC,
)
dual_target_step_output.plot_dynamic_response(plot_variables)