def initialize(self): self.printtxt('') self.printtxt('-----------------------------------------------') self.printtxt('Belth Selpeter Equation calculation started at:') self.printtxt(ctime()) BASECHI.initialize(self) calc = self.calc self.kd = kd = calc.wfs.kd # frequency points init 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.Nw = int(self.wmax / self.dw) + 1 # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j) self.e_S = {} focc_s = {} self.Sindex_S3 = {} iS = 0 kq_k = self.kq_k for k1 in range(self.nkpt): ibzkpt1 = kd.kibz_k[k1] ibzkpt2 = kd.kibz_k[kq_k[k1]] for n1 in range(self.nbands): for m1 in range(self.nbands): focc = self.f_kn[ibzkpt1, n1] - self.f_kn[ibzkpt2, m1] if np.abs(focc) > self.ftol: self.e_S[iS] = self.e_kn[ibzkpt2, m1] - self.e_kn[ibzkpt1, n1] focc_s[iS] = focc self.Sindex_S3[iS] = (k1, n1, m1) iS += 1 self.nS = iS self.focc_S = np.zeros(self.nS) for iS in range(self.nS): self.focc_S[iS] = focc_s[iS] # parallel init self.Scomm = world # kcomm and wScomm is only to be used when wavefunctions r parallelly distributed. self.kcomm = world self.wScomm = serial_comm self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition( self.nS, self.Scomm.rank, self.Scomm.size, reshape=False) self.print_bse() self.get_phi_aGp() # Coulomb kernel init self.kc_G = np.zeros(self.npw) for iG in range(self.npw): index = self.Gindex_G[iG] qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv) self.kc_G[iG] = 1. / np.inner(qG, qG) if self.optical_limit: self.kc_G[0] = 0. 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.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.ini = True BASECHI.initialize(self) self.txtname = self.gwtxtname self.output_init() self.printtxt('GPAW version %s' % (version)) self.printtxt('-----------------------------------------------') self.printtxt('GW calculation started at:') self.printtxt(ctime()) self.printtxt('-----------------------------------------------') self.starttime = time() calc = self.calc kd = self.kd # band init if self.gwnbands is None: if self.npw > calc.wfs.bd.nbands: self.nbands = calc.wfs.bd.nbands else: self.nbands = self.npw # eigenvalue init if self.user_skn is not None: self.printtxt('Use eigenvalues from user.') assert np.shape( self.user_skn )[0] == self.nspins, 'Eigenvalues not compatible with .gpw file!' assert np.shape( self.user_skn )[1] == self.kd.nibzkpts, 'Eigenvalues not compatible with .gpw file!' assert np.shape( self.user_skn)[2] >= self.nbands, 'Too few eigenvalues!' self.e_skn = self.user_skn else: self.printtxt('Use eigenvalues from the calculator.') # q point init self.bzq_kc = kd.get_bz_q_points() self.ibzq_qc = self.bzq_kc # q point symmetry is not used at the moment. self.nqpt = np.shape(self.bzq_kc)[0] # frequency points init self.static = False if self.ppa: # Plasmon Pole Approximation if self.E0 is None: self.E0 = Hartree self.E0 /= Hartree self.w_w = np.array([0., 1j * self.E0]) self.hilbert_trans = False self.wpar = 1 elif self.w_w is None: # static COHSEX self.w_w = np.array([0.]) self.static = True self.hilbert_trans = False self.wpar = 1 self.eta = 0.0001 / Hartree else: # create nonlinear frequency grid # grid is linear from 0 to wcut with spacing dw # spacing is linearily increasing between wcut and wmax # Hilbert transforms are still carried out on linear grid wcut = self.w_w[0] wmax = self.w_w[1] dw = self.w_w[2] w_w = np.linspace(0., wcut, wcut / dw + 1) i = 1 wi = wcut while wi < wmax: wi += i * dw w_w = np.append(w_w, wi) i += 1 while len(w_w) % self.wpar != 0: wi += i * dw w_w = np.append(w_w, wi) i += 1 dw_w = np.zeros(len(w_w)) dw_w[0] = dw dw_w[1:] = w_w[1:] - w_w[:-1] self.w_w = w_w / Hartree self.dw_w = dw_w / Hartree self.eta_w = dw_w * 4 / Hartree self.wcut = wcut self.wmax = self.w_w[-1] self.wmin = self.w_w[0] self.dw = self.w_w[1] - self.w_w[0] self.Nw = len(self.w_w) # self.wpar = int(self.Nw * self.npw**2 * 16. / 1024**2) // 1500 + 1 # estimate memory and parallelize over frequencies for s in range(self.nspins): emaxdiff = self.e_skn[s][:, self.nbands - 1].max() - self.e_skn[s][:, 0].min() assert (self.wmax > emaxdiff ), 'Maximum frequency must be larger than %f' % ( emaxdiff * Hartree) # GW kpoints init if self.kpoints is None: self.gwnkpt = self.kd.nibzkpts self.gwkpt_k = kd.ibz2bz_k else: self.gwnkpt = np.shape(self.kpoints)[0] self.gwkpt_k = self.kpoints # GW bands init if self.bands is None: self.gwnband = self.nbands self.bands = self.gwbands_n = np.arange(self.nbands) else: self.gwnband = np.shape(self.bands)[0] self.gwbands_n = self.bands self.alpha = 1j / (2 * pi * self.vol * self.kd.nbzkpts) # parallel init assert len(self.w_w) % self.wpar == 0 self.wcommsize = self.wpar self.qcommsize = size // self.wpar assert self.qcommsize * self.wcommsize == size, 'wpar must be integer divisor of number of requested cores' if self.nqpt != 1: # parallelize over q-points self.wcomm, self.qcomm, self.worldcomm = set_communicator( world, rank, size, self.wpar) self.ncomm = serial_comm self.dfcomm = self.wcomm self.kcommsize = 1 else: # parallelize over bands self.wcomm, self.ncomm, self.worldcomm = set_communicator( world, rank, size, self.wpar) self.qcomm = serial_comm if self.wpar > 1: self.dfcomm = self.wcomm self.kcommsize = 1 else: self.dfcomm = self.ncomm self.kcommsize = self.ncomm.size nq, self.nq_local, self.q_start, self.q_end = parallel_partition( self.nqpt, self.qcomm.rank, self.qcomm.size, reshape=False) nb, self.nbands_local, self.m_start, self.m_end = parallel_partition( self.nbands, self.ncomm.rank, self.ncomm.size, reshape=False)
def initialize(self): self.ini = True BASECHI.initialize(self) self.txtname = self.gwtxtname self.output_init() self.printtxt('GPAW version %s' %(version)) self.printtxt('-----------------------------------------------') self.printtxt('GW calculation started at:') self.printtxt(ctime()) self.printtxt('-----------------------------------------------') self.starttime = time() calc = self.calc kd = self.kd # band init if self.gwnbands is None: if self.npw > calc.wfs.bd.nbands: self.nbands = calc.wfs.bd.nbands else: self.nbands = self.npw # eigenvalue init if self.user_skn is not None: self.printtxt('Use eigenvalues from user.') assert np.shape(self.user_skn)[0] == self.nspins, 'Eigenvalues not compatible with .gpw file!' assert np.shape(self.user_skn)[1] == self.kd.nibzkpts, 'Eigenvalues not compatible with .gpw file!' assert np.shape(self.user_skn)[2] >= self.nbands, 'Too few eigenvalues!' self.e_skn = self.user_skn else: self.printtxt('Use eigenvalues from the calculator.') # q point init self.bzq_kc = kd.get_bz_q_points() self.ibzq_qc = self.bzq_kc # q point symmetry is not used at the moment. self.nqpt = np.shape(self.bzq_kc)[0] # frequency points init self.static=False if self.ppa: # Plasmon Pole Approximation if self.E0 is None: self.E0 = Hartree self.E0 /= Hartree self.w_w = np.array([0., 1j*self.E0]) self.hilbert_trans=False self.wpar=1 elif self.w_w is None: # static COHSEX self.w_w = np.array([0.]) self.static=True self.hilbert_trans=False self.wpar=1 self.eta = 0.0001 / Hartree else: # create nonlinear frequency grid # grid is linear from 0 to wcut with spacing dw # spacing is linearily increasing between wcut and wmax # Hilbert transforms are still carried out on linear grid wcut = self.w_w[0] wmax = self.w_w[1] dw = self.w_w[2] w_w = np.linspace(0., wcut, wcut/dw+1) i=1 wi=wcut while wi < wmax: wi += i*dw w_w = np.append(w_w, wi) i+=1 while len(w_w) % self.wpar != 0: wi += i*dw w_w = np.append(w_w, wi) i+=1 dw_w = np.zeros(len(w_w)) dw_w[0] = dw dw_w[1:] = w_w[1:] - w_w[:-1] self.w_w = w_w / Hartree self.dw_w = dw_w / Hartree self.eta_w = dw_w * 4 / Hartree self.wcut = wcut self.wmax = self.w_w[-1] self.wmin = self.w_w[0] self.dw = self.w_w[1] - self.w_w[0] self.Nw = len(self.w_w) # self.wpar = int(self.Nw * self.npw**2 * 16. / 1024**2) // 1500 + 1 # estimate memory and parallelize over frequencies for s in range(self.nspins): emaxdiff = self.e_skn[s][:,self.nbands-1].max() - self.e_skn[s][:,0].min() assert (self.wmax > emaxdiff), 'Maximum frequency must be larger than %f' %(emaxdiff*Hartree) # GW kpoints init if self.kpoints is None: self.gwnkpt = self.kd.nibzkpts self.gwkpt_k = kd.ibz2bz_k else: self.gwnkpt = np.shape(self.kpoints)[0] self.gwkpt_k = self.kpoints # GW bands init if self.bands is None: self.gwnband = self.nbands self.bands = self.gwbands_n = np.arange(self.nbands) else: self.gwnband = np.shape(self.bands)[0] self.gwbands_n = self.bands self.alpha = 1j/(2*pi * self.vol * self.kd.nbzkpts) # parallel init assert len(self.w_w) % self.wpar == 0 self.wcommsize = self.wpar self.qcommsize = size // self.wpar assert self.qcommsize * self.wcommsize == size, 'wpar must be integer divisor of number of requested cores' if self.nqpt != 1: # parallelize over q-points self.wcomm, self.qcomm, self.worldcomm = set_communicator(world, rank, size, self.wpar) self.ncomm = serial_comm self.dfcomm = self.wcomm self.kcommsize = 1 else: # parallelize over bands self.wcomm, self.ncomm, self.worldcomm = set_communicator(world, rank, size, self.wpar) self.qcomm = serial_comm if self.wpar > 1: self.dfcomm = self.wcomm self.kcommsize = 1 else: self.dfcomm = self.ncomm self.kcommsize = self.ncomm.size nq, self.nq_local, self.q_start, self.q_end = parallel_partition( self.nqpt, self.qcomm.rank, self.qcomm.size, reshape=False) nb, self.nbands_local, self.m_start, self.m_end = parallel_partition( self.nbands, self.ncomm.rank, self.ncomm.size, reshape=False)
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 initialize(self): self.printtxt('') self.printtxt('-----------------------------------------------') self.printtxt('Belth Selpeter Equation calculation started at:') self.printtxt(ctime()) BASECHI.initialize(self) calc = self.calc self.kd = kd = calc.wfs.kd # frequency points init 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.Nw = int(self.wmax / self.dw) + 1 # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j) self.e_S = {} focc_s = {} self.Sindex_S3 = {} iS = 0 kq_k = self.kq_k for k1 in range(self.nkpt): ibzkpt1 = kd.kibz_k[k1] ibzkpt2 = kd.kibz_k[kq_k[k1]] for n1 in range(self.nbands): for m1 in range(self.nbands): focc = self.f_kn[ibzkpt1,n1] - self.f_kn[ibzkpt2,m1] if np.abs(focc) > self.ftol: self.e_S[iS] =self.e_kn[ibzkpt2,m1] - self.e_kn[ibzkpt1,n1] focc_s[iS] = focc self.Sindex_S3[iS] = (k1, n1, m1) iS += 1 self.nS = iS self.focc_S = np.zeros(self.nS) for iS in range(self.nS): self.focc_S[iS] = focc_s[iS] # parallel init self.Scomm = world # kcomm and wScomm is only to be used when wavefunctions r parallelly distributed. self.kcomm = world self.wScomm = serial_comm self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition( self.nS, self.Scomm.rank, self.Scomm.size, reshape=False) self.print_bse() self.get_phi_aGp() # Coulomb kernel init self.kc_G = np.zeros(self.npw) for iG in range(self.npw): index = self.Gindex_G[iG] qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv) self.kc_G[iG] = 1. / np.inner(qG, qG) if self.optical_limit: self.kc_G[0] = 0. self.printtxt('') return
def initialize(self): self.printtxt('----------------------------------------') self.printtxt('Bethe-Salpeter Equation calculation') self.printtxt('----------------------------------------') self.printtxt('Started at: %s' % ctime()) self.printtxt('') BASECHI.initialize(self) assert self.nspins == 1 calc = self.calc self.kd = kd = calc.wfs.kd # frequency points init 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.Nw = int(self.wmax / self.dw) + 1 # band init if self.nc is None: nv = self.nvalence / 2 - 1 self.nv = np.array([nv, nv+1]) # conduction band start / end self.nc = np.array([nv+1, nv+2]) # valence band start / end self.printtxt('') self.printtxt('Number of electrons : %d' % (self.nvalence)) self.printtxt('Valence band included : (band %d to band %d)' %(self.nv[0], self.nv[1]-1)) self.printtxt('Conduction band included : (band %d to band %d)' %(self.nc[0], self.nc[1]-1)) if self.eshift is not None: self.printtxt('Scissors operator : %2.3f eV' % self.eshift) self.printtxt('') # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j) self.e_S = {} focc_s = {} self.Sindex_S3 = {} iS = 0 kq_k = self.kq_k for k1 in range(self.kd.nbzkpts): ibzkpt1 = kd.bz2ibz_k[k1] ibzkpt2 = kd.bz2ibz_k[kq_k[k1]] for n1 in range(self.nv[0], self.nv[1]): for m1 in range(self.nc[0], self.nc[1]): focc = self.f_skn[0][ibzkpt1,n1] - self.f_skn[0][ibzkpt2,m1] if self.coupling: # Dont use Tamm-Dancoff Approx. check_ftol = np.abs(focc) > self.ftol else: check_ftol = focc > self.ftol if check_ftol: if self.gw_skn is None: self.e_S[iS] = self.e_skn[0][ibzkpt2,m1] - self.e_skn[0][ibzkpt1,n1] else: self.e_S[iS] = self.gw_skn[0][ibzkpt2,m1] - self.gw_skn[0][ibzkpt1,n1] focc_s[iS] = focc self.Sindex_S3[iS] = (k1, n1, m1) iS += 1 self.nS = iS self.focc_S = np.zeros(self.nS) for iS in range(self.nS): self.focc_S[iS] = focc_s[iS] # q points init self.bzq_qc = kd.get_bz_q_points() if not self.qsymm: self.ibzq_qc = self.bzq_qc else: (self.ibzq_qc, self.ibzq_q, self.iop_q, self.timerev_q, self.diff_qc) = kd.get_ibz_q_points(self.bzq_qc, calc.wfs.symmetry.op_scc) if np.abs(self.bzq_qc - kd.bzk_kc).sum() < 1e-8: assert np.abs(self.ibzq_qc - kd.ibzk_kc).sum() < 1e-8 self.nibzq = len(self.ibzq_qc) # Parallel initialization # kcomm and wScomm is only to be used when wavefunctions are distributed in parallel. self.comm = self.Scomm = world self.kcomm = world self.wScomm = serial_comm self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition( self.nS, world.rank, world.size, reshape=False) self.print_bse() if calc.input_parameters['mode'] == 'lcao': calc.initialize_positions() # Coulomb interaction at q=0 for Hartree coupling ### 2D z direction only !!!!!!!!!!!!!!!!!!!!!! if self.integrate_coulomb is None: self.integrate_coulomb = [] if self.vcut is None: pass elif self.vcut == '2D': for iG in range(len(self.Gvec_Gc)): if self.Gvec_Gc[iG, 0] == 0 and self.Gvec_Gc[iG, 1] == 0: self.integrate_coulomb.append(iG) else: raise NotImplementedError elif type(self.integrate_coulomb) is int: self.integrate_coulomb = range(self.integrate_coulomb) elif self.integrate_coulomb == 'all': self.integrate_coulomb = range(len(self.Gvec_Gc)) elif type(self.integrate_coulomb) is list: pass else: raise 'Invalid option for integrate_coulomb' self.printtxt('') self.printtxt('Calculating bare Coulomb kernel') if not len(self.integrate_coulomb) == 0: self.printtxt('Integrating Coulomb kernel at %s reciprocal lattice vector(s)' % len(self.integrate_coulomb)) # Coulomb interaction at problematic G's for exchange coupling if len(self.integrate_coulomb) != 0: self.vint_Gq = [] for iG in self.integrate_coulomb: v_q, v0_q = calculate_Kc_q(self.acell_cv, self.bcell_cv, self.pbc, self.kd.N_c, vcut=self.vcut, Gvec_c=self.Gvec_Gc[iG], q_qc=self.ibzq_qc.copy()) self.vint_Gq.append(v_q) if self.print_coulomb: self.printtxt('') self.printtxt('Average kernel relative to bare kernel - \int v(q)dq / v(q0): ') self.printtxt(' G: % s' % self.Gvec_Gc[iG]) for iq in range(len(v_q)): q_s = ' q = [%1.2f, %1.2f, %1.2f]: ' % (self.ibzq_qc[iq,0], self.ibzq_qc[iq,1], self.ibzq_qc[iq,2]) v_rel = v_q[iq] / v0_q[iq] self.printtxt(q_s + '%1.3f' % v_rel) self.printtxt('') self.V_qGG = self.full_bare_interaction() return
def initialize(self): self.printtxt('----------------------------------------') self.printtxt('Bethe-Salpeter Equation calculation') self.printtxt('----------------------------------------') self.printtxt('Started at: %s' % ctime()) self.printtxt('') BASECHI.initialize(self) assert self.nspins == 1 calc = self.calc self.kd = kd = calc.wfs.kd # frequency points init 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.Nw = int(self.wmax / self.dw) + 1 # band init if self.nc is None: nv = self.nvalence / 2 - 1 self.nv = np.array([nv, nv + 1]) # conduction band start / end self.nc = np.array([nv + 1, nv + 2]) # valence band start / end self.printtxt('') self.printtxt('Number of electrons : %d' % (self.nvalence)) self.printtxt('Valence band included : (band %d to band %d)' % (self.nv[0], self.nv[1] - 1)) self.printtxt('Conduction band included : (band %d to band %d)' % (self.nc[0], self.nc[1] - 1)) if self.eshift is not None: self.printtxt('Scissors operator : %2.3f eV' % self.eshift) self.printtxt('') # find the pair index and initialized pair energy (e_i - e_j) and occupation(f_i-f_j) self.e_S = {} focc_s = {} self.Sindex_S3 = {} iS = 0 kq_k = self.kq_k for k1 in range(self.kd.nbzkpts): ibzkpt1 = kd.bz2ibz_k[k1] ibzkpt2 = kd.bz2ibz_k[kq_k[k1]] for n1 in range(self.nv[0], self.nv[1]): for m1 in range(self.nc[0], self.nc[1]): focc = self.f_skn[0][ibzkpt1, n1] - self.f_skn[0][ibzkpt2, m1] if self.coupling: # Dont use Tamm-Dancoff Approx. check_ftol = np.abs(focc) > self.ftol else: check_ftol = focc > self.ftol if check_ftol: if self.gw_skn is None: self.e_S[iS] = self.e_skn[0][ ibzkpt2, m1] - self.e_skn[0][ibzkpt1, n1] else: self.e_S[iS] = self.gw_skn[0][ ibzkpt2, m1] - self.gw_skn[0][ibzkpt1, n1] focc_s[iS] = focc self.Sindex_S3[iS] = (k1, n1, m1) iS += 1 self.nS = iS self.focc_S = np.zeros(self.nS) for iS in range(self.nS): self.focc_S[iS] = focc_s[iS] # q points init self.bzq_qc = kd.get_bz_q_points() if not self.qsymm: self.ibzq_qc = self.bzq_qc else: (self.ibzq_qc, self.ibzq_q, self.iop_q, self.timerev_q, self.diff_qc) = kd.get_ibz_q_points(self.bzq_qc, calc.wfs.kd.symmetry.op_scc) if np.abs(self.bzq_qc - kd.bzk_kc).sum() < 1e-8: assert np.abs(self.ibzq_qc - kd.ibzk_kc).sum() < 1e-8 self.nibzq = len(self.ibzq_qc) # Parallel initialization # kcomm and wScomm is only to be used when wavefunctions are distributed in parallel. self.comm = self.Scomm = world self.kcomm = world self.wScomm = serial_comm self.nS, self.nS_local, self.nS_start, self.nS_end = parallel_partition( self.nS, world.rank, world.size, reshape=False) self.print_bse() if calc.input_parameters['mode'] == 'lcao': calc.initialize_positions() # Coulomb interaction at q=0 for Hartree coupling ### 2D z direction only !!!!!!!!!!!!!!!!!!!!!! if self.integrate_coulomb is None: self.integrate_coulomb = [] if self.vcut is None: pass elif self.vcut == '2D': for iG in range(len(self.Gvec_Gc)): if self.Gvec_Gc[iG, 0] == 0 and self.Gvec_Gc[iG, 1] == 0: self.integrate_coulomb.append(iG) else: raise NotImplementedError elif type(self.integrate_coulomb) is int: self.integrate_coulomb = range(self.integrate_coulomb) elif self.integrate_coulomb == 'all': self.integrate_coulomb = range(len(self.Gvec_Gc)) elif type(self.integrate_coulomb) is list: pass else: raise 'Invalid option for integrate_coulomb' self.printtxt('') self.printtxt('Calculating bare Coulomb kernel') if not len(self.integrate_coulomb) == 0: self.printtxt( 'Integrating Coulomb kernel at %s reciprocal lattice vector(s)' % len(self.integrate_coulomb)) # Coulomb interaction at problematic G's for exchange coupling if len(self.integrate_coulomb) != 0: self.vint_Gq = [] for iG in self.integrate_coulomb: v_q, v0_q = calculate_Kc_q(self.acell_cv, self.bcell_cv, self.pbc, self.kd.N_c, vcut=self.vcut, Gvec_c=self.Gvec_Gc[iG], q_qc=self.ibzq_qc.copy()) self.vint_Gq.append(v_q) if self.print_coulomb: self.printtxt('') self.printtxt( 'Average kernel relative to bare kernel - \int v(q)dq / v(q0): ' ) self.printtxt(' G: % s' % self.Gvec_Gc[iG]) for iq in range(len(v_q)): q_s = ' q = [%1.2f, %1.2f, %1.2f]: ' % ( self.ibzq_qc[iq, 0], self.ibzq_qc[iq, 1], self.ibzq_qc[iq, 2]) v_rel = v_q[iq] / v0_q[iq] self.printtxt(q_s + '%1.3f' % v_rel) self.printtxt('') self.V_qGG = self.full_bare_interaction()
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