def plot_optical_indices(self, opp=None): project = self.projects[self.currentprojectid] if project.object_str_type(self.currentitemid) == 'cell': cell = project.cells[self.currentitemid] # check if cell already has OpticalIndices attribute try: len(cell.optical_indices.components) except AttributeError as e: if bf.grep(cell.outcar, "DIELECTRIC FUNCTION") is not None or bf.grep( cell.outcar, "DIELECTRIC TENSOR") is not None: cell.optical_indices = oi.OpticalIndices(cell.outcar) else: message = 'Warning! There is no dielectric function to plot in this file! ' message += '\nSee https://cms.mpi.univie.ac.at/wiki/index.php/Dielectric_properties_of_SiC for VASP help' print(message) return None if opp is None: fig = cell.optical_indices.plot( pp=cell.optical_indices.lastopp) else: fig = cell.optical_indices.plot(pp=opp) frame = tk.Frame(self.work_frame, bd=2, bg='white', relief=RAISED) self.fig_to_canvas(fig, frame) self.update_work_frame(frame, cell.treetitle)
def get_band_occupation(outcar, nkpts, functional): """ Retrieve the bands occupation for each kpoint :param outcar: content of the outcar file (list of strings) :param nkpts: number of kpoints (int) :param functional: functional used (string) :return: last energy and occupation of the bands for each kpoint """ if functional == 'GW0@GGA': str_beg = " band No. old QP-enery QP-energies sigma(KS) T+V_ion+V_H V^pw_x(r,r') Z occupation" indices_beg = np.array([f[1] for f in bf.grep(outcar, str_beg) ])[-nkpts:] + 2 col_index = 2 elif functional == 'G0W0@GGA': str_beg = " band No. KS-energies QP-energies sigma(KS) V_xc(KS) V^pw_x(r,r') Z occupation" indices_beg = np.array([f[1] for f in bf.grep(outcar, str_beg)]) + 2 col_index = 2 else: str_beg = ' band No. band energies occupation' indices_beg = np.array([f[1] for f in bf.grep(outcar, str_beg)]) + 1 col_index = 1 indices_end = np.array([outcar[f:].index('') for f in indices_beg]) raw_data = [ outcar[f:g] for f, g in zip(indices_beg, indices_end + indices_beg) ] data = [bf.convert_stringcolumn_to_array(f) for f in raw_data] return [[f[col_index], f[-1]] for f in data]
def extract_rpa(content): index_beg = bf.grep(content, 'INVERSE MACROSCOPIC DIELECTRIC TENSOR')[0][1] + 2 index_end = bf.grep(content, 'screened Coulomb potential')[0][1] - 4 blocks_indices = list(range(index_beg, index_end, 7)) data = [read_block(content[index: index+4]) for index in blocks_indices] energy = np.array([d[0] for d in data]) eps1, eps2 = np.transpose([d[1:] for d in data], axes=(1, 2, 0)) return energy, eps1, eps2
def extract_ipa_gw(content): index_beg = bf.grep(content, 'HEAD OF MICROSCOPIC DIELECTRIC TENSOR (INDEPENDENT PARTICLE)')[0][1] + 2 index_end = bf.grep(content, 'XI_LOCAL: cpu time')[0][1] - 4 blocks_indices = list(range(index_beg, index_end, 7)) data = [read_block(content[index: index+4]) for index in blocks_indices] energy = np.array([d[0] for d in data]) eps1, eps2 = np.transpose([d[1:] for d in data], axes=(1, 2, 0)) return energy, eps1, eps2
def __init__(self, outcar_file): if type(outcar_file) == str: content = bf.read_file(outcar_file) elif type(outcar_file) == list: content = outcar_file self.components = ['XX', 'YY', 'ZZ', 'XY', 'YZ', 'ZX'] self.quantities = ['epsilon 1', 'epsilon 2', 'n', 'k', 'R', 'abs', 'L', 'sigma1', 'sigma2'] self.quantities_labels = ('\epsilon_1', '\epsilon_2', 'n', 'k', 'R' , 'abs', 'L', 'sigma1', 'sigma2') self.components_labels = self.components algo = bf.grep(content, 'ALGO =', 0, 'execute GW part') if algo == 'CHI': self._energy, self._eps1, self._eps2 = extract_rpa(content) elif algo is not None and algo.find('GW') > -1: self._energy, self._eps1, self._eps2 = extract_ipa_gw(content) else: self._energy, self._eps1, self._eps2 = extract_ipa(content) self._n, self._k, self._r, self._abs, self._L, self._sigma1, self._sigma2 = np.transpose([get_nkr(e1, e2, self._energy) for e1, e2 in zip(self._eps1, self._eps2)], axes=(1, 0, 2)) # self._abs, self._L, self._sigma1, self._sigma2 self.data = np.array([self._eps1, self._eps2, self._n, self._k, self._r,self._abs,self._L,self._sigma1,self._sigma2]) self.data_dict = dict(list(zip(self.quantities, self.data))) self.data_dict_t = dict(list(zip(self.components, np.transpose(self.data, axes=(1, 0, 2))))) self.quantities_dict = dict(list(zip(self.quantities, self.quantities_labels))) self.components_dict = dict(list(zip(self.components, self.components_labels))) self.lastopp = OpticalPlotParameters(self)
def get_cell_parameters(outcar): """ Retrieve the cell parameters from the OUTCAR file content :param outcar: content of the outcar file (list of strings, each one for a line) :return: cristallographic parameters of the cell """ index = bf.grep(outcar, 'direct lattice vectors')[-1][ 1] # location of the cristallographic parameters in the OUTCAR raw_data = outcar[index + 1:index + 4] # direct and reciprocal lattice vectors return [[float(f) for f in g.split()[:3]] for g in raw_data]
def extract_ipa(content): tensor_headers = bf.grep(content, "frequency dependent") if tensor_headers is not None: if len(tensor_headers) == 2: index1 = bf.grep(content, "frequency dependent IMAGINARY DIELECTRIC FUNCTION")[0][1] index2 = bf.grep(content, "frequency dependent REAL DIELECTRIC FUNCTION")[0][1] index3 = bf.grep(content, "The outermost node ")[0][1] elif len(tensor_headers) == 4: index1 = tensor_headers[0][1] index2 = tensor_headers[1][1] index3 = tensor_headers[2][1] else: print('Warning! Case not programmed! Are you sure your file is ok?') eps2 = bf.fast_stringcolumn_to_array(content[index1 + 3: index2 - 1]) eps1 = bf.fast_stringcolumn_to_array(content[index2 + 3: index3 - 1]) return eps1[0], eps1[1:], eps2[1:] else: print('Warning! Could not find tensor header in OUTCAR file')
def get_functional(outcar): """ Retrieve the functional used from the outcar data :param outcar: content of the OUTCAR file (list of strings) :return: functional of used """ # Default values functional = 'other' # used for display inline functional_title = 'other' # used for display in matplotlib lexch = bf.grep(outcar, 'LEXCH =', 0, 'internal', 'str', 1) lhfcalc = bf.grep(outcar, 'LHFCALC =', 0, 'Hartree', 'str', 1) hfscreen = bf.grep(outcar, 'HFSCREEN=', 0, 'screening', 'float', 1) gw = bf.grep(outcar, 'Response functions by sum over occupied states:', nb_found=2) if lexch == '2' and lhfcalc == 'F': functional = 'LDA' functional_title = 'LDA' if lexch == '8' and lhfcalc == 'F': functional = 'GGA' functional_title = 'GGA' if lexch == '8' and lhfcalc == 'T': if hfscreen == 0.2: functional = 'HSE' functional_title = 'HSE' if hfscreen == 0.0: functional = 'PBE0' functional_title = 'PBE0' if gw is not None: nelm = bf.grep(outcar, 'NELM =', 0, 'number', 'int', 1) if nelm == 1: functional = 'G0W0@GGA' functional_title = 'G_0W_0@GGA' elif nelm > 1: functional = 'GW0@GGA' functional_title = 'GW_0@GGA' return functional, functional_title
def get_kpoints_reciprocal_coords(outcar, nkpts): index_beg = bf.grep(outcar, ' k-points in units of 2pi/SCALE and weight:', nb_found=1)[0][1] + 1 index_end = outcar[index_beg:].index(' ') data_str = outcar[index_beg:index_beg + index_end] coordinates = np.transpose(bf.convert_stringcolumn_to_array(data_str)[:3]) if len(coordinates) != nkpts: raise bf.PydefImportError( 'Number of kpoint coordinates in reciprocal space retrieved ' 'and number of kpoints are not consistent') else: return coordinates
def get_kpoints_weights_and_coords(outcar, nkpts): """ Retrieve the kpoints weights from the OUTCAR file content :param outcar: content of the OUTCAR file (list of strings) :param nkpts: number of kpoints (int) :return: numpy array """ index_beg = bf.grep(outcar, 'k-points in reciprocal lattice and weights', nb_found=1)[0][1] + 1 index_end = outcar[index_beg:].index(' ') data_str = outcar[index_beg:index_beg + index_end] x, y, z, weights = bf.convert_stringcolumn_to_array(data_str) coordinates = [[f, g, h] for f, g, h in zip(x, y, z)] if len(weights) != nkpts: raise bf.PydefImportError( 'Number of kpoint weights retrieved and number of kpoints are not consistent' ) else: return coordinates, weights
def get_atoms_positions(outcar, atoms): """ :param outcar: content of the outcar file (list of strings) :param atoms: number of atoms of each atomic species (list of integers) :return: position of each atom as a dictionary """ str_beg = 'position of ions in cartesian coordinates (Angst):' index_beg = bf.grep( outcar, str_beg, nb_found=1)[0][1] + 1 # index of the first atom position index_end = outcar[index_beg:].index('') - 1 atoms_positions = [[float(f) for f in g.split()] for g in outcar[index_beg:index_end + index_beg]] # Check that the number of positions retrieved is equal to the number of atoms if len(atoms_positions) != len(atoms): raise bf.PydefImportError( "The number of atoms positions is not consistent with the total number of atoms" ) else: return dict(zip(atoms, atoms_positions))
def get_electrostatic_potentials(outcar, atoms): """ Retrieve the electrostatic averaged potentials from the OUTCAR file :param outcar: content of the OUTCAR file (list of strings) :param atoms: number of atoms of each atomic species (list of integers) :return: dictionary with the electrostatic potential for each atom """ index_beg = bf.grep(outcar, 'average (electrostatic) potential at core', nb_found=1)[0][1] + 3 index_end = outcar[index_beg:].index(' ') potentials_str = outcar[index_beg:index_beg + index_end] potentials_raw = np.concatenate( [[float(f) for f in re.split(' |-', q)[1:]] for q in potentials_str]) potentials = np.array( [-f[1] for f in np.split(potentials_raw, len(atoms))]) if len(potentials) != len(atoms): raise bf.PydefImportError( 'Number of electrostatic potentials retrieved and number are not consistent' ) return dict(zip(list(atoms), potentials))
def __init__(self, outcar_file, doscar_file): """ Read the OUTCAR and DOSCAR output files of a VASP calculation :param outcar_file: location of the OUTCAR file (string) :param doscar_file: location of the DOSCAR file (string) """ # --------------------------------------------------- OUTCAR --------------------------------------------------- self.OUTCAR = outcar_file self.DOSCAR = doscar_file self.outcar = bf.read_file(outcar_file) # content of the OUTCAR file if self.outcar[0][:6] != ' vasp.': raise bf.PydefOutcarError( 'The given file appears to not be a valid OUTCAR file.') # ------------------------------------------- CALCULATION PROPERTIES ------------------------------------------- self.functional, self.functional_title = get_functional( self.outcar) # functional used self.nedos = bf.grep(self.outcar, 'NEDOS =', 0, 'number of ions', 'int', 1) # number of point in the DOS self.encut = bf.grep(self.outcar, 'ENCUT =', 0, 'eV', 'float', 1) # ENCUT used self.ediff = bf.grep(self.outcar, 'EDIFF =', 0, 'stopping', 'float', 1) # EDIFF value self.emin = bf.grep(self.outcar, 'EMIN =', 0, ';', 'float', 1) # minimum energy for the DOS self.emax = bf.grep(self.outcar, 'EMAX =', 0, 'energy-range', 'float', 1) # maximum energy for the DOS self.ismear = bf.grep(self.outcar, 'ISMEAR =', 0, ';', 'int', 1) # ISMEAR tag self.lorbit = bf.grep(self.outcar, 'LORBIT =', 0, '0 simple, 1 ext', 'int', 1) # LORBIT tag self.isym = bf.grep(self.outcar, 'ISYM =', 0, '0-nonsym', 'int', 1) # ISYM tag self.istart = bf.grep(self.outcar, 'ISTART =', 0, 'job', 'int', 1) # ISTART tag self.ispin = bf.grep(self.outcar, 'ISPIN =', 0, 'spin', 'int', 1) # ISPIN tag self.icharg = bf.grep(self.outcar, 'ICHARG =', 0, 'charge:', 'int', 1) # ICHARG tag # --------------------------------------------- SYSTEM PROPERTIES ---------------------------------------------- self.nb_atoms_tot = bf.grep(self.outcar, 'NIONS =', 0, False, 'int', 1) # total number of atoms self.nb_atoms = [ int(f) for f in bf.grep(self.outcar, 'ions per type =', 0).split() ] # population of each atomic species self.atoms_types = [ bf.grep(self.outcar, 'VRHFIN =', f, ':') for f in range(len(bf.grep(self.outcar, 'VRHFIN ='))) ] # atomic species self.population = dict(zip(self.atoms_types, self.nb_atoms)) self.atoms_valence = [ int(float(f)) for f in bf.grep(self.outcar, 'ZVAL =', -1).split() ] # valence of each atomic species self.atoms = np.concatenate( [[f + ' (' + str(g) + ')' for g in range(1, q + 1)] for f, q in zip(self.atoms_types, self.nb_atoms)]) # atoms list self.nb_electrons = bf.grep(self.outcar, 'NELECT =', 0, 'total number', 'float', 1) # total number of electrons self.charge = sum( np.array(self.nb_atoms) * np.array(self.atoms_valence)) - self.nb_electrons self.orbitals = [ f for f in bf.grep(self.outcar, '# of ion', 0, 'tot').split(' ') if f != '' ] # verification of the consistence of the data retrieved if self.nb_atoms_tot != sum(self.nb_atoms) or \ len(self.nb_atoms) != len(self.atoms_types) or \ len(self.nb_atoms) != len(self.atoms_valence): raise bf.PydefImportError( 'Numbers of atoms retrieved are not consistent') self.name, self.display_name = get_system_name(self.atoms_types, self.nb_atoms, False) self.rname, self.display_rname = get_system_name( self.atoms_types, self.nb_atoms, True) # --------------------------------------------- CALCULATION RESULT --------------------------------------------- # Number of electronic steps if self.functional != 'G0W0@GGA' and self.functional != 'GW0@GGA': self.nb_iterations = len(bf.grep( self.outcar, 'Iteration')) # for non GW calculations else: self.nb_iterations = bf.grep(self.outcar, 'NELM =', 0, 'number', 'int', 1) # for GW calculations # Cristallographic properties self.cell_parameters = get_cell_parameters( self.outcar) # cristallographic parameters self.atoms_positions = get_atoms_positions( self.outcar, self.atoms) # atoms positions # Energy & Density of states self.energy = bf.grep(self.outcar, 'free energy TOTEN =', -1, 'eV', 'float', self.nb_iterations) # total energy self.fermi_energy = bf.grep(self.outcar, ' BZINTS: Fermi energy:', -1, ';', 'float') # fermi energy if self.ismear == 0: self.fermi_energy = bf.grep(self.outcar, 'E-fermi :', 0, 'XC(G=0)', 'float', nb_found=1) self.nkpts = bf.grep(self.outcar, 'NKPTS =', 0, 'k-points in BZ', 'int', 1) # number of k-points self.kpoints_coords, self.kpoints_weights = get_kpoints_weights_and_coords( self.outcar, self.nkpts) self.kpoints_coords_r = get_kpoints_reciprocal_coords( self.outcar, self.nkpts) self.nbands = bf.grep(self.outcar, 'NBANDS=', 0, False, 'int', 1) # number of bands self.bands_data = get_band_occupation( self.outcar, self.nkpts, self.functional) # bands energy and occupation self.VBM, self.CBM = get_band_extrema( self.bands_data) # VBM and CBM energies self.gap = self.CBM - self.VBM # electronic gap if self.functional != 'G0W0@GGA' and self.functional != 'GW0@GGA': self.potentials = get_electrostatic_potentials( self.outcar, self.atoms) # electrostatic averaged potentials else: self.potentials = None # --------------------------------------------------- OTHERS --------------------------------------------------- self.ID = ''.join([f + str(g) for f, g in zip(self.atoms_types, self.nb_atoms)]) + '_' + self.functional\ + '_q' + str(int(self.charge)) self.title = self.display_name + ' ' + self.functional_title + ' q=%.0f' % self.charge # title of the # --------------------------------------------------- DOSCAR --------------------------------------------------- if self.DOSCAR != '': self.doscar = bf.read_file( doscar_file) # content of the DOSCAR file self.dos_energy, self.total_dos, self.total_dos_up, self.total_dos_down, self.dos_opa, self.dos_opa_up, \ self.dos_opa_down, self.dos_opas, self.dos_opas_up, self.dos_opas_down = self.analyse_dos() # Maximum value of each DOS excluding the first value self.dosmax = np.max(self.total_dos[1:]) if self.ispin == 2: self.dosmax_up = np.max(self.total_dos_up[1:]) self.dosmax_down = np.max(self.total_dos_down[1:]) self.dpp = DosPlotParameters(self) # DOS plot parameters if self.icharg == 11: self.bpp = BandDiagramPlotParameters(self)
eps1, eps2, n, k, r = c.plot() # eps1.show() n.show() k.show() r.show() c = cc.Cell('D:/OUTCAR.LOPTICS') import sys sys.exit() import pydef_core.basic_functions as bf content = bf.read_file('D:/OUTCAR.LOPTICS') test0 = bf.grep(content, "frequency dependent IMAGINARY DIELECTRIC FUNCTION") index1 = bf.grep(content, "frequency dependent IMAGINARY DIELECTRIC FUNCTION")[0][1] index2 = bf.grep(content, "frequency dependent REAL DIELECTRIC FUNCTION")[0][1] index3 = bf.grep( content, "The outermost node ")[0][1] # This can be a problem sometime! test1 = content[index1 + 4:index2 - 1] test2 = content[index2 + 4:index3 - 1] def check(arg, index): i = index - 1 for elt in arg: i += 1 j = -1