def get_dielectric_matrix(self, xc='RPA', overwritechi0=False, symmetric=True, chi0_wGG=None, calc=None, vcut=None, dir=None): if self.chi0_wGG is None and chi0_wGG is None: self.initialize() self.calculate() elif self.chi0_wGG is None and chi0_wGG is not None: #Read from file and reinitialize self.xc = xc from gpaw.response.parallel import par_read self.chi0_wGG = par_read(chi0_wGG, 'chi0_wGG') self.nvalbands = self.nbands #self.parallel_init() # parallelization not yet implemented self.Nw_local = self.Nw # parallelization not yet implemented if self.calc is None: from gpaw import GPAW self.calc = GPAW(calc,txt=None) if self.xc == 'ALDA' or self.xc == 'ALDA_X': from gpaw.response.kernel import calculate_Kxc from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world, rank, size, serial_comm self.pbc = self.calc.atoms.pbc self.gd = GridDescriptor(self.calc.wfs.gd.N_c*self.rpad, self.acell_cv, pbc_c=True, comm=serial_comm) R_av = self.calc.atoms.positions / Bohr nt_sg = self.calc.density.nt_sG if (self.rpad > 1).any() or (self.pbc - True).any(): nt_sG = self.gd.zeros(self.nspins) #nt_sG = np.zeros([self.nspins, self.nG[0], self.nG[1], self.nG[2]]) for s in range(self.nspins): nt_G = self.pad(nt_sg[s]) nt_sG[s] = nt_G else: nt_sG = nt_sg self.Kxc_sGG = calculate_Kxc(self.gd, nt_sG, self.npw, self.Gvec_Gc, self.gd.N_c, self.vol, self.bcell_cv, R_av, self.calc.wfs.setups, self.calc.density.D_asp, functional=self.xc, density_cut=self.density_cut) if overwritechi0: dm_wGG = self.chi0_wGG else: dm_wGG = np.zeros_like(self.chi0_wGG) if dir is None: q_c = self.q_c else: q_c = np.diag((1,1,1))[dir] * self.qopt self.chi0_wGG[:,0,:] = self.chi00G_wGv[:,:,dir] self.chi0_wGG[:,:,0] = self.chi0G0_wGv[:,:,dir] from gpaw.response.kernel import calculate_Kc, CoulombKernel kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv) self.Kc_GG = kernel.calculate_Kc(q_c, self.Gvec_Gc, self.bcell_cv, symmetric=symmetric) #self.Kc_GG = calculate_Kc(q_c, # self.Gvec_Gc, # self.acell_cv, # self.bcell_cv, # self.pbc, # self.vcut, # symmetric=symmetric) tmp_GG = np.eye(self.npw, self.npw) if xc == 'RPA': self.printtxt('Use RPA.') for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * self.chi0_wGG[iw] elif xc == 'ALDA': self.printtxt('Use ALDA kernel.') # E_LDA = 1 - v_c chi0 (1-fxc chi0)^-1 # http://prb.aps.org/pdf/PRB/v33/i10/p7017_1 eq. 4 A_wGG = self.chi0_wGG.copy() for iw in range(self.Nw_local): A_wGG[iw] = np.dot(self.chi0_wGG[iw], np.linalg.inv(tmp_GG - np.dot(self.Kxc_sGG[0], self.chi0_wGG[iw]))) for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * A_wGG[iw] return dm_wGG
def initialize(self, simple_version=False): self.printtxt("") self.printtxt("-----------------------------------------") self.printtxt("Response function calculation started at:") self.starttime = time() self.printtxt(ctime()) BASECHI.initialize(self) # Frequency init self.dw = None if len(self.w_w) == 1: self.hilbert_trans = False if self.hilbert_trans: self.dw = self.w_w[1] - self.w_w[0] # assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid assert self.w_w.max() == self.w_w[-1] self.dw /= Hartree self.w_w /= Hartree self.wmax = self.w_w[-1] self.wcut = self.wmax + 5.0 / Hartree # self.Nw = int(self.wmax / self.dw) + 1 self.Nw = len(self.w_w) self.NwS = int(self.wcut / self.dw) + 1 else: self.Nw = len(self.w_w) self.NwS = 0 if len(self.w_w) > 2: self.dw = self.w_w[1] - self.w_w[0] assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() self.dw /= Hartree self.nvalbands = self.nbands tmpn = np.zeros(self.nspins, dtype=int) for spin in range(self.nspins): for n in range(self.nbands): if (self.f_skn[spin][:, n] - self.ftol < 0).all(): tmpn[spin] = n break if tmpn.max() > 0: self.nvalbands = tmpn.max() # Parallelization initialize self.parallel_init() # Printing calculation information self.print_chi() if extra_parameters.get("df_dry_run"): raise SystemExit calc = self.calc # For LCAO wfs if calc.input_parameters["mode"] == "lcao": calc.initialize_positions() self.printtxt(" Max mem sofar : %f M / cpu" % (maxrss() / 1024 ** 2)) if simple_version is True: return # PAW part init # calculate <phi_i | e**(-i(q+G).r) | phi_j> # G != 0 part self.phi_aGp, self.phiG0_avp = self.get_phi_aGp(alldir=True) self.printtxt("Finished phi_aGp !") mem = np.array([self.phi_aGp[i].size * 16 / 1024.0 ** 2 for i in range(len(self.phi_aGp))]) self.printtxt(" Phi_aGp : %f M / cpu" % (mem.sum())) # Calculate ALDA kernel (not used in chi0) R_av = calc.atoms.positions / Bohr if self.xc == "RPA": # type(self.w_w[0]) is float: self.Kc_GG = None self.printtxt("RPA calculation.") elif self.xc == "ALDA" or self.xc == "ALDA_X": # self.Kc_GG = calculate_Kc(self.q_c, # self.Gvec_Gc, # self.acell_cv, # self.bcell_cv, # self.calc.atoms.pbc, # self.vcut) # Initialize a CoulombKernel instance kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv) self.Kc_GG = kernel.calculate_Kc(self.q_c, self.Gvec_Gc, self.bcell_cv) self.Kxc_sGG = calculate_Kxc( self.gd, # global grid self.gd.zero_pad(calc.density.nt_sG), self.npw, self.Gvec_Gc, self.gd.N_c, self.vol, self.bcell_cv, R_av, calc.wfs.setups, calc.density.D_asp, functional=self.xc, density_cut=self.density_cut, ) self.printtxt("Finished %s kernel ! " % self.xc) return
def initialize(self): self.printtxt('') self.printtxt('-----------------------------------------') self.printtxt('Response function calculation started at:') self.starttime = time() self.printtxt(ctime()) BASECHI.initialize(self) # Frequency init self.dw = None if len(self.w_w) == 1: self.HilberTrans = False if self.hilbert_trans: self.dw = self.w_w[1] - self.w_w[0] assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid assert self.w_w.max() == self.w_w[-1] self.dw /= Hartree self.w_w /= Hartree self.wmax = self.w_w[-1] self.wcut = self.wmax + 5. / Hartree self.Nw = int(self.wmax / self.dw) + 1 self.NwS = int(self.wcut / self.dw) + 1 else: self.Nw = len(self.w_w) self.NwS = 0 if len(self.w_w) > 1: self.dw = self.w_w[1] - self.w_w[0] assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() self.dw /= Hartree if self.hilbert_trans: # for band parallelization. for n in range(self.nbands): if (self.f_kn[:, n] - self.ftol < 0).all(): self.nvalbands = n break else: # if not hilbert transform, all the bands should be used. self.nvalbands = self.nbands # Parallelization initialize self.parallel_init() # Printing calculation information self.print_chi() if extra_parameters.get('df_dry_run'): raise SystemExit calc = self.calc # For LCAO wfs if calc.input_parameters['mode'] == 'lcao': calc.initialize_positions() self.printtxt(' GS calculator : %f M / cpu' %(maxrss() / 1024**2)) # PAW part init # calculate <phi_i | e**(-i(q+G).r) | phi_j> # G != 0 part self.get_phi_aGp() # Calculate ALDA kernel for EELS spectrum # Use RPA kernel for Optical spectrum and rpa correlation energy if not self.optical_limit and np.dtype(self.w_w[0]) == float: R_av = calc.atoms.positions / Bohr self.Kxc_GG = calculate_Kxc(self.gd, # global grid calc.density.nt_sG, self.npw, self.Gvec_Gc, self.nG, self.vol, self.bcell_cv, R_av, calc.wfs.setups, calc.density.D_asp) self.printtxt('Finished ALDA kernel ! ') else: self.Kxc_GG = np.zeros((self.npw, self.npw)) self.printtxt('Use RPA for optical spectrum ! ') self.printtxt('') return
def initialize(self, simple_version=False): self.printtxt('') self.printtxt('-----------------------------------------') self.printtxt('Response function calculation started at:') self.starttime = time() self.printtxt(ctime()) BASECHI.initialize(self) # Frequency init self.dw = None if len(self.w_w) == 1: self.hilbert_trans = False if self.hilbert_trans: self.dw = self.w_w[1] - self.w_w[0] # assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid assert self.w_w.max() == self.w_w[-1] self.dw /= Hartree self.w_w /= Hartree self.wmax = self.w_w[-1] self.wcut = self.wmax + 5. / Hartree # self.Nw = int(self.wmax / self.dw) + 1 self.Nw = len(self.w_w) self.NwS = int(self.wcut / self.dw) + 1 else: self.Nw = len(self.w_w) self.NwS = 0 if len(self.w_w) > 2: self.dw = self.w_w[1] - self.w_w[0] assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() self.dw /= Hartree self.nvalbands = self.nbands tmpn = np.zeros(self.nspins, dtype=int) for spin in range(self.nspins): for n in range(self.nbands): if (self.f_skn[spin][:, n] - self.ftol < 0).all(): tmpn[spin] = n break if tmpn.max() > 0: self.nvalbands = tmpn.max() # Parallelization initialize self.parallel_init() # Printing calculation information self.print_chi() if extra_parameters.get('df_dry_run'): raise SystemExit calc = self.calc # For LCAO wfs if calc.input_parameters['mode'] == 'lcao': calc.initialize_positions() self.printtxt(' Max mem sofar : %f M / cpu' %(maxrss() / 1024**2)) if simple_version is True: return # PAW part init # calculate <phi_i | e**(-i(q+G).r) | phi_j> # G != 0 part self.phi_aGp, self.phiG0_avp = self.get_phi_aGp(alldir=True) self.printtxt('Finished phi_aGp !') mem = np.array([self.phi_aGp[i].size * 16 /1024.**2 for i in range(len(self.phi_aGp))]) self.printtxt(' Phi_aGp : %f M / cpu' %(mem.sum())) # Calculate ALDA kernel (not used in chi0) R_av = calc.atoms.positions / Bohr if self.xc == 'RPA': #type(self.w_w[0]) is float: self.Kc_GG = None self.printtxt('RPA calculation.') elif self.xc == 'ALDA' or self.xc == 'ALDA_X': #self.Kc_GG = calculate_Kc(self.q_c, # self.Gvec_Gc, # self.acell_cv, # self.bcell_cv, # self.calc.atoms.pbc, # self.vcut) # Initialize a CoulombKernel instance kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv) self.Kc_GG = kernel.calculate_Kc(self.q_c, self.Gvec_Gc, self.bcell_cv) self.Kxc_sGG = calculate_Kxc(self.gd, # global grid self.gd.zero_pad(calc.density.nt_sG), self.npw, self.Gvec_Gc, self.gd.N_c, self.vol, self.bcell_cv, R_av, calc.wfs.setups, calc.density.D_asp, functional=self.xc, density_cut=self.density_cut) self.printtxt('Finished %s kernel ! ' % self.xc) return
def get_dielectric_matrix(self, xc='RPA', overwritechi0=False, symmetric=True, chi0_wGG=None, calc=None, vcut=None, dir=None): if self.chi0_wGG is None and chi0_wGG is None: self.initialize() self.calculate() elif self.chi0_wGG is None and chi0_wGG is not None: #Read from file and reinitialize self.xc = xc from gpaw.response.parallel import par_read self.chi0_wGG = par_read(chi0_wGG, 'chi0_wGG') self.nvalbands = self.nbands #self.parallel_init() # parallelization not yet implemented self.Nw_local = self.Nw # parallelization not yet implemented if self.calc is None: from gpaw import GPAW self.calc = GPAW(calc, txt=None) if self.xc == 'ALDA' or self.xc == 'ALDA_X': from gpaw.response.kernel import calculate_Kxc from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world, rank, size, serial_comm self.pbc = self.calc.atoms.pbc self.gd = GridDescriptor(self.calc.wfs.gd.N_c * self.rpad, self.acell_cv, pbc_c=True, comm=serial_comm) R_av = self.calc.atoms.positions / Bohr nt_sg = self.calc.density.nt_sG if (self.rpad > 1).any() or (self.pbc - True).any(): nt_sG = self.gd.zeros(self.nspins) #nt_sG = np.zeros([self.nspins, self.nG[0], self.nG[1], self.nG[2]]) for s in range(self.nspins): nt_G = self.pad(nt_sg[s]) nt_sG[s] = nt_G else: nt_sG = nt_sg self.Kxc_sGG = calculate_Kxc(self.gd, nt_sG, self.npw, self.Gvec_Gc, self.gd.N_c, self.vol, self.bcell_cv, R_av, self.calc.wfs.setups, self.calc.density.D_asp, functional=self.xc, density_cut=self.density_cut) if overwritechi0: dm_wGG = self.chi0_wGG else: dm_wGG = np.zeros_like(self.chi0_wGG) if dir is None: q_c = self.q_c else: q_c = np.diag((1, 1, 1))[dir] * self.qopt self.chi0_wGG[:, 0, :] = self.chi00G_wGv[:, :, dir] self.chi0_wGG[:, :, 0] = self.chi0G0_wGv[:, :, dir] from gpaw.response.kernel import calculate_Kc, CoulombKernel kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv) self.Kc_GG = kernel.calculate_Kc(q_c, self.Gvec_Gc, self.bcell_cv, symmetric=symmetric) #self.Kc_GG = calculate_Kc(q_c, # self.Gvec_Gc, # self.acell_cv, # self.bcell_cv, # self.pbc, # self.vcut, # symmetric=symmetric) tmp_GG = np.eye(self.npw, self.npw) if xc == 'RPA': self.printtxt('Use RPA.') for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * self.chi0_wGG[iw] elif xc == 'ALDA': self.printtxt('Use ALDA kernel.') # E_LDA = 1 - v_c chi0 (1-fxc chi0)^-1 # http://prb.aps.org/pdf/PRB/v33/i10/p7017_1 eq. 4 A_wGG = self.chi0_wGG.copy() for iw in range(self.Nw_local): A_wGG[iw] = np.dot( self.chi0_wGG[iw], np.linalg.inv(tmp_GG - np.dot(self.Kxc_sGG[0], self.chi0_wGG[iw]))) for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * A_wGG[iw] return dm_wGG
def initialize(self): self.printtxt('') self.printtxt('-----------------------------------------') self.printtxt('Response function calculation started at:') self.starttime = time() self.printtxt(ctime()) BASECHI.initialize(self) # Frequency init self.dw = None if len(self.w_w) == 1: self.HilberTrans = False if self.hilbert_trans: self.dw = self.w_w[1] - self.w_w[0] assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() # make sure its linear w grid assert self.w_w.max() == self.w_w[-1] self.dw /= Hartree self.w_w /= Hartree self.wmax = self.w_w[-1] self.wcut = self.wmax + 5. / Hartree self.Nw = int(self.wmax / self.dw) + 1 self.NwS = int(self.wcut / self.dw) + 1 else: self.Nw = len(self.w_w) self.NwS = 0 if len(self.w_w) > 1: self.dw = self.w_w[1] - self.w_w[0] assert ((self.w_w[1:] - self.w_w[:-1] - self.dw) < 1e-10).all() self.dw /= Hartree if self.hilbert_trans: # for band parallelization. for n in range(self.nbands): if (self.f_kn[:, n] - self.ftol < 0).all(): self.nvalbands = n break else: # if not hilbert transform, all the bands should be used. self.nvalbands = self.nbands # Parallelization initialize self.parallel_init() # Printing calculation information self.print_chi() if extra_parameters.get('df_dry_run'): raise SystemExit calc = self.calc # For LCAO wfs if calc.input_parameters['mode'] == 'lcao': calc.initialize_positions() self.printtxt(' GS calculator : %f M / cpu' % (maxrss() / 1024**2)) # PAW part init # calculate <phi_i | e**(-i(q+G).r) | phi_j> # G != 0 part self.get_phi_aGp() # Calculate ALDA kernel for EELS spectrum # Use RPA kernel for Optical spectrum and rpa correlation energy if not self.optical_limit and np.dtype(self.w_w[0]) == float: R_av = calc.atoms.positions / Bohr self.Kxc_GG = calculate_Kxc( self.gd, # global grid calc.density.nt_sG, self.npw, self.Gvec_Gc, self.nG, self.vol, self.bcell_cv, R_av, calc.wfs.setups, calc.density.D_asp) self.printtxt('Finished ALDA kernel ! ') else: self.Kxc_GG = np.zeros((self.npw, self.npw)) self.printtxt('Use RPA for optical spectrum ! ') self.printtxt('') return