def get_dos(self, partial_dos=False, npts_mu=10000, T=None): """ Return a Dos object interpolating bands Args: partial_dos: if True, projections will be interpolated as well and partial doses will be return. Projections must be available in the loader. npts_mu: number of energy points of the Dos T: parameter used to smooth the Dos """ spin = self.data.spin if isinstance(self.data.spin, int) else 1 energies, densities, vvdos, cdos = BL.BTPDOS(self.eband, self.vvband, npts=npts_mu) if T is not None: densities = BL.smoothen_DOS(energies, densities, T) tdos = Dos(self.efermi / units.eV, energies / units.eV, {Spin(spin): densities}) if partial_dos: tdos = self.get_partial_doses(tdos=tdos, npts_mu=npts_mu, T=T) return tdos
def __init__(self, BztInterpolator, temp_r=np.arange(100, 1400, 100), doping=10. ** np.arange(16, 23), npts_mu=4000, CRTA=1e-14, margin=None): self.CRTA = CRTA self.temp_r = temp_r self.doping = doping self.dosweight = BztInterpolator.data.dosweight lattvec = BztInterpolator.data.get_lattvec() self.epsilon, self.dos, self.vvdos, self.cdos = BL.BTPDOS(BztInterpolator.eband, BztInterpolator.vvband, npts=npts_mu, cband=BztInterpolator.cband) if margin is None: margin = 9. * units.BOLTZMANN * temp_r.max() mur_indices = np.logical_and(self.epsilon > self.epsilon.min() + margin, self.epsilon < self.epsilon.max() - margin) self.mu_r = self.epsilon[mur_indices] N, L0, L1, L2, Lm11 = BL.fermiintegrals( self.epsilon, self.dos, self.vvdos, mur=self.mu_r, Tr=temp_r, dosweight=self.dosweight, cdos=self.cdos) self.efermi = BztInterpolator.data.fermi / units.eV self.mu_r_eV = self.mu_r / units.eV - self.efermi self.nelect = BztInterpolator.data.nelect self.volume = BztInterpolator.data.get_volume() # Compute the Onsager coefficients from those Fermi integrals self.Conductivity_mu, self.Seebeck_mu, self.Kappa_mu, Hall_mu = BL.calc_Onsager_coefficients(L0, L1, L2, self.mu_r, temp_r, self.volume, Lm11=Lm11) # Common properties rescaling self.Conductivity_mu *= CRTA # S / m self.Seebeck_mu *= 1e6 # microvolt / K self.Kappa_mu *= CRTA # W / (m K) self.Hall_carrier_conc_trace_mu = units.Coulomb * 1e-6 / (np.abs(Hall_mu[:, :, 0, 1, 2] + Hall_mu[:, :, 2, 0, 1] + Hall_mu[:, :, 1, 2, 0]) / 3) self.Carrier_conc_mu = (N + self.nelect) / (self.volume / (units.Meter / 100.) ** 3) # Derived properties cond_eff_mass = np.zeros((len(self.temp_r), len(self.mu_r), 3, 3)) for t in range(len(self.temp_r)): for i in range(len(self.mu_r)): try: cond_eff_mass[t, i] = np.linalg.inv(self.Conductivity_mu[t, i]) * self.Carrier_conc_mu[ t, i] * units.qe_SI ** 2 / units.me_SI * 1e6 except np.linalg.LinAlgError: pass self.Effective_mass_mu = cond_eff_mass * CRTA self.Power_Factor_mu = (self.Seebeck_mu @ self.Seebeck_mu) @ self.Conductivity_mu self.Power_Factor_mu *= 1e-9 # milliWatt / m / K**2
def get_dos(self, partial_dos=False, npts_mu=10000, T=None, progress=False): """ Return a Dos object interpolating bands Args: partial_dos: if True, projections will be interpolated as well and partial doses will be return. Projections must be available in the loader. npts_mu: number of energy points of the Dos T: parameter used to smooth the Dos progress: Default False, If True a progress bar is shown when partial dos are computed. """ dos_dict = {} enr = (self.eband.min(), self.eband.max()) if self.data.is_spin_polarized: h = sum(np.array_split(self.accepted, 2)[0]) eband_ud = np.array_split(self.eband, [h], axis=0) vvband_ud = np.array_split(self.vvband, [h], axis=0) spins = [Spin.up, Spin.down] else: eband_ud = [self.eband] vvband_ud = [self.vvband] spins = [Spin.up] for spin, eb, vvb in zip(spins, eband_ud, vvband_ud): energies, densities, vvdos, cdos = BL.BTPDOS(eb, vvb, npts=npts_mu, erange=enr) if T: densities = BL.smoothen_DOS(energies, densities, T) dos_dict.setdefault(spin, densities) tdos = Dos(self.efermi / units.eV, energies / units.eV, dos_dict) if partial_dos: tdos = self.get_partial_doses(tdos, eband_ud, spins, enr, npts_mu, T, progress) return tdos
def __init__( self, BztInterpolator, temp_r=np.arange(100, 1400, 100), doping=None, npts_mu=4000, CRTA=1e-14, margin=None, save_bztTranspProps=False, load_bztTranspProps=False, fname="bztTranspProps.json.gz", ): """ Args: BztInterpolator: a BztInterpolator previously generated temp_r: numpy array of temperatures at which to calculate transport properties doping: doping levels at which to calculate transport properties. If provided, transport properties w.r.t. these doping levels are also computed. See compute_properties_doping() method for details. npts_mu: number of energy points at which to calculate transport properties CRTA: constant value of the relaxation time save_bztTranspProps: Default False. If True all computed transport properties will be stored in fname file. load_bztTranspProps: Default False. If True all computed transport properties will be loaded from fname file. fname: File path where to save/load transport properties. Upon creation, it contains properties tensors w.r.t. the chemical potential of size (len(temp_r),npts_mu,3,3): Conductivity_mu (S/m), Seebeck_mu (microV/K), Kappa_mu (W/(m*K)), Power_Factor_mu (milliW/K m); cond_Effective_mass_mu (m_e) calculated as Ref. Also: Carrier_conc_mu: carrier concentration of size (len(temp_r),npts_mu) Hall_carrier_conc_trace_mu: trace of Hall carrier concentration of size (len(temp_r),npts_mu) mu_r_eV: array of energies in eV and with E_fermi at 0.0 where all the properties are calculated. Example: bztTransp = BztTransportProperties(bztInterp,temp_r = np.arange(100,1400,100)) """ self.dosweight = BztInterpolator.data.dosweight self.volume = BztInterpolator.data.get_volume() self.nelect = BztInterpolator.data.nelect self.efermi = BztInterpolator.data.fermi / units.eV if margin is None: margin = 9.0 * units.BOLTZMANN * temp_r.max() if load_bztTranspProps: self.load(fname) else: self.CRTA = CRTA self.temp_r = temp_r self.doping = doping self.epsilon, self.dos, self.vvdos, self.cdos = BL.BTPDOS( BztInterpolator.eband, BztInterpolator.vvband, npts=npts_mu, cband=BztInterpolator.cband, ) mur_indices = np.logical_and( self.epsilon > self.epsilon.min() + margin, self.epsilon < self.epsilon.max() - margin, ) self.mu_r = self.epsilon[mur_indices] self.mu_r_eV = self.mu_r / units.eV - self.efermi N, L0, L1, L2, Lm11 = BL.fermiintegrals( self.epsilon, self.dos, self.vvdos, mur=self.mu_r, Tr=temp_r, dosweight=self.dosweight, cdos=self.cdos, ) # Compute the Onsager coefficients from those Fermi integrals ( self.Conductivity_mu, self.Seebeck_mu, self.Kappa_mu, Hall_mu, ) = BL.calc_Onsager_coefficients(L0, L1, L2, self.mu_r, temp_r, self.volume, Lm11=Lm11) # Common properties rescaling self.Conductivity_mu *= CRTA # S / m self.Seebeck_mu *= 1e6 # microvolt / K self.Kappa_mu *= CRTA # W / (m K) self.Hall_carrier_conc_trace_mu = ( units.Coulomb * 1e-6 / (np.abs(Hall_mu[:, :, 0, 1, 2] + Hall_mu[:, :, 2, 0, 1] + Hall_mu[:, :, 1, 2, 0]) / 3)) self.Carrier_conc_mu = (N + self.nelect) / (self.volume / (units.Meter / 100.0)**3) # Derived properties cond_eff_mass = np.zeros((len(self.temp_r), len(self.mu_r), 3, 3)) for t in range(len(self.temp_r)): for i in range(len(self.mu_r)): try: cond_eff_mass[t, i] = ( np.linalg.inv(self.Conductivity_mu[t, i]) * self.Carrier_conc_mu[t, i] * units.qe_SI**2 / units.me_SI * 1e6) except np.linalg.LinAlgError: pass self.Effective_mass_mu = cond_eff_mass * CRTA self.Power_Factor_mu = ( self.Seebeck_mu @ self.Seebeck_mu) @ self.Conductivity_mu self.Power_Factor_mu *= 1e-9 # milliWatt / m / K**2 # self.props_as_dict() self.contain_props_doping = False if isinstance(doping, np.ndarray): self.compute_properties_doping(doping, temp_r) if save_bztTranspProps: self.save(fname)
def boltztrap(dirname, bt2file, title, T): print(("\n\nWorking in %s for %s at %i K" % (dirname, title, T))) # If a ready-made file with the interpolation results is available, use it # Otherwise, create the file. if not os.path.exists(bt2file): # Load the input data = BTP.DFTData(dirname) # Select the interesting bands nemin, nemax = data.bandana(emin=data.fermi - .2, emax=data.fermi + .2) # Set up a k point grid with roughly five times the density of the input equivalences = sphere.get_equivalences(data.atoms, len(data.kpoints) * 5) # Perform the interpolation coeffs = fite.fitde3D(data, equivalences) # Save the result serialization.save_calculation( bt2file, data, equivalences, coeffs, serialization.gen_bt2_metadata(data, data.mommat is not None)) # Load the interpolation results print("Load the interpolation results") data, equivalences, coeffs, metadata = serialization.load_calculation( bt2file) # Reconstruct the bands print("Reconstruct the bands") lattvec = data.get_lattvec() eband, vvband, cband = fite.getBTPbands(equivalences, coeffs, lattvec) # Obtain the Fermi integrals for different chemical potentials at # room temperature. TEMP = np.array([T]) epsilon, dos, vvdos, cdos = BL.BTPDOS(eband, vvband, npts=4000) margin = 9. * units.BOLTZMANN * TEMP.max() mur_indices = np.logical_and(epsilon > epsilon.min() + margin, epsilon < epsilon.max() - margin) mur = epsilon[mur_indices] N, L0, L1, L2, Lm11 = BL.fermiintegrals(epsilon, dos, vvdos, mur=mur, Tr=TEMP, dosweight=data.dosweight) # Compute the Onsager coefficients from those Fermi integrals print("Compute the Onsager coefficients") UCvol = data.get_volume() sigma, seebeck, kappa, Hall = BL.calc_Onsager_coefficients( L0, L1, L2, mur, TEMP, UCvol) fermi = BL.solve_for_mu(epsilon, dos, data.nelect, T, data.dosweight) savedata[title + '-%s' % T] = { "sigma": sigma, "seebeck": seebeck, "kappa": kappa, "Hall": Hall, "mu": (mur - fermi) / BL.eV, "temp": T, "n": N[0] + data.nelect }
ecut, efcut, deltae, tmax, deltat, lpfac = 1.0 * RYDBERG, 0.3 * RYDBERG, 0.0005 * RYDBERG, 1200.0, 10.0, 5 # Load the input data = dft.DFTData(dirname) # Select the interesting bands nemin, nemax = data.bandana(emin=data.fermi - ecut, emax=data.fermi + ecut) # Set up a k point grid with roughly five times the density of the input equivalences = sphere.get_equivalences(data.atoms, len(data.kpoints) * lpfac) # Perform the interpolation coeffs = fite.fitde3D(data, equivalences) lattvec = data.get_lattvec() eband, vvband, cband = fite.getBTPbands(equivalences, coeffs, lattvec) epsilon, dos, vvdos, cdos = BL.BTPDOS( eband, vvband, erange=[data.fermi - ecut, data.fermi + ecut], npts=round(2 * ecut / deltae), scattering_model='uniform_tau') # Define the temperatures and chemical potentials we are interested in #Tr = np.arange(deltat, tmax + deltat / 2, deltat) #mur_indices = np.logical_and(epsilon > data.fermi - efcut, epsilon < data.fermi + efcut) #mur = epsilon[mur_indices] Tr = np.arange(deltat, tmax + deltat / 2, deltat) mur = np.empty_like(Tr) _nelect = data.nelect for iT, T in enumerate(Tr): mur[iT] = BL.solve_for_mu(epsilon, dos, _nelect - doping_level,
def __init__(self, BztInterpolator, temp_r=np.arange(100, 1400, 100), doping=10.**np.arange(16, 23), npts_mu=4000, CRTA=1e-14, margin=None): """ Args: BztInterpolator: a BztInterpolator previously generated temp_r: numpy array of temperatures at which to calculate trasport properties doping: doping levels at which to calculate trasport properties npts_mu: number of energy points at which to calculate trasport properties CRTA: constant value of the relaxation time Upon creation, it contains properties tensors w.r.t. the chemical potential of size (len(temp_r),npts_mu,3,3): Conductivity_mu (S/m), Seebeck_mu (microV/K), Kappa_mu (W/(m*K)), Power_Factor_mu (milliW/K); cond_Effective_mass_mu (m_e) calculated as Ref. Also: Carrier_conc_mu: carrier concentration of size (len(temp_r),npts_mu) Hall_carrier_conc_trace_mu: trace of Hall carrier concentration of size (len(temp_r),npts_mu) mu_r_eV: array of energies in eV and with E_fermi at 0.0 where all the properties are calculated. Example: bztTransp = BztTransportProperties(bztInterp,temp_r = np.arange(100,1400,100)) """ self.CRTA = CRTA self.temp_r = temp_r self.doping = doping self.dosweight = BztInterpolator.data.dosweight self.epsilon, self.dos, self.vvdos, self.cdos = BL.BTPDOS( BztInterpolator.eband, BztInterpolator.vvband, npts=npts_mu, cband=BztInterpolator.cband) if margin is None: margin = 9. * units.BOLTZMANN * temp_r.max() mur_indices = np.logical_and( self.epsilon > self.epsilon.min() + margin, self.epsilon < self.epsilon.max() - margin) self.mu_r = self.epsilon[mur_indices] N, L0, L1, L2, Lm11 = BL.fermiintegrals(self.epsilon, self.dos, self.vvdos, mur=self.mu_r, Tr=temp_r, dosweight=self.dosweight, cdos=self.cdos) self.efermi = BztInterpolator.data.fermi / units.eV self.mu_r_eV = self.mu_r / units.eV - self.efermi self.nelect = BztInterpolator.data.nelect self.volume = BztInterpolator.data.get_volume() # Compute the Onsager coefficients from those Fermi integrals self.Conductivity_mu, self.Seebeck_mu, self.Kappa_mu, Hall_mu = BL.calc_Onsager_coefficients( L0, L1, L2, self.mu_r, temp_r, self.volume, Lm11=Lm11) # Common properties rescaling self.Conductivity_mu *= CRTA # S / m self.Seebeck_mu *= 1e6 # microvolt / K self.Kappa_mu *= CRTA # W / (m K) self.Hall_carrier_conc_trace_mu = units.Coulomb * 1e-6 / ( np.abs(Hall_mu[:, :, 0, 1, 2] + Hall_mu[:, :, 2, 0, 1] + Hall_mu[:, :, 1, 2, 0]) / 3) self.Carrier_conc_mu = (N + self.nelect) / (self.volume / (units.Meter / 100.)**3) # Derived properties cond_eff_mass = np.zeros((len(self.temp_r), len(self.mu_r), 3, 3)) for t in range(len(self.temp_r)): for i in range(len(self.mu_r)): try: cond_eff_mass[t, i] = np.linalg.inv( self.Conductivity_mu[t, i]) * self.Carrier_conc_mu[ t, i] * units.qe_SI**2 / units.me_SI * 1e6 except np.linalg.LinAlgError: pass self.Effective_mass_mu = cond_eff_mass * CRTA self.Power_Factor_mu = ( self.Seebeck_mu @ self.Seebeck_mu) @ self.Conductivity_mu self.Power_Factor_mu *= 1e-9 # milliWatt / m / K**2
# Save the result serialization.save_calculation( bt2file, data, equivalences, coeffs, serialization.gen_bt2_metadata(data, data.mommat is not None)) # Load the interpolation results data, equivalences, coeffs, metadata = serialization.load_calculation(bt2file) # Reconstruct the bands lattvec = data.get_lattvec() eband, vvband, cband = fite.getBTPbands(equivalences, coeffs, lattvec) # Obtain the Fermi integrals for different chemical potentials at # room temperature. TEMP = np.array([300.]) epsilon, dos, vvdos, cdos = BL.BTPDOS(eband, vvband, npts=4000) margin = 9. * units.BOLTZMANN * TEMP.max() mur_indices = np.logical_and(epsilon > epsilon.min() + margin, epsilon < epsilon.max() - margin) mur = epsilon[mur_indices] N, L0, L1, L2, Lm11 = BL.fermiintegrals(epsilon, dos, vvdos, mur=mur, Tr=TEMP, dosweight=data.dosweight) # Compute the Onsager coefficients from those Fermi integrals UCvol = data.get_volume() sigma, seebeck, kappa, Hall = BL.calc_Onsager_coefficients( L0, L1, L2, mur, TEMP, UCvol)