def get_chi(self, xc='RPA', q_c=[0, 0, 0], direction='x'): """ Returns v^1/2 chi V^1/2""" pd, chi0_wGG, chi0_wxvG, chi0_wvv = self.calculate_chi0(q_c) G_G = pd.G2_qG[0]**0.5 nG = len(G_G) if pd.kd.gamma: G_G[0] = 1.0 if isinstance(direction, str): d_v = { 'x': [1, 0, 0], 'y': [0, 1, 0], 'z': [0, 0, 1] }[direction] else: d_v = direction d_v = np.asarray(d_v) / np.linalg.norm(d_v) W = slice(self.w1, self.w2) chi0_wGG[:, 0] = np.dot(d_v, chi0_wxvG[W, 0]) chi0_wGG[:, :, 0] = np.dot(d_v, chi0_wxvG[W, 1]) chi0_wGG[:, 0, 0] = np.dot(d_v, np.dot(chi0_wvv[W], d_v).T) G_G /= (4 * pi)**0.5 if self.truncation == 'wigner-seitz': kernel = WignerSeitzTruncatedCoulomb(pd.gd.cell_cv, self.chi0.calc.wfs.kd.N_c) K_G = kernel.get_potential(pd) K_G *= G_G**2 if pd.kd.gamma: K_G[0] = 0.0 elif self.truncation == '2D': K_G = truncated_coulomb(pd) K_G *= G_G**2 else: K_G = np.ones(nG) K_GG = np.zeros((nG, nG), dtype=complex) for i in range(nG): K_GG[i, i] = K_G[i] if xc != 'RPA': R_av = self.chi0.calc.atoms.positions / Bohr nt_sG = self.chi0.calc.density.nt_sG K_GG += calculate_Kxc(pd, nt_sG, R_av, self.chi0.calc.wfs.setups, self.chi0.calc.density.D_asp, functional=xc) * G_G * G_G[:, np.newaxis] chi_wGG = [] for chi0_GG in chi0_wGG: chi0_GG[:] = chi0_GG / G_G / G_G[:, np.newaxis] chi_wGG.append( np.dot(np.linalg.inv(np.eye(nG) - np.dot(chi0_GG, K_GG)), chi0_GG)) return chi0_wGG, np.array(chi_wGG)
def get_chi(self, xc='RPA', q_c=[0, 0, 0], direction='x'): """ Returns v^1/2 chi V^1/2""" pd, chi0_wGG, chi0_wxvG, chi0_wvv = self.calculate_chi0(q_c) G_G = pd.G2_qG[0]**0.5 nG = len(G_G) if pd.kd.gamma: G_G[0] = 1.0 if isinstance(direction, str): d_v = {'x': [1, 0, 0], 'y': [0, 1, 0], 'z': [0, 0, 1]}[direction] else: d_v = direction d_v = np.asarray(d_v) / np.linalg.norm(d_v) W = slice(self.w1, self.w2) chi0_wGG[:, 0] = np.dot(d_v, chi0_wxvG[W, 0]) chi0_wGG[:, :, 0] = np.dot(d_v, chi0_wxvG[W, 1]) chi0_wGG[:, 0, 0] = np.dot(d_v, np.dot(chi0_wvv[W], d_v).T) G_G /= (4 * pi)**0.5 if self.truncation == 'wigner-seitz': kernel = WignerSeitzTruncatedCoulomb(pd.gd.cell_cv, self.chi0.calc.wfs.kd.N_c) K_G = kernel.get_potential(pd) K_G *= G_G**2 if pd.kd.gamma: K_G[0] = 0.0 elif self.truncation == '2D': K_G = truncated_coulomb(pd) K_G *= G_G**2 else: K_G = np.ones(nG) K_GG = np.zeros((nG, nG), dtype=complex) for i in range(nG): K_GG[i, i] = K_G[i] if xc != 'RPA': R_av = self.chi0.calc.atoms.positions / Bohr nt_sG = self.chi0.calc.density.nt_sG K_GG += calculate_Kxc(pd, nt_sG, R_av, self.chi0.calc.wfs.setups, self.chi0.calc.density.D_asp, functional=xc) * G_G * G_G[:, np.newaxis] chi_wGG = [] for chi0_GG in chi0_wGG: chi0_GG[:] = chi0_GG / G_G / G_G[:, np.newaxis] chi_wGG.append(np.dot(np.linalg.inv(np.eye(nG) - np.dot(chi0_GG, K_GG)), chi0_GG)) return chi0_wGG, np.array(chi_wGG)
def get_dielectric_matrix(self, xc='RPA', q_c=[0, 0, 0], direction='x', symmetric=True, calculate_chi=False): """Returns the symmetrized dielectric matrix. :: \tilde\epsilon_GG' = v^{-1/2}_G \epsilon_GG' v^{1/2}_G', where:: epsilon_GG' = 1 - v_G * P_GG' and P_GG' is the polarization. :: In RPA: P = chi^0 In TDDFT: P = (1 - chi^0 * f_xc)^{-1} chi^0 The head of the inverse symmetrized dielectric matrix is equal to the head of the inverse dielectric matrix (inverse dielectric function) """ pd, chi0_wGG, chi0_wxvG, chi0_wvv = self.calculate_chi0(q_c) G_G = pd.G2_qG[0]**0.5 nG = len(G_G) if pd.kd.gamma: G_G[0] = 1.0 if isinstance(direction, str): d_v = {'x': [1, 0, 0], 'y': [0, 1, 0], 'z': [0, 0, 1]}[direction] else: d_v = direction d_v = np.asarray(d_v) / np.linalg.norm(d_v) W = slice(self.w1, self.w2) chi0_wGG[:, 0] = np.dot(d_v, chi0_wxvG[W, 0]) chi0_wGG[:, :, 0] = np.dot(d_v, chi0_wxvG[W, 1]) chi0_wGG[:, 0, 0] = np.dot(d_v, np.dot(chi0_wvv[W], d_v).T) if self.truncation == 'wigner-seitz': kernel = WignerSeitzTruncatedCoulomb(pd.gd.cell_cv, self.chi0.calc.wfs.kd.N_c) K_G = kernel.get_potential(pd)**0.5 if pd.kd.gamma: K_G[0] = 0.0 elif self.truncation == '2D': K_G = truncated_coulomb(pd) if pd.kd.gamma: K_G[0] = 0.0 else: K_G = (4 * pi)**0.5 / G_G if xc != 'RPA': R_av = self.chi0.calc.atoms.positions / Bohr nt_sG = self.chi0.calc.density.nt_sG Kxc_sGG = calculate_Kxc(pd, nt_sG, R_av, self.chi0.calc.wfs.setups, self.chi0.calc.density.D_asp, functional=xc) if calculate_chi: chi_wGG = [] for chi0_GG in chi0_wGG: if xc == 'RPA': P_GG = chi0_GG else: P_GG = np.dot(np.linalg.inv(np.eye(nG) - np.dot(chi0_GG, Kxc_sGG[0])), chi0_GG) if symmetric: e_GG = np.eye(nG) - P_GG * K_G * K_G[:, np.newaxis] else: K_GG = (K_G**2 * np.ones([nG, nG])).T e_GG = np.eye(nG) - P_GG * K_GG if calculate_chi: K_GG = np.diag(K_G**2) if xc != 'RPA': K_GG += Kxc_sGG[0] chi_wGG.append(np.dot(np.linalg.inv(np.eye(nG) - np.dot(chi0_GG, K_GG)), chi0_GG)) chi0_GG[:] = e_GG # chi0_wGG is now the dielectric matrix if not calculate_chi: return chi0_wGG else: return pd, chi0_wGG, chi_wGG
def get_dielectric_matrix(self, xc='RPA', q_c=[0, 0, 0], direction='x', symmetric=True, calculate_chi=False): """Returns the symmetrized dielectric matrix. :: \tilde\epsilon_GG' = v^{-1/2}_G \epsilon_GG' v^{1/2}_G', where:: epsilon_GG' = 1 - v_G * P_GG' and P_GG' is the polarization. :: In RPA: P = chi^0 In TDDFT: P = (1 - chi^0 * f_xc)^{-1} chi^0 The head of the inverse symmetrized dielectric matrix is equal to the head of the inverse dielectric matrix (inverse dielectric function) """ pd, chi0_wGG, chi0_wxvG, chi0_wvv = self.calculate_chi0(q_c) G_G = pd.G2_qG[0]**0.5 nG = len(G_G) if pd.kd.gamma: G_G[0] = 1.0 if isinstance(direction, str): d_v = { 'x': [1, 0, 0], 'y': [0, 1, 0], 'z': [0, 0, 1] }[direction] else: d_v = direction d_v = np.asarray(d_v) / np.linalg.norm(d_v) W = slice(self.w1, self.w2) chi0_wGG[:, 0] = np.dot(d_v, chi0_wxvG[W, 0]) chi0_wGG[:, :, 0] = np.dot(d_v, chi0_wxvG[W, 1]) chi0_wGG[:, 0, 0] = np.dot(d_v, np.dot(chi0_wvv[W], d_v).T) if self.truncation == 'wigner-seitz': kernel = WignerSeitzTruncatedCoulomb(pd.gd.cell_cv, self.chi0.calc.wfs.kd.N_c) K_G = kernel.get_potential(pd)**0.5 if pd.kd.gamma: K_G[0] = 0.0 elif self.truncation == '2D': K_G = truncated_coulomb(pd) if pd.kd.gamma: K_G[0] = 0.0 else: K_G = (4 * pi)**0.5 / G_G if xc != 'RPA': R_av = self.chi0.calc.atoms.positions / Bohr nt_sG = self.chi0.calc.density.nt_sG Kxc_sGG = calculate_Kxc(pd, nt_sG, R_av, self.chi0.calc.wfs.setups, self.chi0.calc.density.D_asp, functional=xc) if calculate_chi: chi_wGG = [] for chi0_GG in chi0_wGG: if xc == 'RPA': P_GG = chi0_GG else: P_GG = np.dot( np.linalg.inv(np.eye(nG) - np.dot(chi0_GG, Kxc_sGG[0])), chi0_GG) if symmetric: e_GG = np.eye(nG) - P_GG * K_G * K_G[:, np.newaxis] else: K_GG = (K_G**2 * np.ones([nG, nG])).T e_GG = np.eye(nG) - P_GG * K_GG if calculate_chi: K_GG = np.diag(K_G**2) if xc != 'RPA': K_GG += Kxc_sGG[0] chi_wGG.append( np.dot(np.linalg.inv(np.eye(nG) - np.dot(chi0_GG, K_GG)), chi0_GG)) chi0_GG[:] = e_GG # chi0_wGG is now the dielectric matrix if not calculate_chi: return chi0_wGG else: return pd, chi0_wGG, chi_wGG