Source code for EPWpy.QE.PH_util

import numpy as np

[docs] class PHProperties: """ A class for parsing and analyzing phonon (PH) calculation properties. This class provides access to various physical quantities derived from Quantum ESPRESSO (QE) `ph.x` output files, such as dielectric constants, Fermi level, band structures, and lattice vectors. It serves as a post-processing utility to extract, store, and manipulate phonon-related data. Parameters ---------- file : str Path to the phonon output file generated by QE (`ph.out`). energy_range : float, optional Energy window (in eV) around the Fermi level for evaluating band-related quantities. Defaults to ``None``. Attributes ---------- eps : float Static dielectric constant of the system. nbnd_energy : int Number of bands within the specified energy range. lattice_vec : ndarray Lattice vectors extracted from the associated PW calculation. fermi_level : float Fermi energy or the highest occupied band energy (in eV). atomic_positions : ndarray Atomic positions in Cartesian or fractional coordinates. band_scf : ndarray Self-consistent field (SCF) band structure data array. Examples -------- >>> ph = PHProperties(file='Si.ph.out', energy_range=5.0) >>> print(ph.file) 'Si.ph.out' >>> print(ph.energy_range) 5.0 """ def __init__(self, file: str, energy_range: float = None, version: float = 7.4 ): self.file = file self.energy_range = energy_range self.version = version
[docs] def ph_properties(self): """ Returns various phonon related outputs """ return({'q_points':self.qpoints, 'output_file':self.file, 'dielectric':self.eps_ph})
[docs] def plot_pl_vector(self,mode): """ performs a quiver plot of pl vectors """ pass
@property def eps_ph(self): """ Returns high-frequency dielectric matrix from DFPT """ dielectric=get_dielectric_matrix(self.file) return(dielectric) @property def qpoints(self): """ Returns q-points for Ph calculation """ return(get_qpoints(self.file)) @property def gkk(self): """ Returns the electron–phonon coupling matrix g(ibnd, jbnd, imode, ik, iq) extracted from a Quantum ESPRESSO `ph.x` output file. The matrix has dimensions: (nbnd_i, nbnd_j, nmodes, nkpoints, nqpoints) where: - ibnd, jbnd: band indices - imode: phonon mode index - ik, iq: k-point and q-point indices Returns ------- np.ndarray 5D array of electron–phonon coupling strengths in units consistent with the QE output. """ return(get_gkk(self.file)) @property def dynmat(self): """ Returns the dynamical matrix """ pass @property def polarization_vector(self): """ Compute and return the polarization vectors from the dynamical matrix file. This property reads the `dynmat.axsf` file generated by `dynmat.x` and extracts the atomic displacement (polarization) vectors corresponding to phonon modes at the Γ-point or other q-points, depending on the underlying calculation. Returns ------- numpy.ndarray or None A 3D NumPy array of shape ``(nmode, natoms, 6)`` containing the polarization vectors and atomic coordinates for each phonon mode. Returns ``None`` if no polarization data are found. Notes ----- Each entry in the last dimension (6 columns) corresponds typically to: `[x, y, z, dx, dy, dz]`, where `(x, y, z)` are atomic positions and `(dx, dy, dz)` are displacement components for a given mode. """ return(get_polarization_vec(self.dynmat_file, self.atoms, self.natoms))
[docs] def get_polarization_vec(dynmat_file, atoms, natoms): """ Reads dynmat.axsf file to return polarization vectors """ matrix = [] t = 0 with open(dynmat_file,'r') as f: for line in f: #print(line.split()) if (line.split()[0] == 'ANIMSTEPS'): nmode = int(line.split()[1]) if (line.split()[0] == 'PRIMCOORD'): check1 = True t = 0 if (line.split()[0] in atoms): matrix.append(line.split()[1:]) if (len(matrix) > 0): matrix1 = np.array(matrix).astype(float).reshape(nmode, natoms, 6) return(matrix1) else: return(None)
[docs] def get_dielectric_matrix(ph_file): T = 0 i = 0 dielectric = np.zeros((3,3), dtype = float) with open(ph_file, 'r') as f: for line in f: if ('Dielectric constant in cartesian axis' in line): T = 1 if ((T > 1) & (i < 3) & (len(line.split()) > 0)): dielectric[i,:] = np.array(line.split()[1:4]).astype(float) i +=1 T = 2*T f.close() return(dielectric)
[docs] def get_qpoints(ph_file): T = 0 i = 0 nqs = 0 with open(ph_file, 'r') as f: for line in f: if ('Dynamical matrices for' in line): T = 1 if (T == 2): nqs = int(line.split()[1]) ph_qpoints = np.zeros((nqs,3),dtype=float) if ((T > 4) & (i < nqs) & (len(line.split()) > 0)): ph_qpoints[i,:3] = np.array(line.split()[1:4]).astype(float) i +=1 T = 2*T f.close() return(ph_qpoints)
[docs] def get_gkk(ph_file): nq = [] nk = [] q_arr = [] k_arr = [] g_mat = [] band1=[] band2=[] mode = [] kk = [] qq = [] t = 0 iq = 0 ik = 0 with open(ph_file, 'r') as f: for line in f: if ('q coord' in line): Arr = line.split()[2:] t = 1 if (Arr in q_arr): pass else: q_arr.append(Arr) iq +=1 if ('k coord' in line): Arr = line.split()[2:] if (Arr in k_arr): pass else: k_arr.append(Arr) ik +=1 t = t*2 if ((t > 16) & ('-----------' in line)): t = 0 if (t > 16): kk.append(ik) qq.append(iq) band1.append(int(line.split()[0])) band2.append(int(line.split()[1])) mode.append(int(line.split()[2])) if (self.version < 7.5): g_mat.append(float(line.split()[-3])) else: g_mat.append(float(line.split()[-3])) f.close() g = np.zeros((max(band1),max(band2),max(mode),len(k_arr),len(q_arr)),dtype = float) t = 0 for i in range(len(g_mat)): g[band1[i]-1,band2[i]-1,mode[i]-1,kk[i]-1,qq[i]-1] = g_mat[i] return(g)
if __name__=="__main__": GKK = get_gkk('notebooks_basic/si/ph/ph_g.out') for i in range(4): for j in range(4): for k in range(6): print(GKK[i,j,k,0,0])