Пример #1
0
    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)
Пример #2
0
    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')
Пример #3
0
    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))
Пример #4
0
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
Пример #5
0
 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
Пример #6
0
    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
Пример #7
0
    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
Пример #8
0
    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()
Пример #9
0
    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
Пример #10
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)
Пример #11
0
    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)
Пример #12
0
    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
Пример #13
0
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)
Пример #14
0
    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
Пример #15
0
    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
Пример #16
0
 def __init__(self, gd1, gd2, dtype=float):
     self.pd1 = PWDescriptor(0.0, gd1, dtype)
     self.pd2 = PWDescriptor(0.0, gd2, dtype)
Пример #17
0
    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
Пример #18
0
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):
Пример #19
0
    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()
Пример #20
0
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))}
Пример #21
0
    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()
Пример #22
0
    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)
Пример #23
0
    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)
Пример #24
0
    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)
Пример #25
0
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)
Пример #26
0
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)}