def par_save(self, filename, name, A_sS): from gpaw.io import open nS = self.nS if rank == 0: w = open(filename, 'w', world) w.dimension('nS', nS) if name == 'v_SS': w.add('w_S', ('nS', ), dtype=self.w_S.dtype) w.fill(self.w_S) w.add('rhoG0_S', ('nS', ), dtype=complex) w.fill(self.rhoG0_S) w.add(name, ('nS', 'nS'), dtype=complex) tmp = np.zeros_like(A_sS) # Assumes that H_SS is written in order from rank 0 - rank N for irank in range(size): if irank == 0: if rank == 0: w.fill(A_sS) else: if rank == irank: world.send(A_sS, 0, irank + 100) if rank == 0: world.receive(tmp, irank, irank + 100) w.fill(tmp) if rank == 0: w.close() world.barrier()
def par_save(self,filename, name, A_sS): from gpaw.io import open nS_local = self.nS_local nS = self.nS if rank == 0: w = open(filename, 'w', world) w.dimension('nS', nS) if name == 'v_SS': w.add('w_S', ('nS',), dtype=self.w_S.dtype) w.fill(self.w_S) w.add('rhoG0_S', ('nS',), dtype=complex) w.fill(self.rhoG0_S) w.add(name, ('nS', 'nS'), dtype=complex) tmp = np.zeros_like(A_sS) # Assumes that H_SS is written in order from rank 0 - rank N for irank in range(size): if irank == 0: if rank == 0: w.fill(A_sS) else: if rank == irank: world.send(A_sS, 0, irank+100) if rank == 0: world.receive(tmp, irank, irank+100) w.fill(tmp) if rank == 0: w.close() world.barrier()
def par_write(filename, name, comm, chi0_wGG): ## support only world communicator at the moment from gpaw.mpi import rank, size, world from gpaw.io import open assert comm.size == size assert comm.rank == rank Nw_local, npw, npw1 = chi0_wGG.shape assert npw == npw1 Nw = Nw_local * size if rank == 0: w = open(filename, 'w', comm) w.dimension('Nw', Nw) w.dimension('npw', npw) w.add(name, ('Nw', 'npw', 'npw'), dtype=complex) tmp = np.zeros_like(chi0_wGG[0]) for iw in range(Nw): irank = iw // Nw_local if irank == 0: if rank == 0: w.fill(chi0_wGG[iw]) else: if rank == irank: world.send(chi0_wGG[iw - rank * Nw_local], 0, irank + 100) if rank == 0: world.receive(tmp, irank, irank + 100) w.fill(tmp) if rank == 0: w.close() world.barrier()
def par_write(filename, name, comm, chi0_wGG): ## support only world communicator at the moment from gpaw.mpi import rank, size, world from gpaw.io import open assert comm.size == size assert comm.rank == rank Nw_local, npw, npw1 = chi0_wGG.shape assert npw == npw1 Nw = Nw_local * size w = open(filename, 'w', comm) w.dimension('Nw', Nw) w.dimension('npw', npw) w.add(name, ('Nw', 'npw', 'npw'), dtype=complex) if rank == 0: tmp = np.zeros_like(chi0_wGG[0]) for iw in range(Nw): irank = iw // Nw_local if irank == 0: if rank == 0: w.fill(chi0_wGG[iw]) else: if rank == irank: world.send(chi0_wGG[iw-rank*Nw_local], 0, irank+100) if rank == 0: world.receive(tmp, irank, irank+100) w.fill(tmp) if rank == 0: w.close() world.barrier()
def load(self, filename): data = pickle.load(open(filename)) self.w_S = data['w_S'] self.v_SS = data['v_SS'] self.printtxt('Read succesfully !')
def full_static_screened_interaction(self): """Calcuate W_GG(q)""" W_qGG = np.zeros((self.nibzq, self.npw, self.npw), dtype=complex) t0 = time() for iq in range(self.nibzq): q = self.ibzq_qc[iq] optical_limit = False if np.abs(q).sum() < 1e-8: q = self.q_c.copy() optical_limit = True df = DF(calc=self.calc, q=q, w=(0., ), optical_limit=optical_limit, nbands=self.nbands, hilbert_trans=False, eta=0.0001, ecut=self.ecut * Hartree, xc='RPA', txt='df.out') df.initialize() df.calculate() if optical_limit: K_GG = self.V_qGG[iq].copy() K0 = calculate_Kc(q, self.Gvec_Gc, self.acell_cv, self.bcell_cv, self.pbc, vcut=self.vcut)[0, 0] for iG in range(1, self.npw): K_GG[0, iG] = self.V_qGG[iq, iG, iG]**0.5 * K0**0.5 K_GG[iG, 0] = self.V_qGG[iq, iG, iG]**0.5 * K0**0.5 K_GG[0, 0] = K0 df_GG = np.eye(self.npw, self.npw) - K_GG * df.chi0_wGG[0] else: df_GG = np.eye(self.npw, self.npw) - self.V_qGG[iq] * df.chi0_wGG[0] dfinv_GG = np.linalg.inv(df_GG) if optical_limit: eps = 1 / dfinv_GG[0, 0] self.printtxt( ' RPA macroscopic dielectric constant is: %3.3f' % eps.real) W_qGG[iq] = dfinv_GG * self.V_qGG[iq] self.timing(iq, t0, self.nibzq, 'iq') if rank == 0: if self.kernel_file is not None: data = {'W_qGG': W_qGG} name = self.kernel_file + '.pckl' pickle.dump(data, open(name, 'w'), -1) return W_qGG
def save(self, filename): """Dump essential data""" data = {'w_S': self.w_S, 'v_SS': self.v_SS} if rank == 0: pickle.dump(data, open(filename, 'w'), -1) world.barrier()
def full_static_screened_interaction(self): """Calcuate W_GG(q)""" W_qGG = np.zeros((self.nibzq, self.npw, self.npw), dtype=complex) t0 = time() for iq in range(self.nibzq): q = self.ibzq_qc[iq] optical_limit = False if np.abs(q).sum() < 1e-8: q = self.q_c.copy() optical_limit = True df = DF(calc=self.calc, q=q, w=(0.,), optical_limit=optical_limit, nbands=self.nbands, hilbert_trans=False, eta=0.0001, ecut=self.ecut*Hartree, xc='RPA', txt='df.out') df.initialize() df.calculate() if optical_limit: K_GG = self.V_qGG[iq].copy() q_v = np.dot(q, self.bcell_cv) K0 = calculate_Kc(q, self.Gvec_Gc, self.acell_cv, self.bcell_cv, self.pbc, vcut=self.vcut)[0,0] for iG in range(1,self.npw): K_GG[0, iG] = self.V_qGG[iq, iG, iG]**0.5 * K0**0.5 K_GG[iG, 0] = self.V_qGG[iq, iG, iG]**0.5 * K0**0.5 K_GG[0,0] = K0 df_GG = np.eye(self.npw, self.npw) - K_GG*df.chi0_wGG[0] else: df_GG = np.eye(self.npw, self.npw) - self.V_qGG[iq]*df.chi0_wGG[0] dfinv_GG = np.linalg.inv(df_GG) if optical_limit: eps = 1/dfinv_GG[0,0] self.printtxt(' RPA macroscopic dielectric constant is: %3.3f' % eps.real) W_qGG[iq] = dfinv_GG * self.V_qGG[iq] self.timing(iq, t0, self.nibzq, 'iq') if rank == 0: if self.kernel_file is not None: data = {'W_qGG': W_qGG} name = self.kernel_file+'.pckl' pickle.dump(data, open(name, 'w'), -1) return W_qGG
def save(self, filename): """Dump essential data""" data = {'w_S' : self.w_S, 'v_SS' : self.v_SS} if rank == 0: pickle.dump(data, open(filename, 'w'), -1) world.barrier()
def par_read(filename, name, Nw=None): r = open(filename, 'r') if Nw is None: Nw = r.dimension('Nw') else: assert Nw <= r.dimension('Nw') npw = r.dimension('npw') Nw_local = Nw // size chi0_wGG = np.zeros((Nw_local, npw, npw), dtype=complex) for iw in range(Nw_local): chi0_wGG[iw] = r.get(name, iw + rank * Nw_local) r.close() return chi0_wGG
def par_read(filename, name, Nw=None): r = open(filename, 'r') if Nw is None: Nw = r.dimension('Nw') else: assert Nw <= r.dimension('Nw') npw = r.dimension('npw') Nw_local = Nw // size chi0_wGG = np.zeros((Nw_local, npw, npw), dtype=complex) for iw in range(Nw_local): chi0_wGG[iw] = r.get(name, iw+rank*Nw_local) r.close() return chi0_wGG
def par_load(self,filename, name): from gpaw.io import open r = open(filename, 'r') nS = r.dimension('nS') if name == 'v_SS': self.w_S = r.get('w_S') A_SS = np.zeros((self.nS_local, nS), dtype=complex) for iS in range(self.nS_start, self.nS_end): A_SS[iS-self.nS_start,:] = r.get(name, iS) self.rhoG0_S = r.get('rhoG0_S') r.close() return A_SS
def par_load(self, filename, name): from gpaw.io import open r = open(filename, 'r') nS = r.dimension('nS') if name == 'v_SS': self.w_S = r.get('w_S') A_SS = np.zeros((self.nS_local, nS), dtype=complex) for iS in range(self.nS_start, self.nS_end): A_SS[iS - self.nS_start, :] = r.get(name, iS) self.rhoG0_S = r.get('rhoG0_S') r.close() return A_SS
def get_dielectric_function(self, filename='df.dat', readfile=None): if self.epsilon_w is None: self.initialize() if readfile is None: H_sS = self.calculate() self.printtxt('Diagonalizing %s matrix.' % self.mode) self.diagonalize(H_sS) self.printtxt('Calculating dielectric function.') elif readfile == 'H_SS': H_sS = self.par_load('H_SS', 'H_SS') self.printtxt('Finished reading H_SS.gpw') self.diagonalize(H_sS) self.printtxt('Finished diagonalizing BSE matrix') elif readfile == 'v_SS': self.v_SS = self.par_load('v_SS', 'v_SS') self.printtxt('Finished reading v_SS.gpw') else: XX w_S = self.w_S if not self.coupling: v_SS = self.v_SS.T # v_SS[:,lamda] else: v_SS = self.v_SS rhoG0_S = self.rhoG0_S focc_S = self.focc_S # get overlap matrix if self.coupling: tmp = np.dot(v_SS.conj().T, v_SS ) overlap_SS = np.linalg.inv(tmp) # get chi epsilon_w = np.zeros(self.Nw, dtype=complex) t0 = time() A_S = np.dot(rhoG0_S, v_SS) B_S = np.dot(rhoG0_S*focc_S, v_SS) if self.coupling: C_S = np.dot(B_S.conj(), overlap_SS.T) * A_S else: if world.size == 1: C_S = B_S.conj() * A_S else: tmp = B_S.conj() * A_S C_S = gatherv(tmp, self.nS) for iw in range(self.Nw): tmp_S = 1. / (iw*self.dw - w_S + 1j*self.eta) epsilon_w[iw] += np.dot(tmp_S, C_S) epsilon_w *= - 4 * pi / np.inner(self.qq_v, self.qq_v) / self.vol epsilon_w += 1 self.epsilon_w = epsilon_w if rank == 0: f = open(filename,'w') #g = open('excitons.dat', 'w') for iw in range(self.Nw): energy = iw * self.dw * Hartree print >> f, energy, np.real(epsilon_w[iw]), np.imag(epsilon_w[iw]) #print >> g, energy, np.real(C_S[iw])/max(abs(C_S)) f.close() #g.close() # Wait for I/O to finish world.barrier() """Check f-sum rule.""" N1 = 0 for iw in range(self.Nw): w = iw * self.dw N1 += np.imag(epsilon_w[iw]) * w N1 *= self.dw * self.vol / (2 * pi**2) self.printtxt('') self.printtxt('Sum rule:') nv = self.nvalence self.printtxt('N1 = %f, %f %% error' %(N1, (N1 - nv) / nv * 100) ) return epsilon_w
def calculate(self): calc = self.calc focc_S = self.focc_S e_S = self.e_S op_scc = calc.wfs.kd.symmetry.op_scc # Get phi_qaGp if self.mode == 'RPA': self.phi_aGp = self.get_phi_aGp() else: fd = opencew('phi_qaGp') if fd is None: self.reader = Reader('phi_qaGp') tmp = self.load_phi_aGp(self.reader, 0)[0] assert len(tmp) == self.npw self.printtxt('Finished reading phi_aGp') else: self.printtxt('Calculating phi_qaGp') self.get_phi_qaGp() world.barrier() self.reader = Reader('phi_qaGp') self.printtxt('Memory used %f M' % (maxrss() / 1024.**2)) self.printtxt('') if self.optical_limit: iq = np.where(np.sum(abs(self.ibzq_qc), axis=1) < 1e-5)[0][0] else: iq = np.where( np.sum(abs(self.ibzq_qc - self.q_c), axis=1) < 1e-5)[0][0] kc_G = np.array([self.V_qGG[iq, iG, iG] for iG in range(self.npw)]) if self.optical_limit: kc_G[0] = 0. # Get screened Coulomb kernel if self.mode == 'BSE': try: # Read data = pickle.load(open(self.kernel_file + '.pckl')) W_qGG = data['W_qGG'] assert np.shape(W_qGG) == np.shape(self.V_qGG) self.printtxt('Finished reading screening interaction kernel') except: # Calculate from scratch self.printtxt('Calculating screening interaction kernel.') W_qGG = self.full_static_screened_interaction() self.printtxt('') else: W_qGG = self.V_qGG t0 = time() self.printtxt('Calculating %s matrix elements' % self.mode) # Calculate full kernel K_SS = np.zeros((self.nS_local, self.nS), dtype=complex) self.rhoG0_S = np.zeros(self.nS, dtype=complex) #noGmap = 0 for iS in range(self.nS_start, self.nS_end): k1, n1, m1 = self.Sindex_S3[iS] rho1_G = self.density_matrix(n1, m1, k1) self.rhoG0_S[iS] = rho1_G[0] for jS in range(self.nS): k2, n2, m2 = self.Sindex_S3[jS] rho2_G = self.density_matrix(n2, m2, k2) K_SS[iS - self.nS_start, jS] = np.sum(rho1_G.conj() * rho2_G * kc_G) if not self.mode == 'RPA': rho3_G = self.density_matrix(n1, n2, k1, k2) rho4_G = self.density_matrix(m1, m2, self.kq_k[k1], self.kq_k[k2]) q_c = self.kd.bzk_kc[k2] - self.kd.bzk_kc[k1] q_c[np.where(q_c > 0.501)] -= 1. q_c[np.where(q_c < -0.499)] += 1. iq = self.kd.where_is_q(q_c, self.bzq_qc) if not self.qsymm: W_GG = W_qGG[iq] else: ibzq = self.ibzq_q[iq] W_GG_tmp = W_qGG[ibzq] iop = self.iop_q[iq] timerev = self.timerev_q[iq] diff_c = self.diff_qc[iq] invop = np.linalg.inv(op_scc[iop]) Gindex = np.zeros(self.npw, dtype=int) for iG in range(self.npw): G_c = self.Gvec_Gc[iG] if timerev: RotG_c = -np.int8( np.dot(invop, G_c + diff_c).round()) else: RotG_c = np.int8( np.dot(invop, G_c + diff_c).round()) tmp_G = np.abs(self.Gvec_Gc - RotG_c).sum(axis=1) try: Gindex[iG] = np.where(tmp_G < 1e-5)[0][0] except: #noGmap += 1 Gindex[iG] = -1 W_GG = np.zeros_like(W_GG_tmp) for iG in range(self.npw): for jG in range(self.npw): if Gindex[iG] == -1 or Gindex[jG] == -1: W_GG[iG, jG] = 0 else: W_GG[iG, jG] = W_GG_tmp[Gindex[iG], Gindex[jG]] if self.mode == 'BSE': tmp_GG = np.outer(rho3_G.conj(), rho4_G) * W_GG K_SS[iS - self.nS_start, jS] -= 0.5 * np.sum(tmp_GG) else: tmp_G = rho3_G.conj() * rho4_G * np.diag(W_GG) K_SS[iS - self.nS_start, jS] -= 0.5 * np.sum(tmp_G) self.timing(iS, t0, self.nS_local, 'pair orbital') K_SS /= self.vol world.sum(self.rhoG0_S) #self.printtxt('Number of G indices outside the Gvec_Gc: %d' % noGmap) # Get and solve Hamiltonian H_sS = np.zeros_like(K_SS) for iS in range(self.nS_start, self.nS_end): H_sS[iS - self.nS_start, iS] = e_S[iS] for jS in range(self.nS): H_sS[iS - self.nS_start, jS] += focc_S[iS] * K_SS[iS - self.nS_start, jS] # Force matrix to be Hermitian if not self.coupling: if world.size > 1: H_Ss = self.redistribute_H(H_sS) else: H_Ss = H_sS H_sS = (np.real(H_sS) + np.real(H_Ss.T)) / 2. + 1j * ( np.imag(H_sS) - np.imag(H_Ss.T)) / 2. # Save H_sS matrix self.par_save('H_SS', 'H_SS', H_sS) return H_sS
def calculate(self): calc = self.calc f_skn = self.f_skn e_skn = self.e_skn kq_k = self.kq_k focc_S = self.focc_S e_S = self.e_S op_scc = calc.wfs.symmetry.op_scc # Get phi_qaGp if self.mode == 'RPA': self.phi_aGp = self.get_phi_aGp() else: try: self.reader = Reader('phi_qaGp') tmp = self.load_phi_aGp(self.reader, 0)[0] assert len(tmp) == self.npw self.printtxt('Finished reading phi_aGp') except: self.printtxt('Calculating phi_qaGp') self.get_phi_qaGp() world.barrier() self.reader = Reader('phi_qaGp') self.printtxt('Memory used %f M' % (maxrss() / 1024.**2)) self.printtxt('') if self.optical_limit: iq = np.where(np.sum(abs(self.ibzq_qc), axis=1) < 1e-5)[0][0] else: iq = np.where(np.sum(abs(self.ibzq_qc - self.q_c), axis=1) < 1e-5)[0][0] kc_G = np.array([self.V_qGG[iq, iG, iG] for iG in range(self.npw)]) if self.optical_limit: kc_G[0] = 0. # Get screened Coulomb kernel if self.mode == 'BSE': try: # Read data = pickle.load(open(self.kernel_file+'.pckl')) W_qGG = data['W_qGG'] assert np.shape(W_qGG) == np.shape(self.V_qGG) self.printtxt('Finished reading screening interaction kernel') except: # Calculate from scratch self.printtxt('Calculating screening interaction kernel.') W_qGG = self.full_static_screened_interaction() self.printtxt('') else: W_qGG = self.V_qGG t0 = time() self.printtxt('Calculating %s matrix elements' % self.mode) # Calculate full kernel K_SS = np.zeros((self.nS_local, self.nS), dtype=complex) self.rhoG0_S = np.zeros(self.nS, dtype=complex) #noGmap = 0 for iS in range(self.nS_start, self.nS_end): k1, n1, m1 = self.Sindex_S3[iS] rho1_G = self.density_matrix(n1,m1,k1) self.rhoG0_S[iS] = rho1_G[0] for jS in range(self.nS): k2, n2, m2 = self.Sindex_S3[jS] rho2_G = self.density_matrix(n2,m2,k2) K_SS[iS-self.nS_start, jS] = np.sum(rho1_G.conj() * rho2_G * kc_G) if not self.mode == 'RPA': rho3_G = self.density_matrix(n1,n2,k1,k2) rho4_G = self.density_matrix(m1,m2,self.kq_k[k1], self.kq_k[k2]) q_c = self.kd.bzk_kc[k2] - self.kd.bzk_kc[k1] q_c[np.where(q_c > 0.501)] -= 1. q_c[np.where(q_c < -0.499)] += 1. iq = self.kd.where_is_q(q_c, self.bzq_qc) if not self.qsymm: W_GG = W_qGG[iq] else: ibzq = self.ibzq_q[iq] W_GG_tmp = W_qGG[ibzq] iop = self.iop_q[iq] timerev = self.timerev_q[iq] diff_c = self.diff_qc[iq] invop = np.linalg.inv(op_scc[iop]) Gindex = np.zeros(self.npw, dtype=int) for iG in range(self.npw): G_c = self.Gvec_Gc[iG] if timerev: RotG_c = -np.int8(np.dot(invop, G_c+diff_c).round()) else: RotG_c = np.int8(np.dot(invop, G_c+diff_c).round()) tmp_G = np.abs(self.Gvec_Gc - RotG_c).sum(axis=1) try: Gindex[iG] = np.where(tmp_G < 1e-5)[0][0] except: #noGmap += 1 Gindex[iG] = -1 W_GG = np.zeros_like(W_GG_tmp) for iG in range(self.npw): for jG in range(self.npw): if Gindex[iG] == -1 or Gindex[jG] == -1: W_GG[iG, jG] = 0 else: W_GG[iG, jG] = W_GG_tmp[Gindex[iG], Gindex[jG]] if self.mode == 'BSE': tmp_GG = np.outer(rho3_G.conj(), rho4_G) * W_GG K_SS[iS-self.nS_start, jS] -= 0.5 * np.sum(tmp_GG) else: tmp_G = rho3_G.conj() * rho4_G * np.diag(W_GG) K_SS[iS-self.nS_start, jS] -= 0.5 * np.sum(tmp_G) self.timing(iS, t0, self.nS_local, 'pair orbital') K_SS /= self.vol world.sum(self.rhoG0_S) #self.printtxt('Number of G indices outside the Gvec_Gc: %d' % noGmap) # Get and solve Hamiltonian H_sS = np.zeros_like(K_SS) for iS in range(self.nS_start, self.nS_end): H_sS[iS-self.nS_start,iS] = e_S[iS] for jS in range(self.nS): H_sS[iS-self.nS_start,jS] += focc_S[iS] * K_SS[iS-self.nS_start,jS] # Force matrix to be Hermitian if not self.coupling: if world.size > 1: H_Ss = self.redistribute_H(H_sS) else: H_Ss = H_sS H_sS = (np.real(H_sS) + np.real(H_Ss.T)) / 2. + 1j * (np.imag(H_sS) - np.imag(H_Ss.T)) /2. # Save H_sS matrix self.par_save('H_SS','H_SS', H_sS) return H_sS
def get_dielectric_function(self, filename='df.dat', readfile=None): if self.epsilon_w is None: self.initialize() if readfile is None: H_sS = self.calculate() self.printtxt('Diagonalizing %s matrix.' % self.mode) self.diagonalize(H_sS) self.printtxt('Calculating dielectric function.') elif readfile == 'H_SS': H_sS = self.par_load('H_SS', 'H_SS') self.printtxt('Finished reading H_SS.gpw') self.diagonalize(H_sS) self.printtxt('Finished diagonalizing BSE matrix') elif readfile == 'v_SS': self.v_SS = self.par_load('v_SS', 'v_SS') self.printtxt('Finished reading v_SS.gpw') else: 1 / 0 w_S = self.w_S if not self.coupling: v_SS = self.v_SS.T # v_SS[:,lamda] else: v_SS = self.v_SS rhoG0_S = self.rhoG0_S focc_S = self.focc_S # get overlap matrix if self.coupling: tmp = np.dot(v_SS.conj().T, v_SS) overlap_SS = np.linalg.inv(tmp) # get chi epsilon_w = np.zeros(self.Nw, dtype=complex) A_S = np.dot(rhoG0_S, v_SS) B_S = np.dot(rhoG0_S * focc_S, v_SS) if self.coupling: C_S = np.dot(B_S.conj(), overlap_SS.T) * A_S else: if world.size == 1: C_S = B_S.conj() * A_S else: tmp = B_S.conj() * A_S C_S = gatherv(tmp, self.nS) for iw in range(self.Nw): tmp_S = 1. / (iw * self.dw - w_S + 1j * self.eta) epsilon_w[iw] += np.dot(tmp_S, C_S) epsilon_w *= -4 * pi / np.inner(self.qq_v, self.qq_v) / self.vol epsilon_w += 1 self.epsilon_w = epsilon_w if rank == 0: f = open(filename, 'w') for iw in range(self.Nw): energy = iw * self.dw * Hartree print(energy, np.real(epsilon_w[iw]), np.imag(epsilon_w[iw]), file=f) f.close() #g.close() # Wait for I/O to finish world.barrier() """Check f-sum rule.""" N1 = 0 for iw in range(self.Nw): w = iw * self.dw N1 += np.imag(epsilon_w[iw]) * w N1 *= self.dw * self.vol / (2 * pi**2) self.printtxt('') self.printtxt('Sum rule:') nv = self.nvalence self.printtxt('N1 = %f, %f %% error' % (N1, (N1 - nv) / nv * 100)) return epsilon_w