def __init__(self, calc, xc, ibzq_qc, fd, unit_cells, density_cut, ecut, tag, timer): self.calc = calc self.gd = calc.density.gd self.xc = xc self.ibzq_qc = ibzq_qc self.fd = fd self.unit_cells = unit_cells self.density_cut = density_cut self.ecut = ecut self.tag = tag self.timer = timer self.A_x = -(3 / 4.) * (3 / np.pi)**(1 / 3.) self.n_g = calc.get_all_electron_density(gridrefinement=1) self.n_g *= Bohr**3 if xc[-3:] == 'PBE': nf_g = calc.get_all_electron_density(gridrefinement=2) nf_g *= Bohr**3 gdf = self.gd.refine() grad_v = [Gradient(gdf, v, n=1).apply for v in range(3)] gradnf_vg = gdf.empty(3) for v in range(3): grad_v[v](nf_g, gradnf_vg[v]) self.gradn_vg = gradnf_vg[:, ::2, ::2, ::2] qd = KPointDescriptor(self.ibzq_qc) self.pd = PWDescriptor(ecut / Hartree, self.gd, complex, qd)
def __init__(self, name=None, calc=None, M=None, spinorbit=None): self.name = name self.calc = GPAW(calc, txt=None, communicator=mpi.serial_comm) self.M = np.array(M, dtype=float) self.spinorbit = spinorbit self.gd = self.calc.wfs.gd.new_descriptor() self.kd = self.calc.wfs.kd if self.calc.wfs.mode is 'pw': self.pd = self.calc.wfs.pd else: self.pd = PWDescriptor(ecut=None, gd=self.gd, kd=self.kd, dtype=complex) self.acell_cv = self.gd.cell_cv self.bcell_cv = 2 * np.pi * self.gd.icell_cv self.vol = self.gd.volume self.BZvol = (2 * np.pi)**3 / self.vol self.nb = self.calc.get_number_of_bands() self.v_Knm = None if spinorbit: if mpi.world.rank == 0: print('Calculating spinorbit Corrections') self.nb = 2 * self.calc.get_number_of_bands() self.e_mK, self.v_Knm = get_spinorbit_eigenvalues(self.calc, return_wfs=True) if mpi.world.rank == 0: print('Done with the spinorbit Corrections')
def initialize(self, density, hamiltonian, wfs, occupations): self.xc.initialize(density, hamiltonian, wfs, occupations) self.nspins = wfs.nspins self.setups = wfs.setups self.density = density self.kpt_u = wfs.kpt_u self.gd = density.gd self.kd = wfs.kd self.bd = wfs.bd if self.bd.comm.size > 1: raise ValueError('Band parallelization not supported by hybridk') self.wfs = wfs self.world = wfs.world self.fd = logfile(self.fd, self.world.rank) N = self.gd.N_c.prod() vol = self.gd.dv * N if self.alpha is None: # XXX ? self.alpha = 6 * vol**(2 / 3.0) / pi**2 if self.ecut is None: self.ecut = 0.5 * pi**2 / (self.gd.h_cv**2).sum(1).max() * 0.9999 self.bzq_qc = self.kd.get_bz_q_points() qd = KPointDescriptor(self.bzq_qc) q0 = self.kd.where_is_q(np.zeros(3), self.bzq_qc) self.pwd = PWDescriptor(self.ecut, self.gd, complex, kd=qd) G2_qG = self.pwd.G2_qG G2_qG[q0][0] = 117.0 self.iG2_qG = [1.0 / G2_G for G2_G in G2_qG] G2_qG[q0][0] = 0.0 self.iG2_qG[q0][0] = 0.0 self.gamma = (vol / (2 * pi)**2 * sqrt(pi / self.alpha) * self.kd.nbzkpts) for q in range(self.kd.nbzkpts): self.gamma -= np.dot(np.exp(-self.alpha * G2_qG[q]), self.iG2_qG[q]) self.iG2_qG[q0][0] = self.gamma self.ghat = LFC(self.gd, [setup.ghat_l for setup in density.setups], qd, dtype=complex) self.log('Value of alpha parameter:', self.alpha) self.log('Value of gamma parameter:', self.gamma) self.log('Cutoff energy:', self.ecut, 'Hartree') self.log('%d x %d x %d k-points' % tuple(self.kd.N_c))
def get_pw_descriptor(q_c, calc, ecut, gammacentered=False): """Get the planewave descriptor of q_c.""" qd = KPointDescriptor([q_c]) pd = PWDescriptor(ecut, calc.wfs.gd, complex, qd, gammacentered=gammacentered) return pd
def get_PWDescriptor(self, q_c, gammacentered=False): """Get the planewave descriptor of q_c.""" qd = KPointDescriptor([q_c]) pd = PWDescriptor(self.ecut, self.calc.wfs.gd, complex, qd, gammacentered=gammacentered) return pd
def calculate(self, q_c, spin='all', A_x=None): wfs = self.calc.wfs if spin == 'all': spins = range(wfs.nspins) else: assert spin in range(wfs.nspins) spins = [spin] q_c = np.asarray(q_c, dtype=float) qd = KPointDescriptor([q_c]) pd = PWDescriptor(self.ecut, wfs.gd, complex, qd) self.print_chi(pd) if extra_parameters.get('df_dry_run'): print(' Dry run exit', file=self.fd) raise SystemExit nG = pd.ngmax nw = len(self.omega_w) mynG = (nG + self.blockcomm.size - 1) // self.blockcomm.size self.Ga = self.blockcomm.rank * mynG self.Gb = min(self.Ga + mynG, nG) assert mynG * (self.blockcomm.size - 1) < nG if A_x is not None: nx = nw * (self.Gb - self.Ga) * nG chi0_wGG = A_x[:nx].reshape((nw, self.Gb - self.Ga, nG)) chi0_wGG[:] = 0.0 else: chi0_wGG = np.zeros((nw, self.Gb - self.Ga, nG), complex) if np.allclose(q_c, 0.0): chi0_wxvG = np.zeros((len(self.omega_w), 2, 3, nG), complex) chi0_wvv = np.zeros((len(self.omega_w), 3, 3), complex) self.chi0_vv = np.zeros((3, 3), complex) else: chi0_wxvG = None chi0_wvv = None print('Initializing PAW Corrections', file=self.fd) self.Q_aGii = self.initialize_paw_corrections(pd) # Do all empty bands: m1 = self.nocc1 m2 = self.nbands self._calculate(pd, chi0_wGG, chi0_wxvG, chi0_wvv, self.Q_aGii, m1, m2, spins) return pd, chi0_wGG, chi0_wxvG, chi0_wvv
def check(self, i_cG, shift0_c, N_c, q_c, Q_aGii): I0_G = np.ravel_multi_index(i_cG - shift0_c[:, None], N_c, 'wrap') qd1 = KPointDescriptor([q_c]) pd1 = PWDescriptor(self.ecut, self.calc.wfs.gd, complex, qd1) G_I = np.empty(N_c.prod(), int) G_I[:] = -1 I1_G = pd1.Q_qG[0] G_I[I1_G] = np.arange(len(I0_G)) G_G = G_I[I0_G] assert len(I0_G) == len(I1_G) assert (G_G >= 0).all() for a, Q_Gii in enumerate(self.initialize_paw_corrections(pd1)): e = abs(Q_aGii[a] - Q_Gii[G_G]).max() assert e < 1e-12
def calculate_gamma(self, vol, alpha): if self.molecule: return 0.0 N_c = self.kd.N_c offset_c = (N_c + 1) % 2 * 0.5 / N_c bzq_qc = monkhorst_pack(N_c) + offset_c qd = KPointDescriptor(bzq_qc) pd = PWDescriptor(self.wfs.pd.ecut, self.wfs.gd, kd=qd) gamma = (vol / (2 * pi)**2 * sqrt(pi / alpha) * self.kd.nbzkpts) for G2_G in pd.G2_qG: if G2_G[0] < 1e-7: G2_G = G2_G[1:] gamma -= np.dot(np.exp(-alpha * G2_G), G2_G**-1) return gamma / self.qstride_c.prod()
def calculate_q(self, i, kpt1, kpt2): wfs = self.calc.wfs q_c = wfs.kd.bzk_kc[kpt2.K] - wfs.kd.bzk_kc[kpt1.K] qd = KPointDescriptor([q_c]) pd = PWDescriptor(self.ecut, wfs.gd, wfs.dtype, kd=qd) Q_G = self.get_fft_indices(kpt1.K, kpt2.K, q_c, pd, kpt1.shift_c - kpt2.shift_c) Q_aGii = self.initialize_paw_corrections(pd, soft=True) for n in range(kpt1.n2 - kpt1.n1): ut1cc_R = kpt1.ut_nR[n].conj() C1_aGi = [ np.dot(Q_Gii, P1_ni[n].conj()) for Q_Gii, P1_ni in zip(Q_aGii, kpt1.P_ani) ] n_mG = self.calculate_pair_densities(ut1cc_R, C1_aGi, kpt2, pd, Q_G) e = self.calculate_n(pd, n, n_mG, kpt2) self.exxvv_sin[kpt1.s, i, n] += e
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)
a2[R2] = 1 y = pd2.restrict(a2, pd1)[0][R1] * a2.size / a1.size equal(x, y, 1e-9) return x if world.size == 1: for size1, size2 in [[(3, 3, 3), (8, 8, 8)], [(4, 4, 4), (9, 9, 9)], [(2, 4, 4), (5, 9, 9)], [(2, 3, 4), (5, 6, 9)], [(2, 3, 4), (5, 6, 8)], [(4, 4, 4), (8, 8, 8)], [(2, 4, 4), (4, 8, 8)], [(2, 4, 2), (4, 8, 4)]]: print(size1, size2) gd1 = GridDescriptor(size1, size1) gd2 = GridDescriptor(size2, size1) pd1 = PWDescriptor(1, gd1, complex) pd2 = PWDescriptor(1, gd2, complex) pd1r = PWDescriptor(1, gd1) pd2r = PWDescriptor(1, gd2) for R1, R2 in [[(0, 0, 0), (0, 0, 0)], [(0, 0, 0), (0, 0, 1)]]: x = test(gd1, gd2, pd1, pd2, R1, R2) y = test(gd1, gd2, pd1r, pd2r, R1, R2) equal(x, y, 1e-9) a1 = np.random.random(size1) a2 = pd1r.interpolate(a1, pd2r)[0] c2 = pd1.interpolate(a1 + 0.0j, pd2)[0] d2 = pd1.interpolate(a1 * 1.0j, pd2)[0] equal(abs(c2.imag).max(), 0, 1e-14) equal(abs(d2.real).max(), 0, 1e-14) equal(gd1.integrate(a1), gd2.integrate(a2), 1e-13)
def initialize(self, density, hamiltonian, wfs, occupations): self.xc.initialize(density, hamiltonian, wfs, occupations) self.nspins = wfs.nspins self.setups = wfs.setups self.density = density self.kpt_u = wfs.kpt_u self.gd = density.gd self.kd = wfs.kd self.bd = wfs.bd N_c = self.gd.N_c N = self.gd.N_c.prod() vol = self.gd.dv * N if self.alpha is None: self.alpha = 6 * vol**(2 / 3.0) / pi**2 self.gamma = (vol / (2 * pi)**2 * sqrt(pi / self.alpha) * self.kd.nbzkpts) ecut = 0.5 * pi**2 / (self.gd.h_cv**2).sum(1).max() if self.kd.N_c is None: self.bzk_kc = np.zeros((1, 3)) dfghdfgh else: n = self.kd.N_c * 2 - 1 bzk_kc = np.indices(n).transpose((1, 2, 3, 0)) bzk_kc.shape = (-1, 3) bzk_kc -= self.kd.N_c - 1 self.bzk_kc = bzk_kc.astype(float) / self.kd.N_c self.pwd = PWDescriptor(ecut, self.gd, self.bzk_kc) n = 0 for k_c, Gpk2_G in zip(self.bzk_kc[:], self.pwd.G2_qG): if (k_c > -0.5).all() and (k_c <= 0.5).all(): #XXX??? if k_c.any(): self.gamma -= np.dot(np.exp(-self.alpha * Gpk2_G), Gpk2_G**-1) else: self.gamma -= np.dot(np.exp(-self.alpha * Gpk2_G[1:]), Gpk2_G[1:]**-1) n += 1 assert n == self.kd.N_c.prod() self.ghat = LFC(self.gd, [setup.ghat_l for setup in density.setups], dtype=complex) self.ghat.set_k_points(self.bzk_kc) self.fullkd = KPointDescriptor(self.kd.bzk_kc, nspins=1) class S: id_a = [] def set_symmetry(self, s): pass self.fullkd.set_symmetry(Atoms(pbc=True), S(), False) self.fullkd.set_communicator(world) self.pt = LFC(self.gd, [setup.pt_j for setup in density.setups], dtype=complex) self.pt.set_k_points(self.fullkd.ibzk_kc) self.interpolator = density.interpolator
def read_gpaw(input_gpw, nb_max=None, spin_factor=2, output_file='out.hdf5', calculate_overlap=True, calculate_momentum=True): """ Read .gpw file and create a hdf5 as output. Partially adapted from gpaw.wannier90.write_overlaps. input_gpw: location of .gpw input file nb_max: maximum band spin_factor: electrons per band (only default value supported!) """ nn = 1 au = AtomicUnits() atoms, calc = restart(input_gpw, txt=None) # Generate full Brillouin zone if necessary if calc.parameters['symmetry'] != 'off': calc.set(symmetry='off') calc.get_potential_energy() calc.write(input_gpw.replace('.gpw', '_FBZ.gpw'), mode='all') calc.get_potential_energy() #Optional parameters: nb = calc.parameters['convergence']['bands'] if nb_max is not None: nb = min(nb, nb_max) nk_size = calc.parameters['kpts']['size'] nk = calc.wfs.kd.nbzkpts kpts = calc.get_bz_k_points() wfs = calc.wfs nvalence = calc.setups.nvalence // spin_factor lattice = atoms.get_cell() / au.AA reciprocal_lattice = (2 * np.pi * au.AA) * atoms.get_reciprocal_cell() bands = range(nb) direction = np.eye(3, dtype=np.intp) klist1d = np.zeros((nk, 3)) klist3d = np.zeros((nk_size), dtype=np.intp) energy = np.zeros((nk, nb)) for i in range(nk): klist1d[i, :] = calc.wfs.kd.bzk_kc[i] for i in range(nk): ix, iy, iz = [int(q) for q in np.rint(nk_size * kpts[i, :])] klist3d[ix, iy, iz] = i nn_table = nearest_neighbor_table(klist3d, nn) energy_fermi = calc.get_fermi_level() for i in range(nk): energy[i, :] = (calc.get_eigenvalues(kpt=i, spin=0) - energy_fermi)[:nb] / au.eV if calculate_overlap: overlap = np.zeros((nk, 3, 2 * nn, nb, nb), dtype=np.complex) icell_cv = (2 * np.pi) * np.linalg.inv(calc.wfs.gd.cell_cv).T r_grid = calc.wfs.gd.get_grid_point_coordinates() n_grid = np.prod(np.shape(r_grid)[1:]) * (False + 1) u_kng = [] for i in range(nk): u_kng.append( np.array([wfs.get_wave_function_array(n, i, 0) for n in bands])) d0_aii = [] for i in calc.wfs.kpt_u[0].p_ani.keys(): d0_ii = calc.wfs.setups[i].d0_ii d0_aii.append(d0_ii) p_kani = [] for i in range(nk): p_kani.append(calc.wfs.kpt_u[0 * nk + i].p_ani) for ik1 in range(nk): u1_ng = u_kng[ik1] for i in range(3): for j in range(-nn, nn): ik2 = nn_table[ik1, i, j] if j < 0: g_vector = (kpts[ik1] + 1.0 * j * direction[i, :] / nk_size) - kpts[ik2] if j >= 0: g_vector = ( kpts[ik1] + 1.0 * (j + 1) * direction[i, :] / nk_size) - kpts[ik2] bg_c = kpts[ik2] - kpts[ik1] + g_vector bg_v = np.dot(bg_c, icell_cv) u2_ng = u_kng[ik2] * np.exp( -1j * np.inner(r_grid.T, bg_v).T) overlap[ik1, i, j, :, :] = get_overlap( calc, bands, np.reshape(u1_ng, (len(u1_ng), n_grid)), np.reshape(u2_ng, (len(u2_ng), n_grid)), p_kani[ik1], p_kani[ik2], d0_aii, bg_v)[:nb, :nb] if calculate_momentum: pair = PairDensity(calc=calc) momentum = np.zeros((nk, nb, nb, 3), dtype=np.complex) delta_q_vector = [0.0, 0.0, 0.0] delta_q_descriptor = KPointDescriptor([delta_q_vector]) plane_wave_descriptor = PWDescriptor(pair.ecut, calc.wfs.gd, complex, delta_q_descriptor) for i in range(nk): kpoint_pair = pair.get_kpoint_pair(plane_wave_descriptor, s=0, K=i, n1=0, n2=nb, m1=0, m2=nb) kpoint_momentum = pair.get_pair_momentum(plane_wave_descriptor, kpoint_pair, np.arange(0, nb), np.arange(0, nb)) momentum[i, :, :, :] = kpoint_momentum[..., 0] hdf5 = h5py.File(output_file, 'w') hdf5.create_dataset("energy", data=energy) hdf5.create_dataset("klist1d", data=klist1d) hdf5.create_dataset("klist3d", data=klist3d) hdf5.create_dataset("lattice_vectors", data=lattice.T) hdf5.create_dataset("reciprocal_vectors", data=reciprocal_lattice.T) hdf5.create_dataset("valence_bands", data=nvalence) hdf5.create_dataset("size", data=nk_size) hdf5.create_dataset("spin_factor", data=spin_factor) if calculate_momentum: hdf5.create_dataset("momentum", data=momentum) if calculate_overlap: hdf5.create_dataset("overlap", data=overlap) hdf5.create_dataset("neighbour_table", data=nn_table)
def calculate_QEH(self): print('Calculating QEH self-energy contribution', file=self.fd) kd = self.calc.wfs.kd # Reset calculation self.sigma_sin = np.zeros(self.shape) # self-energies self.dsigma_sin = np.zeros(self.shape) # derivatives of self-energies # Get KS eigenvalues and occupation numbers: b1, b2 = self.bands nibzk = self.calc.wfs.kd.nibzkpts for i, k in enumerate(self.kpts): for s in range(self.nspins): u = s * nibzk + k kpt = self.calc.wfs.kpt_u[u] self.eps_sin[s, i] = kpt.eps_n[b1:b2] self.f_sin[s, i] = kpt.f_n[b1:b2] / kpt.weight # My part of the states we want to calculate QP-energies for: mykpts = [ self.get_k_point(s, K, n1, n2) for s, K, n1, n2 in self.mysKn1n2 ] kplusqdone_u = [set() for kpt in mykpts] Nq = len((self.qd.ibzk_kc)) for iq, q_c in enumerate(self.qd.ibzk_kc): self.nq = iq nq = iq self.save_state_file() qcstr = '(' + ', '.join(['%.3f' % x for x in q_c]) + ')' print('Calculating contribution from IBZ q-point #%d/%d q_c=%s' % (nq, Nq, qcstr), file=self.fd) rcell_cv = 2 * pi * np.linalg.inv(self.calc.wfs.gd.cell_cv).T q_abs = np.linalg.norm(np.dot(q_c, rcell_cv)) # Screened potential dW_w = self.dW_qw[nq] dW_w = dW_w[:, np.newaxis, np.newaxis] L = abs(self.calc.wfs.gd.cell_cv[2, 2]) dW_w *= L nw = self.nw Wpm_w = np.zeros([2 * nw, 1, 1], dtype=complex) Wpm_w[:nw] = dW_w Wpm_w[nw:] = Wpm_w[0:nw] with self.timer('Hilbert transform'): self.htp(Wpm_w[:nw]) self.htm(Wpm_w[nw:]) qd = KPointDescriptor([q_c]) pd0 = PWDescriptor(self.ecut, self.calc.wfs.gd, complex, qd) # modify pd0 by hand - only G=0 component is needed pd0.G_Qv = np.array([1e-17, 1e-17, 1e-17])[np.newaxis, :] pd0.Q_qG = [np.array([0], dtype='int32')] pd0.ngmax = 1 G_Gv = pd0.get_reciprocal_vectors() self.Q_aGii = self.initialize_paw_corrections(pd0) # Loop over all k-points in the BZ and find those that are related # to the current IBZ k-point by symmetry Q1 = self.qd.ibz2bz_k[iq] Q2s = set() for s, Q2 in enumerate(self.qd.bz2bz_ks[Q1]): if Q2 >= 0 and Q2 not in Q2s: Q2s.add(Q2) for Q2 in Q2s: s = self.qd.sym_k[Q2] self.s = s U_cc = self.qd.symmetry.op_scc[s] time_reversal = self.qd.time_reversal_k[Q2] self.sign = 1 - 2 * time_reversal Q_c = self.qd.bzk_kc[Q2] d_c = self.sign * np.dot(U_cc, q_c) - Q_c assert np.allclose(d_c.round(), d_c) for u1, kpt1 in enumerate(mykpts): K2 = kd.find_k_plus_q(Q_c, [kpt1.K])[0] kpt2 = self.get_k_point(kpt1.s, K2, 0, self.nbands, block=True) k1 = kd.bz2ibz_k[kpt1.K] i = self.kpts.index(k1) N_c = pd0.gd.N_c i_cG = self.sign * np.dot( U_cc, np.unravel_index(pd0.Q_qG[0], N_c)) k1_c = kd.bzk_kc[kpt1.K] k2_c = kd.bzk_kc[K2] # This is the q that connects K1 and K2 in the 1st BZ q1_c = kd.bzk_kc[K2] - kd.bzk_kc[kpt1.K] # G-vector that connects the full Q_c with q1_c shift1_c = q1_c - self.sign * np.dot(U_cc, q_c) assert np.allclose(shift1_c.round(), shift1_c) shift1_c = shift1_c.round().astype(int) shift_c = kpt1.shift_c - kpt2.shift_c - shift1_c I_G = np.ravel_multi_index(i_cG + shift_c[:, None], N_c, 'wrap') pos_av = np.dot(self.spos_ac, pd0.gd.cell_cv) M_vv = np.dot( pd0.gd.cell_cv.T, np.dot(U_cc.T, np.linalg.inv(pd0.gd.cell_cv).T)) Q_aGii = [] for a, Q_Gii in enumerate(self.Q_aGii): x_G = np.exp( 1j * np.dot(G_Gv, (pos_av[a] - np.dot(M_vv, pos_av[a])))) U_ii = self.calc.wfs.setups[a].R_sii[self.s] Q_Gii = np.dot( np.dot(U_ii, Q_Gii * x_G[:, None, None]), U_ii.T).transpose(1, 0, 2) if self.sign == -1: Q_Gii = Q_Gii.conj() Q_aGii.append(Q_Gii) for n in range(kpt1.n2 - kpt1.n1): ut1cc_R = kpt1.ut_nR[n].conj() eps1 = kpt1.eps_n[n] C1_aGi = [ np.dot(Qa_Gii, P1_ni[n].conj()) for Qa_Gii, P1_ni in zip(Q_aGii, kpt1.P_ani) ] n_mG = self.calculate_pair_densities( ut1cc_R, C1_aGi, kpt2, pd0, I_G) if self.sign == 1: n_mG = n_mG.conj() f_m = kpt2.f_n deps_m = eps1 - kpt2.eps_n sigma, dsigma = self.calculate_sigma( n_mG, deps_m, f_m, Wpm_w) nn = kpt1.n1 + n - self.bands[0] self.sigma_sin[kpt1.s, i, nn] += sigma self.dsigma_sin[kpt1.s, i, nn] += dsigma self.world.sum(self.sigma_sin) self.world.sum(self.dsigma_sin) self.complete = True self.save_state_file() return self.sigma_sin, self.dsigma_sin
def calculate(self, ecut, nbands=None, spin=False): """Calculate RPA correlation energy for one or several cutoffs. ecut: float or list of floats Plane-wave cutoff(s). nbands: int Number of bands (defaults to number of plane-waves). spin: bool Separate spin in response function. (Only needed for beyond RPA methods that inherit this function). """ p = functools.partial(print, file=self.fd) if isinstance(ecut, (float, int)): ecut = ecut * (1 + 0.5 * np.arange(6))**(-2 / 3) self.ecut_i = np.asarray(np.sort(ecut)) / Hartree ecutmax = max(self.ecut_i) if nbands is None: p('Response function bands : Equal to number of plane waves') else: p('Response function bands : %s' % nbands) p('Plane wave cutoffs (eV) :', end='') for e in self.ecut_i: p(' {0:.3f}'.format(e * Hartree), end='') p() if self.truncation is not None: p('Using %s Coulomb truncation' % self.truncation) p() if self.filename and os.path.isfile(self.filename): self.read() self.world.barrier() chi0 = Chi0(self.calc, 1j * Hartree * self.omega_w, eta=0.0, intraband=False, hilbert=False, txt='chi0.txt', timer=self.timer, world=self.world, nblocks=self.nblocks) self.blockcomm = chi0.blockcomm wfs = self.calc.wfs if self.truncation == 'wigner-seitz': self.wstc = WignerSeitzTruncatedCoulomb(wfs.gd.cell_cv, wfs.kd.N_c, self.fd) else: self.wstc = None nq = len(self.energy_qi) nw = len(self.omega_w) nGmax = max(count_reciprocal_vectors(ecutmax, wfs.gd, q_c) for q_c in self.ibzq_qc[nq:]) mynGmax = (nGmax + self.nblocks - 1) // self.nblocks nx = (1 + spin) * nw * mynGmax * nGmax A1_x = np.empty(nx, complex) if self.nblocks > 1: A2_x = np.empty(nx, complex) else: A2_x = None self.timer.start('RPA') for q_c in self.ibzq_qc[nq:]: if np.allclose(q_c, 0.0) and self.skip_gamma: self.energy_qi.append(len(self.ecut_i) * [0.0]) self.write() p('Not calculating E_c(q) at Gamma') p() continue thisqd = KPointDescriptor([q_c]) pd = PWDescriptor(ecutmax, wfs.gd, complex, thisqd) nG = pd.ngmax mynG = (nG + self.nblocks - 1) // self.nblocks chi0.Ga = self.blockcomm.rank * mynG chi0.Gb = min(chi0.Ga + mynG, nG) shape = (1 + spin, nw, chi0.Gb - chi0.Ga, nG) chi0_swGG = A1_x[:np.prod(shape)].reshape(shape) chi0_swGG[:] = 0.0 if np.allclose(q_c, 0.0): chi0_swxvG = np.zeros((1 + spin, nw, 2, 3, nG), complex) chi0_swvv = np.zeros((1 + spin, nw, 3, 3), complex) else: chi0_swxvG = None chi0_swvv = None # First not completely filled band: m1 = chi0.nocc1 p('# %s - %s' % (len(self.energy_qi), ctime().split()[-2])) p('q = [%1.3f %1.3f %1.3f]' % tuple(q_c)) energy_i = [] for ecut in self.ecut_i: if ecut == ecutmax: # Nothing to cut away: cut_G = None m2 = nbands or nG else: cut_G = np.arange(nG)[pd.G2_qG[0] <= 2 * ecut] m2 = len(cut_G) p('E_cut = %d eV / Bands = %d:' % (ecut * Hartree, m2)) self.fd.flush() energy = self.calculate_q(chi0, pd, chi0_swGG, chi0_swxvG, chi0_swvv, m1, m2, cut_G, A2_x) energy_i.append(energy) m1 = m2 a = 1 / chi0.kncomm.size if ecut < ecutmax and a != 1.0: # Chi0 will be summed again over chicomm, so we divide # by its size: chi0_swGG *= a if chi0_swxvG is not None: chi0_swxvG *= a chi0_swvv *= a self.energy_qi.append(energy_i) self.write() p() e_i = np.dot(self.weight_q, np.array(self.energy_qi)) p('==========================================================') p() p('Total correlation energy:') for e_cut, e in zip(self.ecut_i, e_i): p('%6.0f: %6.4f eV' % (e_cut * Hartree, e * Hartree)) p() self.energy_qi = [] # important if another calculation is performed if len(e_i) > 1: self.extrapolate(e_i) p('Calculation completed at: ', ctime()) p() self.timer.stop('RPA') self.timer.write(self.fd) self.fd.flush() return e_i * Hartree
def __init__(self, gd1, gd2, dtype=float): self.pd1 = PWDescriptor(0.0, gd1, dtype) self.pd2 = PWDescriptor(0.0, gd2, dtype)
def __call__(self, pd, calc, functional): assert functional in self.permitted_functionals self.functional = functional add_fxc = self.add_fxc # class methods not within the scope of call vol = pd.gd.volume npw = pd.ngmax if self.RSrep == 'grid': print("\tFinding all-electron density", file=self.fd) n_sG, gd = calc.density.get_all_electron_density(atoms=calc.atoms, gridrefinement=1) qd = pd.kd lpd = PWDescriptor(self.ecut, gd, complex, qd, gammacentered=pd.gammacentered) print("\tCalculating fxc on real space grid using" + " all-electron density", file=self.fd) fxc_G = np.zeros(np.shape(n_sG[0])) add_fxc(gd, n_sG, fxc_G) else: nt_sG = calc.density.nt_sG gd, lpd = pd.gd, pd print("\tCalculating fxc on real space grid using smooth density", file=self.fd) fxc_G = np.zeros(np.shape(nt_sG[0])) add_fxc(gd, nt_sG, fxc_G) print("\tFourier transforming into reciprocal space", file=self.fd) nG = gd.N_c nG0 = nG[0] * nG[1] * nG[2] tmp_g = np.fft.fftn(fxc_G) * vol / nG0 Kxc_GG = np.zeros((npw, npw), dtype=complex) for iG, iQ in enumerate(lpd.Q_qG[0]): iQ_c = (np.unravel_index(iQ, nG) + nG // 2) % nG - nG // 2 for jG, jQ in enumerate(lpd.Q_qG[0]): jQ_c = (np.unravel_index(jQ, nG) + nG // 2) % nG - nG // 2 ijQ_c = (iQ_c - jQ_c) if (abs(ijQ_c) < nG // 2).all(): Kxc_GG[iG, jG] = tmp_g[tuple(ijQ_c)] if self.RSrep == 'gpaw': print("\tCalculating PAW corrections to the kernel", file=self.fd) G_Gv = pd.get_reciprocal_vectors() R_av = calc.atoms.positions / Bohr setups = calc.wfs.setups D_asp = calc.density.D_asp KxcPAW_GG = np.zeros_like(Kxc_GG) dG_GGv = np.zeros((npw, npw, 3)) for v in range(3): dG_GGv[:, :, v] = np.subtract.outer(G_Gv[:, v], G_Gv[:, v]) # Distribute computation of PAW correction equally among processes p_r = self.distribute_correction(setups, self.world.size) apdone = 0 npdone = 0 pdone = 0 pdonebefore = np.sum(p_r[:self.world.rank]) pdonenow = pdonebefore + p_r[self.world.rank] for a, setup in enumerate(setups): # PAW correction is evaluated on a radial grid Y_nL = setup.xc_correction.Y_nL rgd = setup.xc_correction.rgd # Continue if computation has been done already nn = len(Y_nL) ng = len(rgd.r_g) apdone += nn * ng if pdonebefore >= apdone or pdone >= pdonenow: npdone += nn * ng pdone += nn * ng continue n_qg = setup.xc_correction.n_qg nt_qg = setup.xc_correction.nt_qg nc_g = setup.xc_correction.nc_g nct_g = setup.xc_correction.nct_g dv_g = rgd.dv_g D_sp = D_asp[a] B_pqL = setup.xc_correction.B_pqL D_sLq = np.inner(D_sp, B_pqL.T) nspins = len(D_sp) f_g = rgd.zeros() ft_g = rgd.zeros() n_sLg = np.dot(D_sLq, n_qg) nt_sLg = np.dot(D_sLq, nt_qg) # Add core density n_sLg[:, 0] += np.sqrt(4. * np.pi) / nspins * nc_g nt_sLg[:, 0] += np.sqrt(4. * np.pi) / nspins * nct_g coefatoms_GG = np.exp(-1j * np.inner(dG_GGv, R_av[a])) for n, Y_L in enumerate(Y_nL): # Continue if computation has been done already npdone += ng if pdonebefore >= npdone or pdone >= pdonenow: pdone += ng continue w = weight_n[n] f_g[:] = 0. n_sg = np.dot(Y_L, n_sLg) add_fxc(rgd, n_sg, f_g) ft_g[:] = 0. nt_sg = np.dot(Y_L, nt_sLg) add_fxc(rgd, nt_sg, ft_g) dG_GG = np.inner(dG_GGv, R_nv[n]) for i in range(len(rgd.r_g)): # Continue if previous ranks already did computation pdone += 1 if pdonebefore >= pdone: continue # Do computation if needed if pdone <= pdonenow: coef_GG = np.exp(-1j * dG_GG * rgd.r_g[i]) KxcPAW_GG += w * coefatoms_GG\ * np.dot(coef_GG, (f_g[i] - ft_g[i]) * dv_g[i]) self.world.sum(KxcPAW_GG) Kxc_GG += KxcPAW_GG return Kxc_GG / vol
x = 2.0 rc = 3.5 r = np.linspace(0, rc, 100) n = 40 a = 8.0 cell_cv = np.array([[a, 0.5, -1], [0, a, 2], [-1, 0, a + 1]]) 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):
def __init__(self, calc, nbands=None, Fock=False): self.calc = calc self.Fock = Fock self.K = calc.get_ibz_k_points() # reduced Brillioun zone self.NK = self.K.shape[0] self.wk = calc.get_k_point_weights( ) # weight of reduced Brillioun zone if nbands is None: self.nbands = calc.get_number_of_bands() else: self.nbands = nbands self.nvalence = int(calc.get_number_of_electrons() / 2) self.EK = [ calc.get_eigenvalues(k)[:self.nbands] for k in range(self.NK) ] # bands energy self.EK = np.array(self.EK) / Hartree self.shape = tuple( calc.get_number_of_grid_points()) # shape of real space grid self.density = calc.get_pseudo_density( ) * Bohr**3 # density at zero time # array of u_nk (periodic part of Kohn-Sham orbitals,only reduced Brillion zone) self.ukn = np.zeros(( self.NK, self.nbands, ) + self.shape, dtype=np.complex) for k in range(self.NK): kpt = calc.wfs.kpt_u[k] for n in range(self.nbands): psit_G = kpt.psit_nG[n] psit_R = calc.wfs.pd.ifft(psit_G, kpt.q) self.ukn[k, n] = psit_R self.icell = 2.0 * np.pi * calc.wfs.gd.icell_cv # inverse cell self.cell = calc.wfs.gd.cell_cv # cell self.r = calc.wfs.gd.get_grid_point_coordinates() for i in range(3): self.r[i] -= self.cell[i, i] / 2. self.volume = np.abs(np.linalg.det( calc.wfs.gd.cell_cv)) # volume of cell self.norm = calc.wfs.gd.dv # self.Fermi = calc.get_fermi_level() / Hartree #Fermi level #desriptors at q=gamma for Hartree self.kdH = KPointDescriptor([[0, 0, 0]]) self.pdH = PWDescriptor(ecut=calc.wfs.pd.ecut, gd=calc.wfs.gd, kd=self.kdH, dtype=complex) #desriptors at q=gamma for Fock self.kdF = KPointDescriptor([[0, 0, 0]]) self.pdF = PWDescriptor(ecut=calc.wfs.pd.ecut / 4., gd=calc.wfs.gd, kd=self.kdF, dtype=complex) #Fermi-Dirac temperature self.temperature = calc.occupations.width #calculate pair-density matrices if Fock: self.M = np.zeros((self.nbands, self.nbands, self.NK, self.NK, self.pdF.get_reciprocal_vectors().shape[0]), dtype=np.complex) indexes = [(n, k) for n, k in product(range(self.nbands), range(self.NK))] for i1 in range(len(indexes)): n1, k1 = indexes[i1] for i2 in range(i1, len(indexes)): n2, k2 = indexes[i1] self.M[n1, n2, k1, k2] = self.pdF.fft( self.ukn[k1, n1].conj() * self.ukn[k2, n2]) self.M[n2, n1, k2, k1] = self.M[n1, n2, k1, k2].conj() self.M *= calc.wfs.gd.dv #Fermi-Dirac distribution self.f = 1 / (1 + np.exp((self.EK - self.Fermi) / self.temperature)) self.Hartree_elements = np.zeros( (self.NK, self.nbands, self.NK, self.nbands, self.nbands), dtype=np.complex) self.LDAx_elements = np.zeros( (self.NK, self.nbands, self.NK, self.nbands, self.nbands), dtype=np.complex) self.LDAc_elements = np.zeros( (self.NK, self.nbands, self.NK, self.nbands, self.nbands), dtype=np.complex) G = self.pdH.get_reciprocal_vectors() G2 = np.linalg.norm(G, axis=1)**2 G2[G2 == 0] = np.inf matrix = np.zeros((self.NK, self.nbands, self.nbands), dtype=np.complex) for k in tqdm(range(self.NK)): for n in range(self.nbands): density = 2 * np.abs(self.ukn[k, n])**2 operator = xc.VLDAx(density) self.LDAx_elements[k, n] = operator_matrix_periodic( matrix, operator, self.ukn.conj(), self.ukn) * self.norm operator = xc.VLDAc(density) self.LDAc_elements[k, n] = operator_matrix_periodic( matrix, operator, self.ukn.conj(), self.ukn) * self.norm density = self.pdH.fft(density) operator = 4 * np.pi * self.pdH.ifft(density / G2) self.Hartree_elements[k, n] = operator_matrix_periodic( matrix, operator, self.ukn.conj(), self.ukn) * self.norm self.wavefunction = np.zeros((self.NK, self.nbands, self.nbands), dtype=np.complex) self.Kinetic = np.zeros((self.NK, self.nbands, self.nbands), dtype=np.complex) self.dipole = self.get_dipole_matrix() for k in range(self.NK): self.wavefunction[k] = np.eye(self.nbands) self.Kinetic[k] = np.diag(self.EK[k]) self.VH0 = self.get_Hartree_matrix(self.wavefunction) self.VLDAc0 = self.get_LDA_correlation_matrix(self.wavefunction) self.VLDAx0 = self.get_LDA_exchange_matrix(self.wavefunction) self.Full_BZ = calc.get_bz_k_points() self.IBZ_map = calc.get_bz_to_ibz_map()
from gpaw.lfc import LocalizedFunctionsCollection as LFC from gpaw.wavefunctions.pw import PWDescriptor, PWLFC from gpaw.kpt_descriptor import KPointDescriptor x = 2.0 rc = 3.5 r = np.linspace(0, rc, 100) n = 40 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))}
def write(self, calc, ecut=40 * Hartree, spacegroup=1): #sg = Spacegroup(spacegroup) #print sg wfs = calc.wfs setups = wfs.setups bd = wfs.bd kd = wfs.kd atoms = calc.atoms natoms = len(atoms) if wfs.symmetry is None: op_scc = np.eye(3, dtype=int).reshape((1, 3, 3)) else: op_scc = wfs.symmetry.op_scc pwd = PWDescriptor(ecut / Hartree, wfs.gd, kd.ibzk_kc) N_c = pwd.gd.N_c i_Qc = np.indices(N_c, np.int32).transpose((1, 2, 3, 0)) i_Qc += N_c // 2 i_Qc %= N_c i_Qc -= N_c // 2 i_Qc.shape = (-1, 3) i_Gc = i_Qc[pwd.Q_G] B_cv = 2.0 * np.pi * wfs.gd.icell_cv G_Qv = np.dot(i_Gc, B_cv).reshape((-1, 3)) G2_Q = (G_Qv**2).sum(axis=1) specie_a = np.empty(natoms, np.int32) nspecies = 0 species = {} names = [] symbols = [] numbers = [] charges = [] for a, id in enumerate(setups.id_a): if id not in species: species[id] = nspecies nspecies += 1 names.append(setups[a].symbol) symbols.append(setups[a].symbol) numbers.append(setups[a].Z) charges.append(setups[a].Nv) specie_a[a] = species[id] dimensions = [('character_string_length', 80), ('max_number_of_coefficients', len(i_Gc)), ('max_number_of_states', bd.nbands), ('number_of_atoms', len(atoms)), ('number_of_atom_species', nspecies), ('number_of_cartesian_directions', 3), ('number_of_components', 1), ('number_of_grid_points_vector1', N_c[0]), ('number_of_grid_points_vector2', N_c[1]), ('number_of_grid_points_vector3', N_c[2]), ('number_of_kpoints', kd.nibzkpts), ('number_of_reduced_dimensions', 3), ('number_of_spinor_components', 1), ('number_of_spins', wfs.nspins), ('number_of_symmetry_operations', len(op_scc)), ('number_of_vectors', 3), ('real_or_complex_coefficients', 2), ('symbol_length', 2)] for name, size in dimensions: print('%-34s %d' % (name, size)) self.nc.createDimension(name, size) var = self.add_variable var('space_group', (), np.array(spacegroup, dtype=int)) var('primitive_vectors', ('number_of_vectors', 'number_of_cartesian_directions'), wfs.gd.cell_cv, units='atomic units') var('reduced_symmetry_matrices', ('number_of_symmetry_operations', 'number_of_reduced_dimensions', 'number_of_reduced_dimensions'), op_scc.astype(np.int32), symmorphic='yes') var('reduced_symmetry_translations', ('number_of_symmetry_operations', 'number_of_reduced_dimensions'), np.zeros((len(op_scc), 3), dtype=np.int32)) var('atom_species', ('number_of_atoms', ), specie_a + 1) var('reduced_atom_positions', ('number_of_atoms', 'number_of_reduced_dimensions'), atoms.get_scaled_positions()) var('atomic_numbers', ('number_of_atom_species', ), np.array(numbers, dtype=float)) var('valence_charges', ('number_of_atom_species', ), np.array(charges, dtype=float)) var('atom_species_names', ('number_of_atom_species', 'character_string_length'), names) var('chemical_symbols', ('number_of_atom_species', 'symbol_length'), symbols) var('pseudopotential_types', ('number_of_atom_species', 'character_string_length'), ['HGH'] * nspecies) var('fermi_energy', (), calc.occupations.fermilevel, units='atomic units') var('smearing_scheme', ('character_string_length', ), 'fermi-dirac') var('smearing_width', (), calc.occupations.width, units='atomic units') var('number_of_states', ('number_of_spins', 'number_of_kpoints'), np.zeros((wfs.nspins, kd.nibzkpts), np.int32) + bd.nbands, k_dependent='no') var('eigenvalues', ('number_of_spins', 'number_of_kpoints', 'max_number_of_states'), np.array([[ calc.get_eigenvalues(k, s) / Hartree for k in range(kd.nibzkpts) ] for s in range(wfs.nspins)]), units='atomic units') var( 'occupations', ('number_of_spins', 'number_of_kpoints', 'max_number_of_states'), np.array([[ calc.get_occupation_numbers(k, s) / kd.weight_k[k] for k in range(kd.nibzkpts) ] for s in range(wfs.nspins)])) var('reduced_coordinates_of_kpoints', ('number_of_kpoints', 'number_of_reduced_dimensions'), kd.ibzk_kc) var('kpoint_weights', ('number_of_kpoints', ), kd.weight_k) var('basis_set', ('character_string_length', ), 'plane_waves') var('kinetic_energy_cutoff', (), 1.0 * ecut, units='atomic units') var('number_of_coefficients', ('number_of_kpoints', ), np.zeros(kd.nibzkpts, np.int32) + len(i_Gc), k_dependent='no') var('reduced_coordinates_of_plane_waves', ('max_number_of_coefficients', 'number_of_reduced_dimensions'), i_Gc[np.argsort(G2_Q)], k_dependent='no') var('number_of_electrons', (), np.array(wfs.nvalence, dtype=np.int32)) #var('exchange_functional', ('character_string_length',), # calc.hamiltonian.xc.name) #var('correlation_functional', ('character_string_length',), # calc.hamiltonian.xc.name) psit_skn1G2 = var( 'coefficients_of_wavefunctions', ('number_of_spins', 'number_of_kpoints', 'max_number_of_states', 'number_of_spinor_components', 'max_number_of_coefficients', 'real_or_complex_coefficients')) x = atoms.get_volume()**0.5 / N_c.prod() psit_Gx = np.empty((len(i_Gc), 2)) for s in range(wfs.nspins): for k in range(kd.nibzkpts): for n in range(bd.nbands): psit_G = pwd.fft(calc.get_pseudo_wave_function( n, k, s))[np.argsort(G2_Q)] psit_G *= x psit_Gx[:, 0] = psit_G.real psit_Gx[:, 1] = psit_G.imag psit_skn1G2[s, k, n, 0] = psit_Gx self.nc.close()
def calculate(self, optical=True, ac=1.0): if self.spinors: """Calculate spinors. Here m is index of eigenvalues with SOC and n is the basis of eigenstates withour SOC. Below m is used for unoccupied states and n is used for occupied states so be careful!""" print('Diagonalizing spin-orbit Hamiltonian', file=self.fd) param = self.calc.parameters if not param['symmetry'] == 'off': print('Calculating KS wavefunctions without symmetry ' + 'for spin-orbit', file=self.fd) if not op.isfile('gs_nosym.gpw'): calc_so = GPAW(**param) calc_so.set(symmetry='off', fixdensity=True, txt='gs_nosym.txt') calc_so.atoms = self.calc.atoms calc_so.density = self.calc.density calc_so.get_potential_energy() calc_so.write('gs_nosym.gpw') calc_so = GPAW('gs_nosym.gpw', txt=None, communicator=serial_comm) e_mk, v_knm = get_spinorbit_eigenvalues(calc_so, return_wfs=True, scale=self.scale) del calc_so else: e_mk, v_knm = get_spinorbit_eigenvalues(self.calc, return_wfs=True, scale=self.scale) e_mk /= Hartree # Parallelization stuff nK = self.kd.nbzkpts myKrange, myKsize, mySsize = self.parallelisation_sizes() # Calculate exchange interaction qd0 = KPointDescriptor([self.q_c]) pd0 = PWDescriptor(self.ecut, self.calc.wfs.gd, complex, qd0) ikq_k = self.kd.find_k_plus_q(self.q_c) v_G = get_coulomb_kernel(pd0, self.kd.N_c, truncation=self.truncation, wstc=self.wstc) if optical: v_G[0] = 0.0 self.pair = PairDensity(self.calc, self.ecut, world=serial_comm, txt='pair.txt') # Calculate direct (screened) interaction and PAW corrections if self.mode == 'RPA': Q_aGii = self.pair.initialize_paw_corrections(pd0) else: self.get_screened_potential(ac=ac) if (self.qd.ibzk_kc - self.q_c < 1.0e-6).all(): iq0 = self.qd.bz2ibz_k[self.kd.where_is_q(self.q_c, self.qd.bzk_kc)] Q_aGii = self.Q_qaGii[iq0] else: Q_aGii = self.pair.initialize_paw_corrections(pd0) # Calculate pair densities, eigenvalues and occupations so = self.spinors + 1 Nv, Nc = so * self.nv, so * self.nc Ns = self.spins rhoex_KsmnG = np.zeros((nK, Ns, Nv, Nc, len(v_G)), complex) # rhoG0_Ksmn = np.zeros((nK, Ns, Nv, Nc), complex) df_Ksmn = np.zeros((nK, Ns, Nv, Nc), float) # -(ev - ec) deps_ksmn = np.zeros((myKsize, Ns, Nv, Nc), float) # -(fv - fc) if np.allclose(self.q_c, 0.0): optical_limit = True else: optical_limit = False get_pair = self.pair.get_kpoint_pair get_rho = self.pair.get_pair_density if self.spinors: # Get all pair densities to allow for SOC mixing # Use twice as many no-SOC states as BSE bands to allow mixing vi_s = [2 * self.val_sn[0, 0] - self.val_sn[0, -1] - 1] vf_s = [2 * self.con_sn[0, -1] - self.con_sn[0, 0] + 2] if vi_s[0] < 0: vi_s[0] = 0 ci_s, cf_s = vi_s, vf_s ni, nf = vi_s[0], vf_s[0] mvi = 2 * self.val_sn[0, 0] mvf = 2 * (self.val_sn[0, -1] + 1) mci = 2 * self.con_sn[0, 0] mcf = 2 * (self.con_sn[0, -1] + 1) else: vi_s, vf_s = self.val_sn[:, 0], self.val_sn[:, -1] + 1 ci_s, cf_s = self.con_sn[:, 0], self.con_sn[:, -1] + 1 for ik, iK in enumerate(myKrange): for s in range(Ns): pair = get_pair(pd0, s, iK, vi_s[s], vf_s[s], ci_s[s], cf_s[s]) m_m = np.arange(vi_s[s], vf_s[s]) n_n = np.arange(ci_s[s], cf_s[s]) if self.gw_skn is not None: iKq = self.calc.wfs.kd.find_k_plus_q(self.q_c, [iK])[0] epsv_m = self.gw_skn[s, iK, :self.nv] epsc_n = self.gw_skn[s, iKq, self.nv:] deps_ksmn[ik] = -(epsv_m[:, np.newaxis] - epsc_n) elif self.spinors: iKq = self.calc.wfs.kd.find_k_plus_q(self.q_c, [iK])[0] epsv_m = e_mk[mvi:mvf, iK] epsc_n = e_mk[mci:mcf, iKq] deps_ksmn[ik, s] = -(epsv_m[:, np.newaxis] - epsc_n) else: deps_ksmn[ik, s] = -pair.get_transition_energies(m_m, n_n) df_mn = pair.get_occupation_differences(self.val_sn[s], self.con_sn[s]) rho_mnG = get_rho(pd0, pair, m_m, n_n, optical_limit=optical_limit, direction=self.direction, Q_aGii=Q_aGii, extend_head=False) if self.spinors: if optical_limit: deps0_mn = -pair.get_transition_energies(m_m, n_n) rho_mnG[:, :, 0] *= deps0_mn df_Ksmn[iK, s, ::2, ::2] = df_mn df_Ksmn[iK, s, ::2, 1::2] = df_mn df_Ksmn[iK, s, 1::2, ::2] = df_mn df_Ksmn[iK, s, 1::2, 1::2] = df_mn vecv0_nm = v_knm[iK][::2][ni:nf, mvi:mvf] vecc0_nm = v_knm[iKq][::2][ni:nf, mci:mcf] rho_0mnG = np.dot(vecv0_nm.T.conj(), np.dot(vecc0_nm.T, rho_mnG)) vecv1_nm = v_knm[iK][1::2][ni:nf, mvi:mvf] vecc1_nm = v_knm[iKq][1::2][ni:nf, mci:mcf] rho_1mnG = np.dot(vecv1_nm.T.conj(), np.dot(vecc1_nm.T, rho_mnG)) rhoex_KsmnG[iK, s] = rho_0mnG + rho_1mnG if optical_limit: rhoex_KsmnG[iK, s, :, :, 0] /= deps_ksmn[ik, s] else: df_Ksmn[iK, s] = pair.get_occupation_differences(m_m, n_n) rhoex_KsmnG[iK, s] = rho_mnG if self.eshift is not None: deps_ksmn[np.where(df_Ksmn[myKrange] > 1.0e-3)] += self.eshift deps_ksmn[np.where(df_Ksmn[myKrange] < -1.0e-3)] -= self.eshift world.sum(df_Ksmn) world.sum(rhoex_KsmnG) self.rhoG0_S = np.reshape(rhoex_KsmnG[:, :, :, :, 0], -1) if hasattr(self, 'H_sS'): return # Calculate Hamiltonian t0 = time() print('Calculating %s matrix elements at q_c = %s' % (self.mode, self.q_c), file=self.fd) H_ksmnKsmn = np.zeros((myKsize, Ns, Nv, Nc, nK, Ns, Nv, Nc), complex) for ik1, iK1 in enumerate(myKrange): for s1 in range(Ns): kptv1 = self.pair.get_k_point(s1, iK1, vi_s[s1], vf_s[s1]) kptc1 = self.pair.get_k_point(s1, ikq_k[iK1], ci_s[s1], cf_s[s1]) rho1_mnG = rhoex_KsmnG[iK1, s1] #rhoG0_Ksmn[iK1, s1] = rho1_mnG[:, :, 0] rho1ccV_mnG = rho1_mnG.conj()[:, :] * v_G for s2 in range(Ns): for Q_c in self.qd.bzk_kc: iK2 = self.kd.find_k_plus_q(Q_c, [kptv1.K])[0] rho2_mnG = rhoex_KsmnG[iK2, s2] rho2_mGn = np.swapaxes(rho2_mnG, 1, 2) H_ksmnKsmn[ik1, s1, :, :, iK2, s2, :, :] += ( np.dot(rho1ccV_mnG, rho2_mGn)) if not self.mode == 'RPA' and s1 == s2: ikq = ikq_k[iK2] kptv2 = self.pair.get_k_point(s1, iK2, vi_s[s1], vf_s[s1]) kptc2 = self.pair.get_k_point(s1, ikq, ci_s[s1], cf_s[s1]) rho3_mmG, iq = self.get_density_matrix(kptv1, kptv2) rho4_nnG, iq = self.get_density_matrix(kptc1, kptc2) if self.spinors: vec0_nm = v_knm[iK1][::2][ni:nf, mvi:mvf] vec1_nm = v_knm[iK1][1::2][ni:nf, mvi:mvf] vec2_nm = v_knm[iK2][::2][ni:nf, mvi:mvf] vec3_nm = v_knm[iK2][1::2][ni:nf, mvi:mvf] rho_0mnG = np.dot(vec0_nm.T.conj(), np.dot(vec2_nm.T, rho3_mmG)) rho_1mnG = np.dot(vec1_nm.T.conj(), np.dot(vec3_nm.T, rho3_mmG)) rho3_mmG = rho_0mnG + rho_1mnG vec0_nm = v_knm[ikq_k[iK1]][::2][ni:nf, mci:mcf] vec1_nm = v_knm[ikq_k[iK1]][1::2][ni:nf,mci:mcf] vec2_nm = v_knm[ikq][::2][ni:nf, mci:mcf] vec3_nm = v_knm[ikq][1::2][ni:nf, mci:mcf] rho_0mnG = np.dot(vec0_nm.T.conj(), np.dot(vec2_nm.T, rho4_nnG)) rho_1mnG = np.dot(vec1_nm.T.conj(), np.dot(vec3_nm.T, rho4_nnG)) rho4_nnG = rho_0mnG + rho_1mnG rho3ccW_mmG = np.dot(rho3_mmG.conj(), self.W_qGG[iq]) W_mmnn = np.dot(rho3ccW_mmG, np.swapaxes(rho4_nnG, 1, 2)) W_mnmn = np.swapaxes(W_mmnn, 1, 2) * Ns * so H_ksmnKsmn[ik1, s1, :, :, iK2, s1] -= 0.5 * W_mnmn if iK1 % (myKsize // 5 + 1) == 0: dt = time() - t0 tleft = dt * myKsize / (iK1 + 1) - dt print(' Finished %s pair orbitals in %s - Estimated %s left' % ((iK1 + 1) * Nv * Nc * Ns * world.size, timedelta(seconds=round(dt)), timedelta(seconds=round(tleft))), file=self.fd) #if self.mode == 'BSE': # del self.Q_qaGii, self.W_qGG, self.pd_q H_ksmnKsmn /= self.vol mySsize = myKsize * Nv * Nc * Ns if myKsize > 0: iS0 = myKrange[0] * Nv * Nc * Ns #world.sum(rhoG0_Ksmn) #self.rhoG0_S = np.reshape(rhoG0_Ksmn, -1) self.df_S = np.reshape(df_Ksmn, -1) if not self.td: self.excludef_S = np.where(np.abs(self.df_S) < 0.001)[0] # multiply by 2 when spin-paired and no SOC self.df_S *= 2.0 / nK / Ns / so self.deps_s = np.reshape(deps_ksmn, -1) H_sS = np.reshape(H_ksmnKsmn, (mySsize, self.nS)) for iS in range(mySsize): # Multiply by occupations and adiabatic coupling H_sS[iS] *= self.df_S[iS0 + iS] * ac # add bare transition energies H_sS[iS, iS0 + iS] += self.deps_s[iS] self.H_sS = H_sS if self.write_h: self.par_save('H_SS.ulm', 'H_SS', self.H_sS)
def initialize(self, density, hamiltonian, wfs, occupations): self.xc.initialize(density, hamiltonian, wfs, occupations) self.nspins = wfs.nspins self.setups = wfs.setups self.density = density self.kpt_u = wfs.kpt_u self.wfs = wfs self.gd = density.gd self.kd = wfs.kd self.bd = wfs.bd N_c = self.gd.N_c N = self.gd.N_c.prod() vol = self.gd.dv * N if self.alpha is None: # XXX ? self.alpha = 6 * vol**(2 / 3.0) / pi**2 self.gamma = (vol / (2 * pi)**2 * sqrt(pi / self.alpha) * self.kd.nbzkpts) if self.ecut is None: self.ecut = 0.5 * pi**2 / (self.gd.h_cv**2).sum(1).max() * 0.9999 assert self.kd.N_c is not None n = self.kd.N_c * 2 - 1 bzk_kc = np.indices(n).transpose((1, 2, 3, 0)) bzk_kc.shape = (-1, 3) bzk_kc -= self.kd.N_c - 1 self.bzk_kc = bzk_kc.astype(float) / self.kd.N_c self.bzq_qc = self.kd.get_bz_q_points() if self.qsym: op_scc = self.kd.symmetry.op_scc self.ibzq_qc = self.kd.get_ibz_q_points(self.bzq_qc, op_scc)[0] self.q_weights = self.kd.q_weights * len(self.bzq_qc) else: self.ibzq_qc = self.bzq_qc self.q_weights = np.ones(len(self.bzq_qc)) self.pwd = PWDescriptor(self.ecut, self.gd, complex) self.G2_qG = self.pwd.g2(self.bzk_kc) n = 0 for k_c, Gpk2_G in zip(self.bzk_kc[:], self.G2_qG): if (k_c > -0.5).all() and (k_c <= 0.5).all(): #XXX??? if k_c.any(): self.gamma -= np.dot(np.exp(-self.alpha * Gpk2_G), Gpk2_G**-1) else: self.gamma -= np.dot(np.exp(-self.alpha * Gpk2_G[1:]), Gpk2_G[1:]**-1) n += 1 assert n == self.kd.N_c.prod() self.pwd = PWDescriptor(self.ecut, self.gd, complex) self.G2_qG = self.pwd.g2(self.ibzq_qc) self.ghat = LFC(self.gd, [setup.ghat_l for setup in density.setups], KPointDescriptor(self.bzq_qc), dtype=complex) #self.interpolator = density.interpolator self.print_initialization(hamiltonian.xc.name)
def calculate_screened_potential(self, ac): """Calculate W_GG(q)""" chi0 = Chi0(self.calc, frequencies=[0.0], eta=0.001, ecut=self.ecut, intraband=False, hilbert=False, nbands=self.nbands, txt='chi0.txt', world=world, ) self.blockcomm = chi0.blockcomm wfs = self.calc.wfs self.Q_qaGii = [] self.W_qGG = [] self.pd_q = [] t0 = time() print('Calculating screened potential', file=self.fd) for iq, q_c in enumerate(self.qd.ibzk_kc): thisqd = KPointDescriptor([q_c]) pd = PWDescriptor(self.ecut, wfs.gd, complex, thisqd) nG = pd.ngmax chi0.Ga = self.blockcomm.rank * nG chi0.Gb = min(chi0.Ga + nG, nG) chi0_wGG = np.zeros((1, nG, nG), complex) if np.allclose(q_c, 0.0): chi0_wxvG = np.zeros((1, 2, 3, nG), complex) chi0_wvv = np.zeros((1, 3, 3), complex) else: chi0_wxvG = None chi0_wvv = None chi0._calculate(pd, chi0_wGG, chi0_wxvG, chi0_wvv, 0, self.nbands, spins='all', extend_head=False) chi0_GG = chi0_wGG[0] # Calculate eps^{-1}_GG if pd.kd.gamma: # Generate fine grid in vicinity of gamma kd = self.calc.wfs.kd N = 4 N_c = np.array([N, N, N]) if self.truncation is not None: # Only average periodic directions if trunction is used N_c[kd.N_c == 1] = 1 qf_qc = monkhorst_pack(N_c) / kd.N_c qf_qc *= 1.0e-6 U_scc = kd.symmetry.op_scc qf_qc = kd.get_ibz_q_points(qf_qc, U_scc)[0] weight_q = kd.q_weights qf_qv = 2 * np.pi * np.dot(qf_qc, pd.gd.icell_cv) a_q = np.sum(np.dot(chi0_wvv[0], qf_qv.T) * qf_qv.T, axis=0) a0_qG = np.dot(qf_qv, chi0_wxvG[0, 0]) a1_qG = np.dot(qf_qv, chi0_wxvG[0, 1]) einv_GG = np.zeros((nG, nG), complex) # W_GG = np.zeros((nG, nG), complex) for iqf in range(len(qf_qv)): chi0_GG[0] = a0_qG[iqf] chi0_GG[:, 0] = a1_qG[iqf] chi0_GG[0, 0] = a_q[iqf] sqrV_G = get_coulomb_kernel(pd, kd.N_c, truncation=self.truncation, wstc=self.wstc, q_v=qf_qv[iqf])**0.5 sqrV_G *= ac**0.5 # Multiply by adiabatic coupling e_GG = np.eye(nG) - chi0_GG * sqrV_G * sqrV_G[:, np.newaxis] einv_GG += np.linalg.inv(e_GG) * weight_q[iqf] # einv_GG = np.linalg.inv(e_GG) * weight_q[iqf] # W_GG += (einv_GG * sqrV_G * sqrV_G[:, np.newaxis] # * weight_q[iqf]) else: sqrV_G = get_coulomb_kernel(pd, self.kd.N_c, truncation=self.truncation, wstc=self.wstc)**0.5 sqrV_G *= ac**0.5 # Multiply by adiabatic coupling e_GG = np.eye(nG) - chi0_GG * sqrV_G * sqrV_G[:, np.newaxis] einv_GG = np.linalg.inv(e_GG) # W_GG = einv_GG * sqrV_G * sqrV_G[:, np.newaxis] # Now calculate W_GG if pd.kd.gamma: # Reset bare Coulomb interaction sqrV_G = get_coulomb_kernel(pd, self.kd.N_c, truncation=self.truncation, wstc=self.wstc)**0.5 W_GG = einv_GG * sqrV_G * sqrV_G[:, np.newaxis] if self.integrate_gamma != 0: # Numerical integration of Coulomb interaction at all q-points if self.integrate_gamma == 2: reduced = True else: reduced = False V0, sqrV0 = get_integrated_kernel(pd, self.kd.N_c, truncation=self.truncation, reduced=reduced, N=100) W_GG[0, 0] = einv_GG[0, 0] * V0 W_GG[0, 1:] = einv_GG[0, 1:] * sqrV0 * sqrV_G[1:] W_GG[1:, 0] = einv_GG[1:, 0] * sqrV_G[1:] * sqrV0 elif self.integrate_gamma == 0 and pd.kd.gamma: # Analytical integration at gamma bzvol = (2 * np.pi)**3 / self.vol / self.qd.nbzkpts Rq0 = (3 * bzvol / (4 * np.pi))**(1. / 3.) V0 = 16 * np.pi**2 * Rq0 / bzvol sqrV0 = (4 * np.pi)**(1.5) * Rq0**2 / bzvol / 2 W_GG[0, 0] = einv_GG[0, 0] * V0 W_GG[0, 1:] = einv_GG[0, 1:] * sqrV0 * sqrV_G[1:] W_GG[1:, 0] = einv_GG[1:, 0] * sqrV_G[1:] * sqrV0 else: pass if pd.kd.gamma: e = 1 / einv_GG[0, 0].real print(' RPA dielectric constant is: %3.3f' % e, file=self.fd) self.Q_qaGii.append(chi0.Q_aGii) self.pd_q.append(pd) self.W_qGG.append(W_GG) if iq % (self.qd.nibzkpts // 5 + 1) == 2: dt = time() - t0 tleft = dt * self.qd.nibzkpts / (iq + 1) - dt print(' Finished %s q-points in %s - Estimated %s left' % (iq + 1, timedelta(seconds=round(dt)), timedelta(seconds=round(tleft))), file=self.fd)
a = Atoms('H', cell=(3 * np.eye(3)), pbc=True) calc = GPAW(mode=PW(600), kpts=[[0, 0, 0], [0.25, 0, 0]]) a.calc = calc a.get_potential_energy() calc.diagonalize_full_hamiltonian(nbands=nb, expert=True) calc.write('a.gpw', 'all') pair = PairDensity('a.gpw', ecut=100) # Check continuity eq. for q_c in [[0, 0, 0], [1. / 4, 0, 0]]: ol = np.allclose(q_c, 0.0) qd = KPointDescriptor([q_c]) pd = PWDescriptor(pair.ecut, calc.wfs.gd, complex, qd) kptpair = pair.get_kpoint_pair(pd, 0, [0, 0, 0], 0, nb, 0, nb) deps_nm = kptpair.get_transition_energies(np.arange(0, nb), np.arange(0, nb)) n_nmG = pair.get_pair_density(pd, kptpair, np.arange(0, nb), np.arange(0, nb), optical_limit=ol) n_nmvG = pair.get_pair_momentum(pd, kptpair, np.arange(0, nb), np.arange(0, nb)) if ol: n2_nmv = np.zeros((nb, nb, 3), complex)
from gpaw.wavefunctions.pw import PWDescriptor, PWLFC from gpaw.kpt_descriptor import KPointDescriptor x = 2.0 rc = 3.5 r = np.linspace(0, rc, 100) n = 40 a = 8.0 gd = GridDescriptor((n, n, n), (a, a, a), comm=mpi.serial_comm) kpts = np.array([(0.25, 0.25, 0.0)]) kd = KPointDescriptor(kpts) 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)}