def phono3py(filename, quantities=['kappa', 'temperature'], write_lifetime=False, write_mfp=False, write_occupation=False): """Loads Phono3py data. Can also calculate lifetimes, mean free paths and occupations, which can be written to a file. Includes unit conversions and outputs units for all the data (see tp.settings). Also corrects mode_kappa for different phono3py versions. Arguments --------- filename : str filepath. quantities : list, optional values to extract. Accepts Phono3py keys, lifetime, mean_free_path and occupation. Default: kappa, temperature. write_lifetime : bool, optional write lifetimes to a new hdf5 file if in quantites. Default: False. write_mfp : bool, optional write mean free paths to a new hdf5 file if in quantities. Default: False. write_occupation : bool, optional write occupations to a new hdf5 file if in quantities. Default: False. Returns ------- dict output data. """ import h5py # name conversions and abbreviations conversions = settings.phono3py_conversions() pnames = settings.to_phono3py() tnames = settings.to_tp() units = settings.units() if isinstance(quantities, str): quantities = quantities.split() quantities = [pnames[q] if q in pnames else q for q in quantities] subs = { 'dispersion': 'qpoint', 'waterfall': 'frequency', 'wideband': ['frequency', 'gamma', 'qpoint'] } hast = [ 'gamma', 'heat_capacity', 'kappa', 'lifetime', 'mean_free_path', 'mode_kappa', 'occupation' ] for i in range(len(quantities)): if quantities[i] in subs: quantities[i] = subs[quantities[i]] quantities = list(np.ravel(quantities)) # add dependant variables if 'temperature' not in quantities: for q in quantities: if q in hast: quantities.append('temperature') break # load and calculate data data = h5py.File(filename, 'r') data2 = {'meta': {'kappa_source': 'phono3py', 'units': {}}} for q in quantities: assert q in data or q in ['lifetime', 'mean_free_path', 'occupation'], \ '{} unrecognised. Quantity must be {}, lifetime, mean_free_path ' \ 'or occupation'.format(q, ', '.join(data)) q2 = tnames[q] if q in tnames else q if q in data: data2[q2] = data[q][()] elif q in ['lifetime', 'mean_free_path']: data2['lifetime'] = np.reciprocal(np.multiply( 2, data['gamma'][()])) data2['lifetime'] = np.where(np.isinf(data2['lifetime']), 0, data2['lifetime']) if q == 'mean_free_path': data2[q] = np.multiply( np.transpose([ data2['lifetime'], ] * 3, (1, 2, 3, 0)), data['group_velocity'][()]) elif q == 'occupation': from tp.calculate import be_occupation as occupation data2[q] = [ occupation(data['frequency'][()], t) for t in data['temperature'][()] ] if q2 in units: data2['meta']['units'][q2] = units[q2] # write calculated data (loath to mess with original file) for write, q in zip([write_lifetime, write_mfp, write_occupation], ['lifetime', 'mean_free_path', 'occupation']): if write and q in quantities: data3 = h5py.File('{}-{}'.format(q, filename), 'w') for q2 in [q, 'temperature', 'qpoint']: data3.create_dataset(q2, np.shape(data2[q2]), data=data2[q2]) data3.close() # check mode_kappa and correct for certain phono3py versions if 'mode_kappa' in data2: try: k = round(data['kappa'][-1][0], 3) mk = round(data['mode_kappa'][-1][:, :, 0].sum(axis=1).sum(), 3) if k != mk: raise Exception( 'The sum of mode_kappa does not equal kappa.\n ' 'kappa={:.3f}; sum(mode_kappa)={:.3f}.'.format(k, mk)) except Exception: mk2 = np.divide(data['mode_kappa'], np.prod(data['mesh'][:])) k = round(data['kappa'][-1][0], 3) mk = round(mk2[-1][:, :, 0].sum(axis=1).sum(), 3) if k != mk: raise Exception( 'Mode kappa has been divided by the mesh, but ' 'the sum of mode_kappa does not equal kappa.\n ' 'kappa={:.3f}; sum(mode_kappa)={:.3f}.'.format(k, mk)) else: data2['mode_kappa'] = np.divide(data2['mode_kappa'], np.prod(data['mesh'][()][:])) data.close() for c in conversions: if c in data2: data2[c] = np.multiply(data2[c], conversions[c]) return data2
def boltztrap(filename, quantities=[ 'temperature', 'doping', 'seebeck', 'conductivity', 'electronic_thermal_conductivity' ], doping='n'): """Loads BoltzTraP data from the tp boltztrap.hdf5 file. Includes unit conversion and outputs units (see tp.settings). Arguments --------- filename : str filepath. quantites : dict, optional values to extract. Accepts boltztrap.hdf5 keys. Default: temperature, doping, seebeck, conductivity, electronic_thermal_conductivity. doping : str, optional doping. Default: n. Returns ------- dict extracted values. """ import h5py # name conversions and abbreviations assert doping in ['n', 'p'], 'doping must be n or p' conversions = settings.boltztrap_conversions() bnames = settings.to_boltztrap() tnames = settings.to_tp() units = settings.units() if isinstance(quantities, str): quantities = quantities.split() quantities = [bnames[q] if q in bnames else q for q in quantities] # list of quantities dependant on doping and temperature hasdope = [ 'average_eff_mass', 'conductivity', 'fermi_level', 'seebeck', 'power_factor', 'electronic_thermal_conductivity' ] hastemp = [ 'average_eff_mass', 'conductivity', 'fermi_level', 'seebeck', 'power_factor', 'electronic_thermal_conductivity' ] # add dependant variables if 'doping' not in quantities: for q in quantities: if q in hasdope: quantities.append('doping') break if 'temperature' not in quantities: for q in quantities: if q in hastemp: quantities.append('temperature') break # load data data = h5py.File(filename, 'r') data2 = {'meta': {'electronic_source': 'boltztrap', 'units': {}}} for q in quantities: assert q in data, '{} unrecognised. Quantity must be in {} or {}.'.format( q, ', '.join(list(data)[:-1]), list(data)[-1]) q2 = tnames[q] if q in tnames else q data2[q2] = data[q] if q in hasdope: data2[q2] = data2[q2][doping] if q2 in units: data2['meta']['units'][q2] = units[q2] for c in conversions: if c in data2: data2[c] = np.multiply(data2[c], conversions[c]) return data2
def amset_mesh(filename, quantities=[ 'temperature', 'doping', 'scattering_rates', 'scattering_labels' ], spin='avg'): """Loads AMSET mesh data. Includes unit conversion and outputs units (see tp.settings). Swaps temperature and doping indices so temperature is first, for consistency with other codes. Arguments --------- filename : str filepath. quantites : dict, optional values to extract. Accepts AMSET keys, without spin channels, which are dealt with in the spin variable. Default: temperature, doping, scattering_rates, scattering_labels. spin : str, optional spin. Accepts up, down or avg. If avg and there is only one spin channel, selects that, else averages both. Default: avg. Returns ------- dict extracted values. """ import h5py # name conversions and abbreviations conversions = settings.amset_conversions() anames = settings.to_amset() tnames = settings.to_tp() units = settings.units() if isinstance(quantities, str): quantities = quantities.split() quantities = [anames[q] if q in anames else q for q in quantities] # list of quantities dependant on doping and temperature hasdope = ['fermi_levels', 'scattering_rates'] hastemp = ['fermi_levels', 'scattering_rates'] hastype = ['scattering_rates'] hasspin = ['energies', 'vb_index', 'scattering_rates', 'velocities'] # add dependant variables if 'doping' not in quantities: for q in quantities: if q in hasdope: quantities.append('doping') break if 'temperatures' not in quantities: for q in quantities: if q in hastemp: quantities.append('temperatures') break if 'scattering_labels' not in quantities: for q in quantities: if q in hastype: quantities.append('scattering_labels') break # load data data = h5py.File(filename, 'r') if spin in ['avg', 'average']: if 'energies_up' in data and 'energies_down' in data: spin = 'avg' elif 'energies_up' in data: spin = 'up' elif 'energies_down' in data: spin = 'down' data2 = {'meta': {'electronic_source': 'amset', 'spin': spin, 'units': {}}} for q in quantities: q2 = tnames[q] if q in tnames else q if q in hasspin: if spin == 'avg': data2[q2] = np.average( [data['{}_up'.format(q)], data['{}_down'.format(q)]], axis=0) elif spin in ['up', 'down']: data2[q2] = data['{}_{}'.format(q, spin)] else: raise Exception('spin must be up or down or avg') else: data2[q2] = data[q] if q in hasdope and q in hastemp: # temperature in first index for consistency with other codes if q in hastype: data2[q2] = np.swapaxes(data2[q2], 1, 2) else: data2[q2] = np.swapaxes(data2[q2], 0, 1) if q2 in units: data2['meta']['units'][q2] = units[q2] for c in conversions: if c in data2: data2[c] = np.multiply(data2[c], conversions[c]) return data2
def amset(filename, quantities=[ 'temperature', 'doping', 'seebeck', 'conductivity', 'electronic_thermal_conductivity' ]): """Loads AMSET transport data. Includes unit conversion and outputs units (see tp.settings). Swaps temperature and doping indices so temperature is first, for consistency with other codes, and mobility is formatted as an array, like scattering_rates is in the mesh.h5 file. Maintains basic compatibility with amset 0.1. Arguments --------- filename : str filepath. quantites : dict, optional values to extract. Default: temperature, doping, seebeck, conductivity, electronic_thermal_conductivity. Returns ------- dict extracted values. """ import json # name conversions and abbreviations conversions = settings.amset_conversions() anames = settings.to_amset() tnames = settings.to_tp() units = settings.units() if isinstance(quantities, str): quantities = quantities.split() quantities = [anames[q] if q in anames else q for q in quantities] # list of quantities dependant on doping, temperature and scattering hasdope = [ 'fermi_levels', 'conductivity', 'seebeck', 'electronic_thermal_conductivity', 'mobility' ] hastemp = [ 'fermi_levels', 'conductivity', 'seebeck', 'electronic_thermal_conductivity', 'mobility' ] hastype = ['mobility'] # add dependant variables if 'doping' not in quantities: for q in quantities: if q in hasdope: quantities.append('doping') break if 'temperatures' not in quantities: for q in quantities: if q in hastemp: quantities.append('temperatures') break # load data with open(filename) as f: data = json.load(f) data2 = {'meta': {'electronic_source': 'amset', 'units': {}}} for q in quantities: assert q in data, \ '{} unrecognised. Quantity must be in {} or {}.'.format(q, ', '.join(list(data)[:-1]), list(data)[-1]) q2 = tnames[q] if q in tnames else q # compatibility with previous version if isinstance(data[q], dict) and 'data' in data[q]: data2[q2] = data[q]['data'] else: data2[q2] = data[q] if q in hasdope and q in hastemp: # temperature index first for consistency with other codes if q in hastype: for t in data2[q2]: data2[q2][t] = np.swapaxes(data2[q2][t], 0, 1) else: data2[q2] = np.swapaxes(data2[q2], 0, 1) if q in hastype: if 'scattering_labels' not in data2: data2['scattering_labels'] = data[q].keys() # for consistency with the format in the mesh data data2[q2] = [data2[q2][l] for l in data2['scattering_labels']] if q2 in units: data2['meta']['units'][q2] = units[q2] for c in conversions: if c in data2: data2[c] = np.multiply(data2[c], conversions[c]) return data2
def amset(filename, quantities=[ 'temperatures', 'doping', 'seebeck', 'conductivity', 'electronic_thermal_conductivity' ], spin='up'): """Loads AMSET data. Includes unit conversion and outputs units (see tp.settings). Arguments: filename : str filepath. quantites : dict, optional values to extract. Accepts AMSET keys Default: temperatures, doping, seebeck, conductivity, electronic_thermal_conductivity. spin : str, optional spin. Default: up. Returns: dict extracted values. """ import json # name conversions and abbreviations conversions = settings.amset_conversions() anames = settings.to_amset() tnames = settings.to_tp() units = settings.units() if isinstance(quantities, str): quantities = quantities.split() quantities = [anames[q] if q in anames else q for q in quantities] # list of quantities requiring 'data' key, scattering type and spin hasdata = [ 'doping', 'temperatures', 'fermi_levels', 'conductivity', 'seebeck', 'electronic_thermal_conductivity', # 'mobility', 'kpoints', 'ir_kpoints', 'ir_to_full_kpoint_mapping' ] hastype = ['mobility', 'scattering_rates', 'scattering_labels'] hasspin = ['energies', 'vb_idx', 'velocities_product'] #, 'scattering_rates'] # list of quantities dependant on doping and temperature hasdope = [ 'fermi_levels', 'conductivity', 'seebeck', 'electronic_thermal_conductivity', 'mobility', 'scattering_rates' ] hastemp = [ 'fermi_levels', 'conductivity', 'seebeck', 'electronic_thermal_conductivity', 'mobility', 'energies', 'velocities_product', 'scattering_rates' ] # add dependant variables if 'doping' not in quantities: for q in quantities: if q in hasdope: quantities.append('doping') break if 'temperatures' not in quantities: for q in quantities: if q in hastemp: quantities.append('temperatures') break # load data with open(filename) as f: data = json.load(f) assert spin in data['scattering_rates'].keys(), \ 'spin must be in {}'.format(' or '.join(data['scattering_rates'].keys())) data2 = {'meta': {'electronic_source': 'amset', 'units': {}}} for q in quantities: assert q in data, '{} unrecognised. Quantity must be in {} or {}.'.format( q, ', '.join(list(data)[:-1]), list(data)[-1]) q2 = tnames[q] if q in tnames else q data2[q2] = data[q] if q in hasspin: data2[q2] = data2[q2][spin] if q in hasdata: data2[q2] = data2[q2]['data'] if q in hasdope and q not in hastype: # for consistency with other codes data2[q2] = np.swapaxes(data2[q2], 0, 1) if q2 in units: data2['meta']['units'][q2] = units[q2] for c in conversions: if c in data2: data2[c] = np.multiply(data2[c], conversions[c]) return data2