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)
Esempio n. 2
0
    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
Esempio n. 3
0
    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)
Esempio n. 4
0
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)
Esempio n. 5
0
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]],
Esempio n. 6
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
Esempio n. 7
0
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)