Thermal coupling¶
Breathe Simulate uses a lumped thermal model by default. The cell self heats under load and exchanges heat with the ambient. Sometimes you already have a richer (for example 3D) thermal model of your own and want Breathe to run the electrochemistry under your cell temperature trajectory.
This is open loop coupling:
- Your external thermal model produces a cell temperature trajectory T(t).
- You feed T(t) into Breathe Simulate, which runs the electrochemistry under it and returns the heat generation Q(t) and voltage.
- You feed Q(t) back into your thermal model to advance it.
In this mode Breathe's own thermal model is overridden, so the ambient temperature and heat transfer coefficient are unused.
This notebook covers:
- Querying the design parameters of the Molicel P45B.
- Running an isothermal simulation where the temperature is held constant.
- Using a temperature timeseries object to couple an external thermal model.
from breathe_simulate import api_interface as api
from breathe_simulate import Cycler, TemperatureProfile
from breathe_simulate import enable_notebook_plotly
enable_notebook_plotly()
Query the design parameters¶
We can pull the design parameters for any base battery. Here we use the Ni65 (CATL-147) D/MP2, and also read its equilibrium KPIs to get the nominal capacity, which we use to set up the cycler in C rate.
base_params = api.get_design_parameters("Molicel P45B")
base_params
{'NLiRatio': 1.192712619876931,
'NPratio': 1.039106051327928,
'Vmax_V': 4.200003037059671,
'Vmin_V': 2.4999805201342147,
'aluminiumThickness_um': 22.2,
'anode': 'molicel_p45b_anode',
'anodeArealLoading_mAhcm2': 3.8996207810294305,
'anodeCathodeAreaRatio': 1.065290648694187,
'anodeMassLoading_mgcm2': 8.44896611475494,
'anodePorosity': 0.16663641853607114,
'anodeTabResistance_uOhmAh': 0.0,
'anodeThickness_um': 48.90000000000002,
'capacityVariationPercent': 0.0,
'cathode': 'molicel_p45b_cathode',
'cathodeArealLoading_mAhcm2': 3.7528611983790308,
'cathodeMassLoading_mgcm2': 14.188761420434503,
'cathodePorosity': 0.14216134985845785,
'cathodeTabResistance_uOhmAh': 0.0,
'cathodeThickness_um': 37.48333333333334,
'concentration_molL': 1.0,
'copperThickness_um': 11.2,
'electrodeArea_cm2': 1495.6199999999994,
'electrolyte': 'molicel_p45b_electrolyte',
'electrolyteBuffer_rel': 0.2,
'format': 'molicel_p45b',
'lamne': 0.0,
'lampe': 0.0,
'lli': 0.0,
'separatorThickness_um': 16.8}
results = api.get_eqm_kpis("Molicel P45B")
baseline_capacity = results.capacity
print(f"Nominal capacity: {baseline_capacity:.3f} Ah")
Nominal capacity: 4.500 Ah
An isothermal simulation¶
First, a baseline. We set up a 1C discharge and run it isothermally, so the cell temperature is held constant at the initial temperature. In this mode there is no self heating and no exchange with the ambient, so the ambient temperature and heat transfer coefficient have no effect.
cycler = Cycler(selected_unit="C", cell_capacity=baseline_capacity)
cycler_dict = cycler.cc_dch(
-1.0, 2.5
) # 1C discharge to 2.5 V (discharge current is negative)
print(cycler_dict)
{'cycle_type': 'CC_DCH', 'selected_unit': 'C', 'control_parameters': {'I_dch': -1.0, 'V_min': 2.5}}
isothermal_result = api.run_sim(
base_battery="Molicel P45B",
cycler=cycler_dict,
initialSoC=1.0,
initialTemperature_degC=25.0,
isothermal=True,
)
The cell temperature stays flat at 25 °C for the whole run:
isothermal_result.plot_dynamic_response("Cell temperature [°C]")