Source code for directupsampling.thermo

import numpy as np
import pandas as pd

from directupsampling.data import GPa_to_eV_per_Angstrom3, kB
from directupsampling.eos import check_pressure_unit
from directupsampling.fesurface import FreeEnergySurface


[docs] class Thermo: def __init__( self, fes: FreeEnergySurface, tmax=1000, pressure=0.0001, temperatures=None, pressure_unit: str = "GPa", ): """Assumes pressure to be in GPa.""" unit_conversion = check_pressure_unit(pressure_unit) self.fes = fes self.pressure = pressure * unit_conversion if temperatures is None: self.temperatures = np.linspace(1, tmax, tmax, dtype=int) else: self.temperatures = temperatures self._properties = None @property def properties(self): if self._properties is None: self.calculate_properties() return self._properties
[docs] def calculate_properties(self, veps=1e-4): """At the moment without defects""" props = pd.DataFrame(index=self.temperatures) props.index.name = "temperature" prev_volume = prev_temp = prev_gibbs = prev_entropy = None for i, temp in enumerate(self.temperatures): volume = self.fes.get_volume(self.pressure, temp) # , ini_guess=prev_volume) gibbs = self.fes.get_gibbs_energy(self.pressure, temp) if i == 0: first_volume = volume vcoef = 0 entropy = 0 else: vcoef = (volume - prev_volume) / (temp - prev_temp) / volume entropy = -(gibbs - prev_gibbs) / (temp - prev_temp) vrel = (volume - first_volume) / first_volume vm = volume - veps vp = volume + veps pm = self.fes.get_pressure(vm, temp) pp = self.fes.get_pressure(vp, temp) # differs from old fortran code: pp = -(Fp2-Fp1)/Veps enthalpy = gibbs + temp * entropy compress = -2 / (vp + vm) * (vp - vm) / ((pp - pm)) # /2) # no /2 due to pp diff above bm_isot = 1 / compress if i > 2: cp = temp * (entropy - prev_entropy) / (temp - prev_temp) else: cp = 0 tvbm_term = temp * volume * bm_isot * vcoef**2 cv = cp - tvbm_term if cv > 1e-5: grueneisen = volume * vcoef * bm_isot / cv bm_adia = bm_isot * cp / cv else: grueneisen = -1 bm_adia = bm_isot props.loc[temp, "volume_expansion"] = volume props.loc[temp, "volume_expansion_relative"] = vrel * 100 props.loc[temp, "volume_expansion_coefficient"] = vcoef * 1e5 props.loc[temp, "Gibbs_energy"] = gibbs props.loc[temp, "enthalpy"] = enthalpy props.loc[temp, "PV_term"] = self.pressure * volume props.loc[temp, "entropy"] = entropy / kB props.loc[temp, "heat_capacity_isobaric"] = cp / kB props.loc[temp, "heat_capacity_isochoric"] = cv / kB props.loc[temp, "TVbetaSqrBT"] = tvbm_term / kB props.loc[temp, "compressibility_isothermal"] = ( compress * GPa_to_eV_per_Angstrom3 ) props.loc[temp, "bulk_modulus_isothermal"] = ( bm_isot / GPa_to_eV_per_Angstrom3 ) props.loc[temp, "bulk_modulus_adiabatic"] = ( bm_adia / GPa_to_eV_per_Angstrom3 ) props.loc[temp, "Grueneisen_parameter"] = grueneisen prev_volume, prev_temp = volume, temp prev_gibbs = gibbs prev_entropy = entropy self._properties = props
# if defect: # thermo['Gibbs_energy'] += # # thermo['free_energy_atVeqT0K'] # # thermo['free_energy_vsV_atTmax_noET0K'] # thermo['free_energy_vsV_atTmax'] # if some_structure: # thermo['aLat_expansion'] # thermo['aLat_expansion_relative'] # thermo['aLat_expansion_coefficient'] # if hcp: # thermo['cLat_expansion'] # thermo['cLat_expansion_relative'] # thermo['cLat_expansion_coefficient'] # thermo['cBya'] # # # # if (Gs%nG>0) then # ! Gibbs energy of defects # call defectGibbsEnergy(Gs,Pm1,i,Gdm1) # call defectGibbsEnergy(Gs,P ,i,Gd0 ) # call defectGibbsEnergy(Gs,Pp1,i,Gdp1) # else # Gdm1=0; Gd0=0; Gdp1=0 # endif # ! total Gibbs energies # Gm1 = Gpm1 + Gdm1; G = Gp0 + Gd0; Gp1 = Gpp1 + Gdp1 # ! equilibrium volumes # Vm1 = (G-Gm1)/(P-Pm1) # Vp1 = (Gp1-G)/(Pp1-P) # ! main quantities at single T # VP(i) = (Vm1+Vp1)/2 # if (strType.NE."none") then # ! lattice constant expansion # if (strType.EQ."fcc") aP(i)=(4.*VP(i))**(1./3.); # if (strType.EQ."bcc") aP(i)=(2.*VP(i))**(1./3.); # ! for hcp also c and cBya expansion # if (strType.EQ."hcp") then # call cByaRatio(Fs,VP(i),cBya(i)) # ! hcp conversion from volume and cBya to a and c # nAtoms=2 # aP(i) = ((nAtoms*VP(i)/sin(pi/3.))/cBya(i))**(1./3.) # c(i) = cBya(i)*aP(i) # endif # ! relative lattice constant expansion # raP(i)=(aP(i)-aP(1))/aP(1) # if (strType.EQ."hcp") rc(i)=(c(i)-c(1))/c(1) # ! lattice constant coefficient # if (i>1) then # aCoef(i) = (aP(i)-aP(i-1))/(T(i)-T(i-1))/aP(i) # if (strType.EQ."hcp") cCoef(i) = (c(i)-c(i-1))/(T(i)-T(i-1))/c(i) # else # aCoef(i) = 0. # if (strType.EQ."hcp") cCoef(i) = 0. # endif # endif