"""Implements functionality for handling phonons."""from__future__importannotationsfrompathlibimportPathfromtypingimportTYPE_CHECKINGimportnumpyasnpfromlineshape_tools.constantsimportomega2eVifTYPE_CHECKING:fromase.atomsimportAtoms
[docs]defget_ipr(U:np.ndarray)->np.ndarray:"""Evaluate the inverse participation ratio. Args: U (np.ndarray): matrix with phonon eigenvectors as columns (see np.linalg.eigh). """return1/np.sum(np.sum(U.reshape((U.shape[0]//3,3,U.shape[1]))**2,axis=1)**2,axis=0)
[docs]defget_disp_vect(atoms0:Atoms,atoms1:Atoms)->np.ndarray:"""Compute smallest displacement vector between two sets of atoms. Args: atoms0 (Atoms): first set of atoms atoms1 (Atoms): second set of atoms Returns: np.ndarray: 3N dimensional displacement vector in Å """dx=atoms0.get_scaled_positions()-atoms1.get_scaled_positions()dx-=np.round(dx)dx=dx@atoms0.cellreturndx.flatten()
[docs]defget_dq_vect(atoms0:Atoms,atoms1:Atoms)->np.ndarray:"""Compute smallest mass-weighted displacement vector between two sets of atoms. Args: atoms0 (Atoms): first set of atoms atoms1 (Atoms): second set of atoms Returns: np.ndarray: 3N dimensional displacement vector in amu^{1/2} Å """returnnp.repeat(np.sqrt(atoms0.get_masses()),3)*get_disp_vect(atoms0,atoms1)
[docs]defget_phonons(dynmat:np.ndarray|Path|str,acoustic_tol:float=5e-4)->tuple[np.ndarray,np.ndarray]:"""Compute the phonon frequencies and eigenvectors from a dynamical matrix. Args: dynmat (np.ndarray | Path | str): path to a dynamical matrix in .npz format or a np.ndarray corresponding to a dynamical matrix (shape 3N x 3N). acoustic_tol (float): tolerance (in eV) to determine acoustic phonon modes. Returns: omega (np.ndarray): phonon frequencies (in eV/amu/Ang^2). U (np.ndarray): matrix with phonon eigenvectors as columns (see np.linalg.eigh). """ifisinstance(dynmat,Path)orisinstance(dynmat,str):H=np.load(dynmat)["H"]else:H=dynmatomega2,U=np.linalg.eigh(H)omega2[omega2<(acoustic_tol/omega2eV)**2]=0.0returnnp.sqrt(omega2),U