Source code for bmlite.materials._lfp
from numbers import Real
import numpy as np
[docs]
class LFPInterp:
def __init__(self, alpha_a: float, alpha_c: float, Li_max: float) -> None:
"""
LFP kinetic and transport properties, interpolated from data.
Parameters
----------
alpha_a : float
Anodic symmetry factor in Butler-Volmer expression [-].
alpha_c : float
Cathodic symmetry factor in Butler-Volmer expression [-].
Li_max : float
Maximum lithium concentration in solid phase [kmol/m3].
"""
import os
import pandas as pd
from scipy.interpolate import CubicSpline
self.alpha_a = alpha_a
self.alpha_c = alpha_c
self.Li_max = Li_max
# Diffusivity polynomial coeffs, for Ds = 10**P(x)
self._Ds_coeffs = np.array([
349.29800720, -925.34470810, 875.56218099, -268.24357721,
-102.31082863, 100.13715321, -27.74353094, -17.700056810,
])
# OCV and hysteresis, from csv data file
csvfile = os.path.dirname(__file__) + '/data/lfp_ocv.csv'
df = pd.read_csv(csvfile).sort_values(by='x')
self._Eeq_interp = CubicSpline(df['x'], df['V_avg'])
self._Mhyst_interp = CubicSpline(df['x'], df['M_hyst'])
[docs]
def get_Ds(self, x: float | np.ndarray, T: float,
fluxdir: float | np.ndarray) -> float | np.ndarray:
"""
Calculate the lithium diffusivity in the solid phase given the local
intercalation fraction `x` and temperature `T`.
Parameters
----------
x : float | 1D array
Lithium intercalation fraction [-].
T : float
Battery temperature [K].
fluxdir : float | 1D array
Lithiation direction: +1 for lithiation, -1 for delithiation, 0 for
rest. Used for direction-dependent parameters. Ensure the zero case
is handled explicitly or via a default (lithiating or delithiating).
Returns
-------
Ds : float | 1D array
Lithium diffusivity in the solid phase [m2/s].
"""
Ds = 4.014e-17*np.ones_like(x) # 10**np.polyval(self._Ds_coeffs, x)
return Ds.item() if np.isscalar(x) else Ds
[docs]
def get_i0(self, x: float | np.ndarray, C_Li: float | np.ndarray,
T: float, fluxdir: float | np.ndarray) -> float | np.ndarray:
"""
Calculate the exchange current density given the intercalation
fraction `x` at the particle surface, the local lithium ion
concentration `C_Li`, and temperature `T`. The input types for
`x` and `C_Li` should both be the same (i.e., both float or both
1D arrays).
Parameters
----------
x : float | 1D array
Lithium intercalation fraction at `r = R_s` [-].
C_Li : float | 1D array
Lithium ion concentration in the local electrolyte [kmol/m3].
T : float
Battery temperature [K].
fluxdir : float | 1D array
Lithiation direction: +1 for lithiation, -1 for delithiation, 0 for
rest. Used for direction-dependent parameters. Ensure the zero case
is handled explicitly or via a default (lithiating or delithiating).
Returns
-------
i0 : float | 1D array
Exchange current density [A/m2].
"""
from .. import Constants
c = Constants()
# Avoid floating point errors
if isinstance(x, Real):
if (x < 0 and self.alpha_c < 1) or (x > 1 and self.alpha_a < 1):
raise ValueError('x is out of [0, 1] during i0 calculation')
elif isinstance(x, np.ndarray):
if ((any(x.flatten() < 0) and self.alpha_c < 1)
or (any(x.flatten() > 1) and self.alpha_a < 1)):
raise ValueError('x is out of [0, 1] during i0 calculation')
i0 = 0.27 * np.exp(-30e6 / c.R * (1 / T - 1 / 303.15)) \
* C_Li**self.alpha_a * (self.Li_max * x)**self.alpha_c \
* (self.Li_max - self.Li_max * x)**self.alpha_a
return i0
[docs]
def get_Eeq(self, x: float | np.ndarray) -> float | np.ndarray:
"""
Calculate the equilibrium potential given the surface intercalation
fraction `x` at the particle surface.
Parameters
----------
x : float
Lithium intercalation fraction at `r = R_s` [-].
Returns
-------
Eeq : float
Equilibrium potential [V].
"""
return self._Eeq_interp(x)
[docs]
def get_Mhyst(self, x: float | np.ndarray) -> float | np.ndarray:
"""
Calculate the hysteresis magnitude given the surface intercalation
fraction `x` at the particle surface.
Parameters
----------
x : float | 1D array
Lithium intercalation fraction at `r = R_s` [-].
Returns
-------
M_hyst : float | 1D array
Hysteresis magnitude [V].
"""
return self._Mhyst_interp(x)