Source code for tp.data.run

"""External code running tools."""

#Functions
#---------
#
#    boltztrap
#"""

import numpy as np
import shutil
import tp

[docs]def boltztrap(tmax=1001, tstep=50, tmin=None, doping=np.logspace(18, 21, 17), ke_mode='boltzmann', vasprun='vasprun.xml', kpoints=None, relaxation_time=1e-14, lpfac=10, run=True, analyse=True, output='boltztrap.hdf5', run_dir='.', clean=False, **kwargs): """Runs BoltzTraP from a VASP density of states (DoS). Wrapper for pymatgen.electronic_structure.boltztrap but runs faster than using the built in from_files method and outputs an hdf5 file. Note: BoltzTraP can be a fickle friend, so if you're getting errors, it may be worth reinstalling or trying on a different machine. Arguments --------- tmax : float, optional maximum temperature in K. Default: 1000. tstep : float, optional temperature step in K. Default: 50. tmin : float, optional minimum temperature in K. This does not reduce how many temperatures are run in BoltzTraP, only how many are saved to hdf5. Default: tstep. doping : array-like, optional doping concentrations in cm-1. Default: np.logspace(18, 21, 17). k_mode : str, optional method for calculating the electronic thermal conductivity. Options: boltzmann (default): standard boltztrap method. Madsen and Singh, Comput. Phys. Commun. 2006, 175, 67. wiedemann: Wiedemann-Franz law with constant L = 2.44E-8. Franz and Wiedemann, Ann. Phys. 1853, 165, 497. snyder: Wiedemann-Franz law, with L varying with Seebeck. Kim et al., APL Mat. 2015, 3, 041506. vasprun : str, optional path to vasprun. Default: vasprun.xml. kpoints : str, optional path to KPOINTS file if there are zero-weighted k-points. Default: KPOINTS. relaxation_time : float, optional charge carrier relaxation time. Default: 1e-14. lpfac : int, optional DoS interpolation factor. Default: 10. run : bool, optional run BoltzTraP. Default: True. analyse : bool, optional analyse BoltzTraP. Default: True. output : str, optional output hdf5 filename. Default: boltztrap.hdf5. run_dir : str, optional path to run boltztrap in. Default: current directory. clean : bool, optional remove boltztrap directory post-run. Default: False. kwargs passed to pymatgen.electronic.structure.boltztrap.BoltztrapRunner. Returns ------- None instead prints to hdf5 (see below). hdf5 File Contents ------------------ average_eff_mass : dict the charge carrier effective mass in units of m_e, taking into account all bands, as opposed to the single parabolic band model. Data is a dictionary with an array each for n and p doping, of shape (temperatures, concentrations, 3, 3). conductivity : dict electric conductivity in S m-1. Data is a dictionary with an array each for n and p doping, of shape (temperatures, concentrations, 3, 3). doping : array-like carrier concentration in cm-1. Identical to input. electronic_thermal_conductivity : dict electronic thermal conductivity in W m-1 K-1. Data is a dictionary with an array each for n and p doping, of shape (temperatures, concentrations, 3, 3). fermi_level : dict fermi level at different temperatures in units of eV. Data is a dictionary with an array each for n and p doping, of shape (temperatures, concentrations). power_factor : dict power factor in W m-1 K-2. Data is a dictionary with an array each for n and p doping, of shape (temperatures, concentrations, 3, 3). seebeck : dict Seebeck coefficient in muV K-1. Data is a dictionary with an array each for n and p doping, of shape (temperatures, concentrations, 3, 3). temperature : numpy array temperatures in K. meta : dict metadata: interpolation_factor : int lpfac. ke_mode : str as input. relaxation_time : float as input. soc : bool spin-orbit coupling calculation. units : dict units of each property above. """ import os from pymatgen.electronic_structure.boltztrap \ import BoltztrapRunner, BoltztrapAnalyzer, BoltztrapError from pymatgen.io.vasp.outputs import Vasprun from scipy import constants # check inputs for name, value in zip(['run', 'analyse', 'clean'], [ run, analyse, clean]): assert isinstance(value, bool), '{} must be True or False'.format(name) ke_mode = ke_mode.lower() ke_modes = ['boltzmann', 'wiedemann', 'snyder'] assert ke_mode in ke_modes, 'ke_mode must be {} or {}.'.format( ', '.join(ke_modes[:-1]), ke_modes[-1]) run_dir = os.path.abspath(run_dir) tmax += tstep tmin = tstep if tmin is None else tmin temperature = np.arange(tmin, tmax, tstep) if run: # run boltztrap from vasprun.xml -> boltztrap directory doping = np.array(doping) vr = Vasprun(vasprun, parse_potcar_file=False) soc = vr.as_dict()['input']['parameters']['LSORBIT'] try: bs = vr.get_band_structure(line_mode=False) nelect = vr.parameters['NELECT'] btr = BoltztrapRunner(bs, nelect, doping=list(doping), tmax=tmax, tgrid=tstep, soc=soc, lpfac=lpfac, **kwargs) print('Running Boltztrap...', end='') btr_dir = btr.run(path_dir=run_dir) print('Done.') except BoltztrapError: bs = vr.get_band_structure(line_mode=True,kpoints_filename=kpoints) nelect = vr.parameters['NELECT'] btr = BoltztrapRunner(bs, nelect, doping=list(doping), tmax=tmax, tgrid=tstep, soc=soc, lpfac=lpfac, **kwargs) btr_dir = btr.run(path_dir=run_dir) print('Done.') """ Detects whether the BoltzTraP build on this computer writes the doping concentrations correctly, and if it doesn't, writes them. """ with open(os.path.join(btr_dir, 'boltztrap.outputtrans'), 'r') as f: line = f.readlines()[-2] if len(line) >= 23 and line[:23] == ' Calling FermiIntegrals': with open(os.path.join(btr_dir, 'boltztrap.outputtrans'),'a') as f: for i, x in enumerate(np.concatenate((doping, -doping))): f.write( 'Doping level number {} n = {} carriers/cm3\n'.format(i, x)) else: btr_dir = os.path.join(run_dir, 'boltztrap') if analyse: # run boltztrap from boltztrap directory -> hdf5 file print('Analysing Boltztrap...', end='') bta = BoltztrapAnalyzer.from_files(btr_dir) print('Done.') data = {'average_eff_mass': {}, 'conductivity': {}, 'doping': doping, 'electronic_thermal_conductivity': {}, 'power_factor': {}, 'seebeck': {}, 'temperature': temperature, 'meta': {'units': {'average_eff_mass': 'm_e', 'conductivity': 'S m-1', 'doping': 'cm-1', 'electronic_thermal_conductivity': 'W m-1 K-1', 'fermi_level': 'eV', 'power_factor': 'W m-1 K-2', 'seebeck': 'muV K-1', 'temperature': 'K'}, 'dimensions': {'average_eff_mass': ['temperature', 'doping', 3, 3], 'conductivity': ['temperature', 'doping', 3, 3], 'doping': ['doping'], 'electronic_thermal_conductivity': ['temperature', 'doping', 3, 3], 'fermi_level': ['temperature', 'doping'], 'power_factor': ['temperature', 'doping', 3, 3], 'seebeck': ['temperature', 'doping', 3, 3], 'temperature': ['temperature']}, 'interpolation_factor': lpfac, 'ke_mode': ke_mode, 'relaxation_time': relaxation_time, 'soc': soc}} # load data print('Calculating transport...', end='') c = bta._cond_doping dp = bta.doping e = constants.e f = bta.mu_doping k = bta._kappa_doping me = constants.m_e s = bta._seebeck_doping # calculate transport properties for d in ['n', 'p']: c[d] = np.array([c[d][t] for t in temperature]) dp[d] = np.array(dp[d]) k[d] = np.array([k[d][t] for t in temperature]) f[d] = np.array([f[d][t] for t in temperature]) s[d] = np.array([s[d][t] for t in temperature]) data['average_eff_mass'][d] = np.linalg.inv(c[d]) \ * dp[d][None, :, None, None] \ * 1e6 * e ** 2 / me data['conductivity'][d] = np.multiply(c[d], relaxation_time) data['seebeck'][d] = np.multiply(s[d], 1e6) data['power_factor'][d] = tp.calculate.power_factor( data['conductivity'][d], data['seebeck'][d], use_tprc=False) if ke_mode == 'boltztrap': data['electronic_thermal_conductivity'][d] = \ k[d] * relaxation_time \ - data['power_factor'][d] * temperature[:,None,None,None] else: if ke_mode == 'wiedemann': L = 2.44E-8 else: L = (1.5 + np.exp(-np.abs(data['seebeck'][d])/116)) * 1e-8 data['electronic_thermal_conductivity'][d] = \ L * data['conductivity'][d] * temperature[:,None,None,None] data['fermi_level'] = f print('Done.') tp.data.save.hdf5(data, output) if clean: shutil.rmtree(btr_dir) os.remove(os.path.join(run_dir, 'boltztrap.out')) return