Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions Data/BatteryThermalModel/BatteryThermal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
## We are modeling and training the thermal model for our accumulator which holds the tractive battery for FS-3

To understand the battery module:
There are 5 segments
Each segment has 6 packs of Enpaqa VTC5A Sony/Murata Li-Ion 2x10p
120 cells per segment, 600 cells total

## Equations

### 1) HEAT GENERATION

$Q = I^2 R$

Where:
Q: Total Heat Generated by the Tractive Battery
I: ACC_POWER_CURRENT from the parquet
R: 0.8Ω for one pack (2x10) ; 16Ω for the tractive battery

### 2) CONVECTION/COOLING FROM FANS

$\frac{dT}{dt} = hA_s(\frac{Q}{n}-T_\infty)$

Where:
$\frac{Q}{n}$: Individual packs temprature (2x10) , n is the number of cells
$h$: Heat Transfer Coefficient
$T_\infty$: Ambient Temprature
$A_s$: Surface Area

### 3) CONDUCTION [Cell to Cell]

$\frac{dT}{dt} = -k \cdot \frac{dT}{dt} \cdot A_c$

Where:
$\frac{dT}{dt}$:
$k$: Thermal Conductivity

### 4) CONDUCTION [Cell to Enclosure]

$\frac{dT}{dt} = -k \cdot \frac{dT}{dt} \cdot A_c$

Where:
$\frac{dT}{dt}$:
$k$: Thermal Conductivity

### 5) CONVECTION (Enclosure to Air)

$\frac{dT}{dt} = hA_s(T_s-T_\infty)$

Where:
$T_s$: Surface Temprature
$h$: Heat Transfer Coeeficient
$T_\infty$: Ambient Temprature
$A_s$: Surface Area

### 6) RADIATION (Enclosure to Air)

$\frac{dT}{dt} = \epsilon \cdot \sigma \cdot A_s(T_s^4 - T_{sur}^4)$

Where:
$\epsilon$: Emmisivity of Aluminum (Enclosure)
$\sigma$: 5.67 $\cdot$ $10^{-8}$
$A_s$: Surface Area
$T_s^4$: Surface Temprature
$T_{sur}^4$: Surrounding/Ambient Temprature
8 changes: 4 additions & 4 deletions Data/BatteryThermalModel/DataColumns.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""import matplotlib
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import polars as pl
dfa = pl.read_parquet("fs-data/FS-3/08172025/08172025_27autox2&45C_35C_~28Cambient_100fans.parquet")
dfb = pl.read_parquet("fs-data/FS-3/08172025/08172025_28autox3&4_45C_40C_~29Cambient_0fans.parquet")
dfc = pl.read_parquet("08172025_20_Endurance1P1.parquet")
print(dfc.columns)"""
"""print(dfb.columns)
print(dfa.columns)"""
print(dfc.columns)
print(dfb.columns)
print(dfa.columns)

import polars as pl
import matplotlib.pyplot as plt
Expand Down
16 changes: 16 additions & 0 deletions Data/BatteryThermalModel/DataFrames.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import polars as pl
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
import sys
sys.path.append(".")
sys.path.append("..")
sys.path.append("./Data")
from Data.FSLib.IntegralsAndDerivatives import *
dfa = pl.read_parquet("fs-data/FS-3/08172025/08172025_27autox2&45C_35C_~28Cambient_100fans.parquet")
dfb = pl.read_parquet("fs-data/FS-3/08172025/08172025_28autox3&4_45C_40C_~29Cambient_0fans.parquet")
print(dfa)
print(dfb)
print(dfa.columns)
print(dfb.columns)

9 changes: 4 additions & 5 deletions Data/BatteryThermalModel/FS4_FanTherm.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
import numpy as np
from scipy.optimize import curve_fit
import sys
from pathlib import Path

sys.path.append(str(Path(__file__).resolve().parent.parent))

from FSLib.IntegralsAndDerivatives import *
sys.path.append(".")
sys.path.append("..")
sys.path.append("./Data")
from Data.FSLib.IntegralsAndDerivatives import *
# from Data.integralsAndDerivatives import in_place_derive

def simpleTimeCol (dfa, dt=60/5035):
Expand Down
91 changes: 91 additions & 0 deletions Data/BatteryThermalModel/FanBatteryThermalModeling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#Fan&BatteryThermalModeling
# Understanding the Tractive Battrey Accumulator Model
## We have 5 segments, with each segment having six 2x10 packs/(cells according to the parquet). 120 cells per segment, 600 cells total.
# There are 3 holes in each segment which are cooling the batteries and the cells/packs are arranged 2x3 2 in the front and 3 wide, distance of the holes is 3 times the width/length
import polars as pl
import matplotlib.pyplot as plt
import numpy as np
import argparse
from scipy.optimize import curve_fit
import sys
sys.path.append(".")
sys.path.append("..")
sys.path.append("./Data")
from Data.FSLib.IntegralsAndDerivatives import *
from Data.FSLib.AnalysisFunctions import *
parser = argparse.ArgumentParser()
parser.add_argument(
"parquet_path",
type=str,
help="Path to the Parquet file"
)

args = parser.parse_args()
df = pl.read_parquet(args.parquet_path)

#df1= pl.read_parquet("fs-data/FS-3/08172025/08172025_27autox2&45C_35C_~28Cambient_100fans.parquet")
#df2= pl.read_parquet("fs-data/FS-3/08172025/08172025_28autox3&4_45C_40C_~29Cambient_0fans.parquet")
#df3= pl.read_parquet("fs-data/FS-3/08102025/08102025Endurance1_FirstHalf.parquet")
#time starts from 0

#df1 = df1.with_columns(simpleTimeCol(df1))[6788:]
#df2 = df2.with_columns(simpleTimeCol(df2))[69330+370+6788:]
#df3 = df3.with_columns(simpleTimeCol(df3))[69330+370+6788:]
ambientTemp = 28
df = df.with_columns(simpleTimeCol(df))[6788:]
df = df.with_columns((pl.col("Time") - df["Time"][ambientTemp]).alias("Time"))

#time starts from 0
#df1 = df1.with_columns((pl.col("Time") - df1["Time"][0]).alias("Time"))
#df2 = df2.with_columns((pl.col("Time") - df2["Time"][0]).alias("Time"))
#df3 = df3.with_columns((pl.col("Time") - df3["Time"][0]).alias("Time"))

#constants
mc = 1026 # J/K 1.14*900=1026
Area = 0.02620083033 # m^2 A=n*l*c => n=20, l=0.0695, c=0.01884951822
Ac=0.00691908680696
sigma=5.67*(10**-8) # Stefan-Boltzmann constant
#AsACC=
e= 0.1 # Emissivity of Aluminium [TRAININGPARAMETER]
h = 50# W/m^2K (convection coefficient) [TRAININGPARAMETER] [-184.90636861]
k=0.205 #(Thermal conductivity of the cell) [calculate physically]
k1=0.205

I = df["SME_TEMP_BusCurrent"] ## Accordingly change the 'df1' to any data frame choosen]
Temprature=(((I**2)*(16*(10**-3)))/mc)
IntegratedTemp=in_place_integrate(Temprature, dt=60/5035) #integrating the temperature change to get the total temperature generated by the battery over time
q1=h*Area*(IntegratedTemp-ambientTemp) #Cooling
q1=q1/mc
q2=-k*IntegratedTemp*Ac #Pack to Pack conduction; k: Thermal conductivity, Ac: Cross-section area of the Pack [TRAININGPARAMETER]
q2=q2/mc
q3=k1*surfaceTemp*Ac2 #Cell to enclosure conduction; k1: Thermal conductivity, Ac2: Cross-section area of the Accumulator wall [TRAININGPARAMETER]
#q4=h*AsACC*(ACCst-ambientTemp) #enclosure to air convection; AsACC: Surface area of the accumulator [TRAININGPARAMETER]
#q5=e*sigma*AsACC*(ACCst^4-ambientTemp^4) #Radiation; e: emissivity of aluminium, sigma: Stefan-Boltzmann constant [TRAININGPARAMETER]
IntegratedTemp=in_place_integrate(Temprature, dt=60/5035) #integrating the temperature change to get the total temperature generated by the battery over time
# dT/dt = (I^2*R - h*A*(T-T_ambient)) / (m*c))
temp_cols = [f"ACC_SEG{s}_TEMPS_CELL{c}" for s in range(5) for c in range(6)] #We are not using this anymore since out Ts is now measured by T/mc instead
#Q=(q2+q3)-(q1+q5+q4)

temps = np.array((30, 19))

for i in range(len(Temprature)):



df = df.with_columns(
df.select([pl.col(col).cast(pl.Float32) for col in temp_cols])
.mean_horizontal()
.alias("TempMean")
)

#plt.ylim(bottom=ambientTemp)
plt.plot(df["Time"], IntegratedTemp)
plt.xlabel("Time (s)")
plt.ylabel("Temperature (°C)")
plt.legend()
plt.show()

#python Data/BatteryThermalModel/FanBatteryThermalModeling.py fs-data/FS-3/08102025/08102025Endurance1_FirstHalf.parquet
#python Data/BatteryThermalModel/FanBatteryThermalModeling.py fs-data/FS-3/08172025/08172025_27autox2&45C_35C_~28Cambient_100fans.parquet
#python Data/BatteryThermalModel/FanBatteryThermalModeling.py fs-data/FS-3/08102025/08102025Endurance1_SecondHalf.parquet
#python Data/BatteryThermalModel/FanBatteryThermalModeling.py fs-data/FS-3/08102025/08102025RollingResistanceTestP1.parquet
8 changes: 5 additions & 3 deletions Data/BatteryThermalModel/Simultaneous_Plot_Viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def load_avg_temp_from_parquet(path: str) -> NDArray[np.float64]:

Returns
-------
NDArray[np.float64]
NDArray[np.float64]
Array of average temperatures across all cells.
"""
columns_list = [
Expand All @@ -44,7 +44,7 @@ def run_thermal_model_from_parquet(
path: str,
current_column: str = "SME_TEMP_BusCurrent",
t_span: Tuple[float, float] = (0, 10),
initial_temp: float = 30,
initial_temp: float = 33.5,
t_eval: NDArray[np.float64] | None = None,
):
"""
Expand Down Expand Up @@ -72,7 +72,7 @@ def run_thermal_model_from_parquet(
current_draw = df[current_column].to_numpy()

if t_eval is None:
t_eval = np.linspace(t_span[0], t_span[1], 100, dtype=np.float64)
t_eval = np.linspace(t_span[0], t_span[1], 1000, dtype=np.float64)

return thermal_ode_solve_ivp(current_draw, t_span, initial_temp, t_eval)

Expand Down Expand Up @@ -152,3 +152,5 @@ def main() -> None:
# run the main function: python Simultaneous_Plot_Viewer.py "/Users/gautham/Documents/fs-data/FS-3/08102025/08102025Endurance1_FirstHalf.parquet"
if __name__ == "__main__":
main()

#python Data/BatteryThermalModel/Simultaneous_Plot_Viewer.py fs-data/FS-3/08102025/08102025Endurance1_FirstHalf.parquet
Empty file.
7 changes: 6 additions & 1 deletion Data/BatteryThermalModel/fs4BatteryThermalModelingEx.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@


THERMAL_COEFFICIENT: float = 12.6316 / (49.9 * 1000.0)
ambient_temp: float = 32.0
"""
Effective thermal coefficient relating I² to temperature rate of change.

Expand Down Expand Up @@ -50,10 +51,14 @@ def thermal_ode(
Instantaneous temperature time derivative ``dT/dt`` in
degrees Celsius per second.
"""
mc = 967.6 # J/K
Area = 0.71 # m^2
idx = int(t * len(current_draw) / total_time)
idx = min(max(idx, 0), len(current_draw) - 1)
I_t = current_draw[idx]
return float(THERMAL_COEFFICIENT * (I_t ** 2))
heatingCoeff = 5.0
coolingCoeff = 20.0
return float(THERMAL_COEFFICIENT * (I_t ** 2) * heatingCoeff + (T-ambient_temp) * -184.90636861 * Area/mc * coolingCoeff)


def thermal_ode_solve_ivp(
Expand Down
2 changes: 2 additions & 0 deletions Data/BatteryThermalModel/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[project]
name = "BatteryThermalModel"
Empty file added Data/BatteryThermalModel/teste
Empty file.
1 change: 1 addition & 0 deletions fs-data
Submodule fs-data added at 4a7e93