Source code for debyetools.electronic

import numpy as np
from scipy.optimize import leastsq

NAv  = 0.6022140857e24
kB   = 0.138064852e-22

[docs]class Electronic: """ Implementation of the electronic contribution to the free energy. :param float params: N(Ef)(V) function parameters. """ def __init__(self, *params: np.ndarray): self.pel = params self.r=1 for n,q in enumerate(params): setattr(self,'q'+str(n),q)
[docs] def NfV(self, V: float) -> float: """ N(Ef)(V) :param float V: Volume. :return: N(Ef)(V) :rtype: float """ return self.q0*V**0 + self.q1*V**1 + self.q2*V**2 + self.q3*V**3
[docs] def dNfVdV_T(self, V: float) -> float: """ derivative of N(Ef)(V) :param V: Volume. :type V: float :return: derivative of N(Ef)(V) :rtype: float """ return 3*V**2*self.q3+2*V*self.q2+self.q1
[docs] def d2NfVdV2_T(self, V: float) -> float: """ derivative of N(Ef)(V) :param V: Volume. :type V: float :return: derivative of N(Ef)(V) :rtype: float """ return 6*V*self.q3+2*self.q2
[docs] def d3NfVdV3_T(self, V: float) -> float: """ derivative of N(Ef)(V) :param V: Volume. :type V: float :return: derivative of N(Ef)(V) :rtype: float """ return 6*self.q3
[docs] def d4NfVdV4_T(self, V: float) -> float: """ derivative of N(Ef)(V) :param V: Volume. :type V: float :return: derivative of N(Ef)(V) :rtype: float """ return 0
[docs] def E(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Electronic energy :param T: Temperature. :type T: float|np.ndarray :param V: Volume. :type V: float|np.ndarray :return: E_el :rtype: float|np.ndarray """ return (1/6)*np.pi**2*NAv*self.r*kB**2*T**2*self.NfV(V)/(0.160218e-18)
[docs] def S(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Electronic entropy. :param T: Temperature. :type T: float|np.ndarray :param V: Volume. :type V: float|np.ndarray :return: S_el :rtype: float|np.ndarray """ return (2/6)*np.pi**2*NAv*self.r*kB**2*T*self.NfV(V)/(0.160218e-18)
[docs] def F(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - (1/6)*np.pi**2*NAv*self.r*kB**2*T**2*self.NfV(V)/(0.160218e-18)
[docs] def dFdV_T(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - (1/6)*np.pi**2*NAv*self.r*kB**2*T**2*self.dNfVdV_T(V)/(0.160218e-18)
[docs] def dFdT_V(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - 2*T*np.pi**2*NAv*self.r*kB**2*self.NfV(V)*(1/6)/(0.160218e-18)
[docs] def d2FdT2_V(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - 2*np.pi**2*NAv*self.r*kB**2*self.NfV(V)*(1/6)/(0.160218e-18)
[docs] def d2FdV2_T(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - (1/6)*np.pi**2*NAv*self.r*kB**2*T**2*self.d2NfVdV2_T(V)/(0.160218e-18)
[docs] def d3FdV3_T(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - (1/6)*np.pi**2*NAv*self.r*kB**2*T**2*self.d3NfVdV3_T(V)/(0.160218e-18)
[docs] def d4FdV4_T(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return - (1/6)*np.pi**2*NAv*self.r*kB**2*T**2*self.d4NfVdV4_T(V)/(0.160218e-18)
[docs] def d2FdVdT(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return -2*np.pi**2*NAv*self.r*kB**2*T*self.dNfVdV_T(V)*(1/6)/(0.160218e-18)
[docs] def d3FdV2dT(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return -2*np.pi**2*NAv*self.r*kB**2*T*self.d2NfVdV2_T(V)*(1/6)/(0.160218e-18)
[docs] def d3FdVdT2(self, T: float|np.ndarray, V: float|np.ndarray) -> float|np.ndarray: """ Derivative of the electronic contribution to the free energy. :param float|np.ndarray T: Temperature. :param float|np.ndarray V: Volume. :return: F_el :rtype: float|np.ndarray """ return -2*np.pi**2*NAv*self.r*kB**2*self.dNfVdV_T(V)*(1/6)/(0.160218e-18)
[docs]def fit_electronic(Vs: np.ndarray, p_el: np.ndarray, E: np.ndarray, N: np.ndarray, Ef: np.ndarray, ixss: int = 6, ixse: int = -1) -> np.ndarray: """ Fitting procedure for the N(Ef)(V) function. :param np.ndarray Vs: Volumes. :param np.ndarray p_el: Initial parameters. :param np.ndarray E: Matrix with energies at each level for each volume. :param np.ndarray N: Matrix with densities of state at each level for each volume. :param np.ndarray Ef: Fermi levels as function of temperature. :param int ixse: (optional) eDOS subset index. :param intixss: (optional) eDOS subset index. :retun np.ndarray: optimized parameters. """ V = np.array(Vs) ix_V0=4 EfV0 = float(Ef[ix_V0]) ixs=[i for i,x in enumerate(E[ix_V0]) if x>=Ef[ix_V0]] E1 = float(E[ix_V0][ixs[0]-1]) E2 = float(E[ix_V0][ixs[0]]) N1 = float(N[ix_V0][ixs[0]-1]) N2 = float(N[ix_V0][ixs[0]]) NfV0 = (EfV0 - E1)*(N2 - N1)/(E2 - E1) + N1 NfV = np.array([NfV0*np.sqrt(ef/EfV0) for ef in Ef][ixss:ixse]) P2 = leastsq(NfV2m, p_el, args=(V[ixss:ixse], NfV),maxfev=1000) P2 = P2[0] return P2
[docs]def NfV_poly_fun(V: float, _A: float, _B: float, _C: float, _D: float) -> float: """ Polynomial model for N(Ef)(V) for min. :param V: Volume/ :type V: float :param _A: param. :type _A: float :param _B: param. :type _B: float :param _C: param. :type _C: float :param _D: param. :type _D: float :return: polynimial for minimization. :rtype: float """ return _A + _B*V + _C*V**2 + _D*V**3
[docs]def NfV2m(P: np.ndarray, Vdata: np.ndarray, NfVdata: np.ndarray) -> np.ndarray: """ Error function for minimizaiton. :param P: Parameters. :type P: np.ndarray :param Vdata: Volume data. :type Vdata: np.ndarray :param NfVdata: N(Ef)(V) data. :type NfVdata: np.ndarray :return: err. :rtype: np.ndarray """ NfVcalc = [NfV_poly_fun(Vi, P[0], P[1], P[2], P[3]) for Vi in Vdata] return (NfVcalc-NfVdata)**2