32 lines
1.7 KiB
Python
32 lines
1.7 KiB
Python
import numpy as np
|
|
import functions.rainflow as rainflow
|
|
|
|
def extract_stressors(t_secs, soc, T_celsius):
|
|
# Extract stressors
|
|
t_days = t_secs / (24*60*60)
|
|
delta_t_days = t_days[-1] - t_days[0]
|
|
delta_efc = np.sum(np.abs(np.ediff1d(soc, to_begin=0)))/2 # sum the total changes to SOC / 2
|
|
dod = np.max(soc) - np.min(soc)
|
|
abs_instantaneous_crate = np.abs(np.diff(soc)/np.diff(t_secs/(60*60))) # get instantaneous C-rates
|
|
abs_instantaneous_crate[abs_instantaneous_crate < 1e-2] = 0 # get rid of extremely small values (storage) before calculating mean
|
|
Crate = np.trapz(abs_instantaneous_crate, t_days[1:]) / delta_t_days
|
|
# Check storage condition, which will give nan Crate:
|
|
if np.isnan(Crate):
|
|
Crate = 0
|
|
T_kelvin = T_celsius + 273.15
|
|
# Estimate Ua (anode to reference potential) from SOC.
|
|
# Uses the equation from Safari and Delacourt, https://doi.org/10.1149/1.3567007.
|
|
# Anode stoichiometry is assumed to be the same for any chemistry/cell, and is calculated using the equation from Schimpe et al https://doi.org/10.1149/2.1181714jes
|
|
# While this will not be precise, it still helps get a guess as to where the plateaus of the anode-reference potential are.
|
|
def get_Xa(soc):
|
|
return 8.5*10**-3 + soc*(0.78 - 8.5*10**-3)
|
|
def get_Ua(Xa):
|
|
return (0.6379 + 0.5416*np.exp(-305.5309*Xa) +
|
|
0.044*np.tanh(-1*(Xa-0.1958)/0.1088) - 0.1978*np.tanh((Xa-1.0571)/0.0854) -
|
|
0.6875*np.tanh((Xa+0.0117)/0.0529) - 0.0175*np.tanh((Xa-0.5692)/0.0875))
|
|
Ua = get_Ua(get_Xa(soc))
|
|
|
|
cycles = rainflow.count_cycles(soc)
|
|
cycles = sum(i for _, i in cycles)
|
|
|
|
return delta_t_days, delta_efc, T_kelvin, soc, Ua, dod, Crate, cycles |