def init_potential(self): #initialization of nonlocal part of pseudopotential # V_NL=|chi_i> V_i <chi_i| spline_aj = [] for setup in self.wfs.setups: spline_aj.append(setup.pt_j) self.lfc = PWLFC(spline_aj, self.pd) self.lfc.set_positions(self.calc.spos_ac) #set position of atoms proj_G = [] proj_r = [] #collect chi_i in real space using FFT for kpt in self.wfs.kpt_u: proj_G.append(self.lfc.expand(kpt.q)) proj = [] n_i = proj_G[-1].shape[1] for i in range(n_i): proj.append(self.pd.ifft(proj_G[-1][:, i].copy(), kpt.q)) proj_r.append(proj) self.chi = np.array(proj_r) / self.gd.dv s = 0 # s=0 because we perform spin-paired calculation V = [] #collect V for a in range(len(self.wfs.setups)): dH_ii = unpack(self.ham.dH_asp[a][s]) V.append(dH_ii.diagonal()) V = np.array(V) self.V = V.ravel() self.norb = self.V.size # number of orbitals in nonlocal potential #initialization of local part of pseudopotential V = self.ham.vbar.pd.zeros() self.ham.vbar.add(V) self.Vloc = self.ham.vbar.pd.ifft(V)
def initialize_paw_corrections(self, pd, soft=False): wfs = self.calc.wfs q_v = pd.K_qv[0] optical_limit = np.allclose(q_v, 0) G_Gv = pd.get_reciprocal_vectors() if optical_limit: G_Gv[0] = 1 pos_av = np.dot(self.spos_ac, pd.gd.cell_cv) # Collect integrals for all species: Q_xGii = {} for id, atomdata in wfs.setups.setups.items(): if soft: ghat = PWLFC([atomdata.ghat_l], pd) ghat.set_positions(np.zeros((1, 3))) Q_LG = ghat.expand() Q_Gii = np.dot(atomdata.Delta_iiL, Q_LG).T else: Q_Gii = two_phi_planewave_integrals(G_Gv, atomdata) ni = atomdata.ni Q_Gii.shape = (-1, ni, ni) Q_xGii[id] = Q_Gii Q_aGii = [] for a, atomdata in enumerate(wfs.setups): id = wfs.setups.id_a[a] Q_Gii = Q_xGii[id] x_G = np.exp(-1j * np.dot(G_Gv, pos_av[a])) Q_aGii.append(x_G[:, np.newaxis, np.newaxis] * Q_Gii) if optical_limit: Q_aGii[a][0] = atomdata.dO_ii return Q_aGii
def calculate_exx(self): """Non-selfconsistent calculation.""" self.timer.start('EXX') self.timer.start('Initialization') kd = self.kd wfs = self.wfs if fftw.FFTPlan is fftw.NumpyFFTPlan: self.log('NOT USING FFTW !!') self.log('Spins:', self.wfs.nspins) W = max(1, self.wfs.kd.comm.size // self.wfs.nspins) # Are the k-points distributed? kparallel = (W > 1) # Find number of occupied bands: self.nocc_sk = np.zeros((self.wfs.nspins, kd.nibzkpts), int) for kpt in self.wfs.kpt_u: for n, f in enumerate(kpt.f_n): if abs(f) < self.fcut: self.nocc_sk[kpt.s, kpt.k] = n break else: self.nocc_sk[kpt.s, kpt.k] = self.wfs.bd.nbands self.wfs.kd.comm.sum(self.nocc_sk) noccmin = self.nocc_sk.min() noccmax = self.nocc_sk.max() self.log('Number of occupied bands (min, max): %d, %d' % (noccmin, noccmax)) self.log('Number of valence electrons:', self.wfs.setups.nvalence) if self.bandstructure: self.log('Calculating eigenvalue shifts.') # allocate array for eigenvalue shifts: self.exx_skn = np.zeros( (self.wfs.nspins, kd.nibzkpts, self.wfs.bd.nbands)) if self.bands is None: noccmax = self.wfs.bd.nbands else: noccmax = max(max(self.bands) + 1, noccmax) N_c = self.kd.N_c vol = wfs.gd.dv * wfs.gd.N_c.prod() if self.alpha is None: alpha = 6 * vol**(2 / 3.0) / pi**2 else: alpha = self.alpha if self.gamma_point == 1: if alpha == 0.0: qvol = (2 * np.pi)**3 / vol / N_c.prod() self.gamma = 4 * np.pi * (3 * qvol / (4 * np.pi))**(1 / 3.) / qvol else: self.gamma = self.calculate_gamma(vol, alpha) else: kcell_cv = wfs.gd.cell_cv.copy() kcell_cv[0] *= N_c[0] kcell_cv[1] *= N_c[1] kcell_cv[2] *= N_c[2] self.gamma = madelung(kcell_cv) * vol * N_c.prod() / (4 * np.pi) self.log('Value of alpha parameter: %.3f Bohr^2' % alpha) self.log('Value of gamma parameter: %.3f Bohr^2' % self.gamma) # Construct all possible q=k2-k1 vectors: Nq_c = (N_c - 1) // self.qstride_c i_qc = np.indices(Nq_c * 2 + 1, float).transpose((1, 2, 3, 0)).reshape( (-1, 3)) self.bzq_qc = (i_qc - Nq_c) / N_c * self.qstride_c self.q0 = ((Nq_c * 2 + 1).prod() - 1) // 2 # index of q=(0,0,0) assert not self.bzq_qc[self.q0].any() # Count number of pairs for each q-vector: self.npairs_q = np.zeros(len(self.bzq_qc), int) for s in range(kd.nspins): for k1 in range(kd.nibzkpts): for k2 in range(kd.nibzkpts): for K2, q, n1_n, n2 in self.indices(s, k1, k2): self.npairs_q[q] += len(n1_n) self.npairs0 = self.npairs_q.sum() # total number of pairs self.log('Number of pairs:', self.npairs0) # Distribute q-vectors to Q processors: Q = self.world.size // self.wfs.kd.comm.size myrank = self.world.rank // self.wfs.kd.comm.size rank = 0 N = 0 myq = [] nq = 0 for q, n in enumerate(self.npairs_q): if n > 0: nq += 1 if rank == myrank: myq.append(q) N += n if N >= (rank + 1.0) * self.npairs0 / Q: rank += 1 assert len(myq) > 0, 'Too few q-vectors for too many processes!' self.bzq_qc = self.bzq_qc[myq] try: self.q0 = myq.index(self.q0) except ValueError: self.q0 = None self.log('%d x %d x %d k-points' % tuple(self.kd.N_c)) self.log('Distributing %d IBZ k-points over %d process(es).' % (kd.nibzkpts, self.wfs.kd.comm.size)) self.log('Distributing %d q-vectors over %d process(es).' % (nq, Q)) # q-point descriptor for my q-vectors: qd = KPointDescriptor(self.bzq_qc) # Plane-wave descriptor for all wave-functions: self.pd = PWDescriptor(wfs.pd.ecut, wfs.gd, dtype=wfs.pd.dtype, kd=kd) # Plane-wave descriptor pair-densities: self.pd2 = PWDescriptor(self.dens.pd2.ecut, self.dens.gd, dtype=wfs.dtype, kd=qd) self.log('Cutoff energies:') self.log(' Wave functions: %10.3f eV' % (self.pd.ecut * Hartree)) self.log(' Density: %10.3f eV' % (self.pd2.ecut * Hartree)) # Calculate 1/|G+q|^2 with special treatment of |G+q|=0: G2_qG = self.pd2.G2_qG if self.q0 is None: if self.omega is None: self.iG2_qG = [1.0 / G2_G for G2_G in G2_qG] else: self.iG2_qG = [ (1.0 / G2_G * (1 - np.exp(-G2_G / (4 * self.omega**2)))) for G2_G in G2_qG ] else: G2_qG[self.q0][0] = 117.0 # avoid division by zero if self.omega is None: self.iG2_qG = [1.0 / G2_G for G2_G in G2_qG] self.iG2_qG[self.q0][0] = self.gamma else: self.iG2_qG = [ (1.0 / G2_G * (1 - np.exp(-G2_G / (4 * self.omega**2)))) for G2_G in G2_qG ] self.iG2_qG[self.q0][0] = 1 / (4 * self.omega**2) G2_qG[self.q0][0] = 0.0 # restore correct value # Compensation charges: self.ghat = PWLFC([setup.ghat_l for setup in wfs.setups], self.pd2) self.ghat.set_positions(self.spos_ac) if self.molecule: self.initialize_gaussian() self.log('Value of beta parameter: %.3f 1/Bohr^2' % self.beta) self.timer.stop('Initialization') # Ready ... set ... go: self.t0 = time() self.npairs = 0 self.evv = 0.0 self.evvacdf = 0.0 for s in range(self.wfs.nspins): kpt1_q = [ KPoint(self.wfs, noccmax).initialize(kpt) for kpt in self.wfs.kpt_u if kpt.s == s ] kpt2_q = kpt1_q[:] if len(kpt1_q) == 0: # No s-spins on this CPU: continue # Send and receive ranks: srank = self.wfs.kd.get_rank_and_index(s, (kpt1_q[0].k - 1) % kd.nibzkpts)[0] rrank = self.wfs.kd.get_rank_and_index(s, (kpt1_q[-1].k + 1) % kd.nibzkpts)[0] # Shift k-points kd.nibzkpts - 1 times: for i in range(kd.nibzkpts): if i < kd.nibzkpts - 1: if kparallel: kpt = kpt2_q[-1].next(self.wfs) kpt.start_receiving(rrank) kpt2_q[0].start_sending(srank) else: kpt = kpt2_q[0] self.timer.start('Calculate') for kpt1, kpt2 in zip(kpt1_q, kpt2_q): # Loop over all k-points that k2 can be mapped to: for K2, q, n1_n, n2 in self.indices(s, kpt1.k, kpt2.k): self.apply(K2, q, kpt1, kpt2, n1_n, n2) self.timer.stop('Calculate') if i < kd.nibzkpts - 1: self.timer.start('Wait') if kparallel: kpt.wait() kpt2_q[0].wait() self.timer.stop('Wait') kpt2_q.pop(0) kpt2_q.append(kpt) self.evv = self.world.sum(self.evv) self.evvacdf = self.world.sum(self.evvacdf) self.calculate_exx_paw_correction() if self.method == 'standard': self.exx = self.evv + self.devv + self.evc + self.ecc elif self.method == 'acdf': self.exx = self.evvacdf + self.devv + self.evc + self.ecc else: 1 / 0 self.log('Exact exchange energy:') for txt, e in [('core-core', self.ecc), ('valence-core', self.evc), ('valence-valence (pseudo, acdf)', self.evvacdf), ('valence-valence (pseudo, standard)', self.evv), ('valence-valence (correction)', self.devv), ('total (%s)' % self.method, self.exx)]: self.log(' %-36s %14.6f eV' % (txt + ':', e * Hartree)) self.log('Total time: %10.3f seconds' % (time() - self.t0)) self.npairs = self.world.sum(self.npairs) assert self.npairs == self.npairs0 self.timer.stop('EXX') self.timer.write(self.fd)
a = 8.0 gd = GridDescriptor((n, n, n), (a, a, a), comm=mpi.serial_comm) spos_ac = np.array([(0.15, 0.45, 0.95)]) pd = PWDescriptor(45, gd, complex) pdr = PWDescriptor(45, gd) from gpaw.fftw import FFTPlan print(FFTPlan) for l in range(4): print(l) s = Spline(l, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) lfc = PWLFC([[s]], pd) lfcr = PWLFC([[s]], pdr) c_axi = {0: np.zeros((1, 2 * l + 1), complex)} c_axi[0][0, 0] = 1.9 cr_axi = {0: np.zeros((1, 2 * l + 1))} cr_axi[0][0, 0] = 1.9 b = pd.zeros(1, dtype=complex) br = pdr.zeros(1) lfc.set_positions(spos_ac) lfc.add(b, c_axi) lfcr.set_positions(spos_ac) lfcr.add(br, cr_axi)
gd = GridDescriptor((n, n, n), cell_cv, comm=mpi.serial_comm) a_R = gd.empty() z = np.linspace(0, n, n, endpoint=False) a_R[:] = 2 + np.sin(2 * np.pi * z / n) spos_ac = np.array([(0.15, 0.45, 0.95)]) pd = PWDescriptor(45, gd) a_G = pd.fft(a_R) s = Spline(0, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) p = Spline(1, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) d = Spline(2, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) lfc = PWLFC([[s, p, d]], pd) lfc.set_positions(spos_ac) b_LG = pd.zeros(9) lfc.add(b_LG, {0: np.eye(9)}) e1 = pd.integrate(a_G, b_LG) assert abs(lfc.integrate(a_G)[0] - e1).max() < 1e-11 s1 = [] for i in range(9): x = [0, 0, 0, 0, 0, 0, 0, 0, 0] x[i] = 1 s1.append(lfc.stress_tensor_contribution(a_G, {0: x}) - np.eye(3) * e1[i]) x = 1e-6 for dist in [[[x, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, x, 0], [0, 0, 0]],
def initialize(self): self.eta /= Hartree self.ecut /= Hartree calc = self.calc self.nspins = self.calc.wfs.nspins # kpoint init self.kd = kd = calc.wfs.kd self.nikpt = kd.nibzkpts self.ftol /= kd.nbzkpts # cell init self.acell_cv = calc.wfs.gd.cell_cv self.acell_cv, self.bcell_cv, self.vol, self.BZvol = \ get_primitive_cell(self.acell_cv,rpad=self.rpad) # grid init gd = calc.wfs.gd.new_descriptor(comm=serial_comm) self.pbc = gd.pbc_c self.gd = gd self.nG0 = np.prod(gd.N_c) # Number of grid points and volume including zero padding self.nGrpad = gd.N_c * self.rpad self.nG0rpad = np.prod(self.nGrpad) self.d_c = [ Gradient(gd, i, n=4, dtype=complex).apply for i in range(3) ] # obtain eigenvalues, occupations nibzkpt = kd.nibzkpts kweight_k = kd.weight_k self.eFermi = self.calc.occupations.get_fermi_level() try: self.e_skn self.printtxt('Use eigenvalues from user.') except: self.printtxt('Use eigenvalues from the calculator.') self.e_skn = {} self.f_skn = {} for ispin in range(self.nspins): self.e_skn[ispin] = np.array([ calc.get_eigenvalues(kpt=k, spin=ispin) for k in range(nibzkpt) ]) / Hartree self.f_skn[ispin] = np.array([ calc.get_occupation_numbers(kpt=k, spin=ispin) / kweight_k[k] for k in range(nibzkpt) ]) / kd.nbzkpts #self.printtxt('Eigenvalues(k=0) are:') #print >> self.txt, self.e_skn[0][0] * Hartree self.enoshift_skn = {} for ispin in range(self.nspins): self.enoshift_skn[ispin] = self.e_skn[ispin].copy() if self.eshift is not None: self.add_discontinuity(self.eshift) self.printtxt('Shift unoccupied bands by %f eV' % (self.eshift)) # k + q init if self.q_c is not None: self.qq_v = np.dot(self.q_c, self.bcell_cv) # summation over c if self.optical_limit: kq_k = np.arange(kd.nbzkpts) self.expqr_g = 1. else: r_vg = gd.get_grid_point_coordinates() # (3, nG) qr_g = gemmdot(self.qq_v, r_vg, beta=0.0) self.expqr_g = np.exp(-1j * qr_g) del r_vg, qr_g kq_k = kd.find_k_plus_q(self.q_c) self.kq_k = kq_k # Plane wave init if self.G_plus_q: self.npw, self.Gvec_Gc, self.Gindex_G = set_Gvectors(self.acell_cv, self.bcell_cv, self.gd.N_c, self.ecut, q=self.q_c) else: self.npw, self.Gvec_Gc, self.Gindex_G = set_Gvectors( self.acell_cv, self.bcell_cv, self.gd.N_c, self.ecut) # band init if self.nbands is None: self.nbands = calc.wfs.bd.nbands self.nvalence = calc.wfs.nvalence # Projectors init setups = calc.wfs.setups self.spos_ac = calc.atoms.get_scaled_positions() if self.pwmode: self.pt = PWLFC([setup.pt_j for setup in setups], self.calc.wfs.pd) self.pt.set_positions(self.spos_ac) else: self.pt = LFC(gd, [setup.pt_j for setup in setups], KPointDescriptor(self.kd.bzk_kc), dtype=complex, forces=True) self.pt.set_positions(self.spos_ac) # Printing calculation information self.print_stuff() return
spos_ac = np.array([(0.15, 0.5, 0.95)]) pd = PWDescriptor(45, gd, complex, kd) eikr = np.ascontiguousarray( np.exp(2j * np.pi * np.dot(np.indices(gd.N_c).T, (kpts / gd.N_c).T).T)[0]) from gpaw.fftw import FFTPlan print(FFTPlan) for l in range(3): print(l) s = Spline(l, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) lfc1 = LFC(gd, [[s]], kd, dtype=complex) lfc2 = PWLFC([[s]], pd) c_axi = {0: np.zeros((1, 2 * l + 1), complex)} c_axi[0][0, 0] = 1.9 - 4.5j c_axiv = {0: np.zeros((1, 2 * l + 1, 3), complex)} b1 = gd.zeros(1, dtype=complex) b2 = pd.zeros(1, dtype=complex) for lfc, b in [(lfc1, b1), (lfc2, b2)]: lfc.set_positions(spos_ac) lfc.add(b, c_axi, 0) b2 = pd.ifft(b2[0]) * eikr equal(abs(b2 - b1[0]).max(), 0, 0.001)