示例#1
0
    def expand_hamiltonian_matrix(self):
        """Construct K_p from individual h_nn for each l."""
        ni = sum([2 * l + 1 for l in self.l_j])
        nj = len(self.l_j)

        H_ii = np.zeros((ni, ni))
        if len(self.data['DIJ']) == 0:
            return pack2(H_ii)

        # Multiply by 4.
        # I think the factor of 4 compensates for the fact that the projectors
        # all had square norms of 4, but we brought them back down to 1
        # because that's more sensible.
        H_jj = 4.0 * self.data['DIJ'].reshape((nj, nj))
        m1start = 0
        for j1, l1 in enumerate(self.l_j):
            j1 = self.jargs[j1]
            m1stop = m1start + 2 * l1 + 1
            m2start = 0
            for j2, l2 in enumerate(self.l_j):
                j2 = self.jargs[j2]
                m2stop = m2start + 2 * l2 + 1
                if l1 == l2:
                    dm = m1stop - m1start
                    H_ii[m1start:m1stop, m2start:m2stop] = \
                        np.eye(dm) * H_jj[j1, j2]
                else:
                    assert H_jj[j1, j2] == 0.0
                m2start = m2stop
            m1start = m1stop
        return pack2(H_ii)
示例#2
0
文件: upf.py 项目: robwarm/gpaw-symm
    def expand_hamiltonian_matrix(self):
        """Construct K_p from individual h_nn for each l."""
        ni = sum([2 * l + 1 for l in self.l_j])
        nj = len(self.l_j)

        H_ii = np.zeros((ni, ni))
        if len(self.data['DIJ']) == 0:
            return pack2(H_ii)
        
        # Multiply by 4.
        # I think the factor of 4 compensates for the fact that the projectors
        # all had square norms of 4, but we brought them back down to 1
        # because that's more sensible.
        H_jj = 4.0 * self.data['DIJ'].reshape((nj, nj))
        m1start = 0
        for j1, l1 in enumerate(self.l_j):
            j1 = self.jargs[j1]
            m1stop = m1start + 2 * l1 + 1
            m2start = 0
            for j2, l2 in enumerate(self.l_j):
                j2 = self.jargs[j2]
                m2stop = m2start + 2 * l2 + 1
                if l1 == l2:
                    dm = m1stop - m1start
                    H_ii[m1start:m1stop, m2start:m2stop] = \
                        np.eye(dm) * H_jj[j1, j2]
                else:
                    assert H_jj[j1, j2] == 0.0
                m2start = m2stop
            m1start = m1stop
        return pack2(H_ii)
示例#3
0
文件: hgh.py 项目: robwarm/gpaw-symm
    def expand_hamiltonian_matrix(self):
        """Construct K_p from individual h_nn for each l."""
        ni = sum([2 * l + 1 for l in self.l_j])

        H_ii = np.zeros((ni, ni))

        # The H_ii used in gpaw is much larger and more general than the one
        # required for HGH pseudopotentials.  This means a lot of the elements
        # must be assigned the same value.  Not a performance issue though,
        # since these are small matrices
        M1start = 0
        for n1, l1 in self.hghdata.nl_iter():
            M1end = M1start + 2 * l1 + 1
            M2start = 0
            v = self.hghdata.v_l[l1]
            for n2, l2 in self.hghdata.nl_iter():
                M2end = M2start + 2 * l2 + 1
                if l1 == l2:
                    h_nn = v.expand_hamiltonian_diagonal()
                    H_mm = np.identity(M2end - M2start) * h_nn[n1, n2]
                    H_ii[M1start:M1end, M2start:M2end] += H_mm
                M2start = M2end
            M1start = M1end
        K_p = pack2(H_ii)
        return K_p
示例#4
0
    def expand_hamiltonian_matrix(self):
        """Construct K_p from individual h_nn for each l."""
        ni = sum([2 * l + 1 for l in self.l_j])

        H_ii = np.zeros((ni, ni))

        # The H_ii used in gpaw is much larger and more general than the one
        # required for HGH pseudopotentials.  This means a lot of the elements
        # must be assigned the same value.  Not a performance issue though,
        # since these are small matrices
        M1start = 0
        for n1, l1 in self.hghdata.nl_iter():
            M1end = M1start + 2 * l1 + 1
            M2start = 0
            v = self.hghdata.v_l[l1]
            for n2, l2 in self.hghdata.nl_iter():
                M2end = M2start + 2 * l2 + 1
                if l1 == l2:
                    h_nn = v.expand_hamiltonian_diagonal()
                    H_mm = np.identity(M2end - M2start) * h_nn[n1, n2]
                    H_ii[M1start:M1end, M2start:M2end] += H_mm
                M2start = M2end
            M1start = M1end
        K_p = pack2(H_ii)
        return K_p
示例#5
0
文件: hubbard.py 项目: thonmaker/gpaw
def hubbard(setup, D_sp):
    nspins = len(D_sp)

    l_j = setup.l_j
    l = setup.Hubl
    scale = setup.Hubs
    nl = np.where(np.equal(l_j, l))[0]
    nn = (2 * np.array(l_j) + 1)[0:nl[0]].sum()

    e_xc = 0.0
    dH_sp = []

    s = 0
    for D_p in D_sp:
        N_mm, V = aoom(setup, unpack2(D_p), l, scale)
        N_mm = N_mm / 2 * nspins

        if nspins == 4:
            N_mm = N_mm / 2.0
            if s == 0:
                Eorb = setup.HubU / 2. * (N_mm -
                                          0.5 * np.dot(N_mm, N_mm)).trace()

                Vorb = setup.HubU / 2. * (np.eye(2 * l + 1) - N_mm)

            else:
                Eorb = setup.HubU / 2. * (-0.5 * np.dot(N_mm, N_mm)).trace()

                Vorb = -setup.HubU / 2. * N_mm
        else:
            Eorb = setup.HubU / 2. * (N_mm - np.dot(N_mm, N_mm)).trace()

            Vorb = setup.HubU * (0.5 * np.eye(2 * l + 1) - N_mm)

        e_xc += Eorb
        if nspins == 1:
            # add contribution of other spin manyfold
            e_xc += Eorb

        if len(nl) == 2:
            mm = (2 * np.array(l_j) + 1)[0:nl[1]].sum()

            V[nn:nn + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb
            V[mm:mm + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb
            V[nn:nn + 2 * l + 1, mm:mm + 2 * l + 1] *= Vorb
            V[mm:mm + 2 * l + 1, mm:mm + 2 * l + 1] *= Vorb
        else:
            V[nn:nn + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb

        dH_sp.append(pack2(V))
        s += 1

    return e_xc, dH_sp
示例#6
0
def constructX(gen, gamma=0):
    """Construct the X_p^a matrix for the given atom.

    The X_p^a matrix describes the valence-core interactions of the
    partial waves.
    """
    # initialize attributes
    uv_j = gen.vu_j  # soft valence states * r:
    lv_j = gen.vl_j  # their repective l quantum numbers
    Nvi = 0
    for l in lv_j:
        Nvi += 2 * l + 1  # total number of valence states (including m)

    # number of core and valence orbitals (j only, i.e. not m-number)
    Njcore = gen.njcore
    Njval = len(lv_j)

    # core states * r:
    uc_j = gen.u_j[:Njcore]
    r, dr, N = gen.r, gen.dr, gen.N
    r2 = r**2

    # potential times radius
    vr = np.zeros(N)

    # initialize X_ii matrix
    X_ii = np.zeros((Nvi, Nvi))

    # make gaunt coeff. list
    lmax = max(gen.l_j[:Njcore] + gen.vl_j)
    G_LLL = gaunt(lmax=lmax)

    # sum over core states
    for jc in range(Njcore):
        lc = gen.l_j[jc]

        # sum over first valence state index
        i1 = 0
        for jv1 in range(Njval):
            lv1 = lv_j[jv1]

            # electron density 1 times radius times length element
            n1c = uv_j[jv1] * uc_j[jc] * dr
            n1c[1:] /= r[1:]

            # sum over second valence state index
            i2 = 0
            for jv2 in range(Njval):
                lv2 = lv_j[jv2]

                # electron density 2
                n2c = uv_j[jv2] * uc_j[jc]
                n2c[1:] /= r2[1:]

                # sum expansion in angular momenta
                for l in range(min(lv1, lv2) + lc + 1):
                    # Int density * potential * r^2 * dr:
                    if gamma == 0:
                        vr = gen.rgd.poisson(n2c, l)
                    else:
                        vr = gen.rgd.yukawa(n2c, l, gamma)
                    nv = np.dot(n1c, vr)

                    # expansion coefficients
                    A_mm = X_ii[i1:i1 + 2 * lv1 + 1, i2:i2 + 2 * lv2 + 1]
                    for mc in range(2 * lc + 1):
                        for m in range(2 * l + 1):
                            G1c = G_LLL[lv1**2:(lv1 + 1)**2, lc**2 + mc,
                                        l**2 + m]
                            G2c = G_LLL[lv2**2:(lv2 + 1)**2, lc**2 + mc,
                                        l**2 + m]
                            A_mm += nv * np.outer(G1c, G2c)
                i2 += 2 * lv2 + 1
            i1 += 2 * lv1 + 1

    # pack X_ii matrix
    X_p = pack2(X_ii)
    return X_p
示例#7
0
def constructX(gen):
    """Construct the X_p^a matrix for the given atom.

    The X_p^a matrix describes the valence-core interactions of the
    partial waves.
    """
    # initialize attributes
    uv_j = gen.vu_j    # soft valence states * r:
    lv_j = gen.vl_j    # their repective l quantum numbers
    Nvi  = 0 
    for l in lv_j:
        Nvi += 2 * l + 1   # total number of valence states (including m)

    # number of core and valence orbitals (j only, i.e. not m-number)
    Njcore = gen.njcore
    Njval  = len(lv_j)

    # core states * r:
    uc_j = gen.u_j[:Njcore]
    r, dr, N, beta = gen.r, gen.dr, gen.N, gen.beta

    # potential times radius
    vr = np.zeros(N)
        
    # initialize X_ii matrix
    X_ii = np.zeros((Nvi, Nvi))

    # make gaunt coeff. list
    lmax = max(gen.l_j[:Njcore] + gen.vl_j)
    gaunt = make_gaunt(lmax=lmax)

    # sum over core states
    for jc in range(Njcore):
        lc = gen.l_j[jc]

        # sum over first valence state index
        i1 = 0
        for jv1 in range(Njval):
            lv1 = lv_j[jv1] 

            # electron density 1 times radius times length element
            n1c = uv_j[jv1] * uc_j[jc] * dr
            n1c[1:] /= r[1:]

            # sum over second valence state index
            i2 = 0
            for jv2 in range(Njval):
                lv2 = lv_j[jv2]
                
                # electron density 2
                n2c = uv_j[jv2] * uc_j[jc] * dr
                n2c[1:] /= r[1:]
            
                # sum expansion in angular momenta
                for l in range(min(lv1, lv2) + lc + 1):
                    # Int density * potential * r^2 * dr:
                    hartree(l, n2c, beta, N, vr)
                    nv = np.dot(n1c, vr)
                    
                    # expansion coefficients
                    A_mm = X_ii[i1:i1 + 2 * lv1 + 1, i2:i2 + 2 * lv2 + 1]
                    for mc in range(2 * lc + 1):
                        for m in range(2 * l + 1):
                            G1c = gaunt[lv1**2:(lv1 + 1)**2,
                                        lc**2 + mc, l**2 + m]
                            G2c = gaunt[lv2**2:(lv2 + 1)**2,
                                        lc**2 + mc, l**2 + m]
                            A_mm += nv * np.outer(G1c, G2c)
                i2 += 2 * lv2 + 1
            i1 += 2 * lv1 + 1

    # pack X_ii matrix
    X_p = pack2(X_ii)
    return X_p
示例#8
0
    def make_paw_setup(self, tag=None):
        aea = self.aea

        setup = SetupData(aea.symbol, aea.xc.name, tag, readxml=False)

        nj = sum(len(waves) for waves in self.waves_l)
        setup.e_kin_jj = np.zeros((nj, nj))
        setup.id_j = []
        j1 = 0
        for l, waves in enumerate(self.waves_l):
            ne = 0
            for n, f, e, phi_g, phit_g, pt_g in zip(waves.n_n, waves.f_n,
                                                    waves.e_n, waves.phi_ng,
                                                    waves.phit_ng,
                                                    waves.pt_ng):
                setup.append(n, l, f, e, waves.rcut, phi_g, phit_g, pt_g)
                if n == -1:
                    ne += 1
                    id = '%s-%s%d' % (aea.symbol, 'spdf'[l], ne)
                else:
                    id = '%s-%d%s' % (aea.symbol, n, 'spdf'[l])
                setup.id_j.append(id)
            j2 = j1 + len(waves)
            setup.e_kin_jj[j1:j2, j1:j2] = waves.dekin_nn
            j1 = j2

        setup.nc_g = self.nc_g * sqrt(4 * pi)
        setup.nct_g = self.nct_g * sqrt(4 * pi)
        setup.e_kinetic_core = self.ekincore
        setup.vbar_g = self.v0r_g * sqrt(4 * pi)
        setup.vbar_g[1:] /= self.rgd.r_g[1:]
        setup.vbar_g[0] = setup.vbar_g[1]
        setup.Z = aea.Z
        setup.Nc = self.ncore
        setup.Nv = self.nvalence
        setup.e_kinetic = aea.ekin
        setup.e_xc = aea.exc
        setup.e_electrostatic = aea.eH + aea.eZ
        setup.e_total = aea.exc + aea.ekin + aea.eH + aea.eZ
        setup.rgd = self.rgd
        setup.rcgauss = 1 / sqrt(self.alpha)

        self.calculate_exx_integrals()
        setup.ExxC = self.exxcc
        setup.X_p = pack2(self.exxcv_ii)

        setup.tauc_g = self.rgd.zeros()
        setup.tauct_g = self.rgd.zeros()
        #print 'no tau!!!!!!!!!!!'

        if self.aea.scalar_relativistic:
            reltype = 'scalar-relativistic'
        else:
            reltype = 'non-relativistic'
        attrs = [('type', reltype),
                 ('version', 2),
                 ('name', 'gpaw-%s' % version)]
        setup.generatorattrs = attrs

        setup.l0 = self.l0
        setup.e0 = self.e0
        setup.r0 = self.r0
        setup.nderiv0 = self.nderiv0

        return setup
示例#9
0
    def make_paw_setup(self, tag=None):
        aea = self.aea

        from gpaw.setup_data import SetupData
        setup = SetupData(aea.symbol, aea.xc.name, tag, readxml=False)

        setup.id_j = []

        J = []  # new reordered j and i indices
        I = []

        # Bound states:
        j = 0
        i = 0
        for l, waves in enumerate(self.waves_l):
            for n, f, e, phi_g, phit_g, pt_g in zip(waves.n_n, waves.f_n,
                                                    waves.e_n, waves.phi_ng,
                                                    waves.phit_ng,
                                                    waves.pt_ng):
                if n != -1:
                    setup.append(n, l, f, e, waves.rcut, phi_g, phit_g, pt_g)
                    id = '%d%s' % (n, 'spdf'[l])
                    setup.id_j.append(id)
                    J.append(j)
                    I.extend(range(i, i + 2 * l + 1))
                j += 1
                i += 2 * l + 1

        # Excited states:
        j = 0
        i = 0
        for l, waves in enumerate(self.waves_l):
            ne = 0
            for n, f, e, phi_g, phit_g, pt_g in zip(waves.n_n, waves.f_n,
                                                    waves.e_n, waves.phi_ng,
                                                    waves.phit_ng,
                                                    waves.pt_ng):
                if n == -1:
                    setup.append(n, l, f, e, waves.rcut, phi_g, phit_g, pt_g)
                    ne += 1
                    id = '%s%d' % ('spdf'[l], ne)
                    setup.id_j.append(id)
                    J.append(j)
                    I.extend(range(i, i + 2 * l + 1))
                j += 1
                i += 2 * l + 1

        nj = sum(len(waves) for waves in self.waves_l)
        e_kin_jj = np.zeros((nj, nj))
        j1 = 0
        for waves in self.waves_l:
            j2 = j1 + len(waves)
            e_kin_jj[j1:j2, j1:j2] = waves.dekin_nn
            j1 = j2
        setup.e_kin_jj = e_kin_jj[J][:, J].copy()

        setup.nc_g = self.nc_g * sqrt(4 * pi)
        setup.nct_g = self.nct_g * sqrt(4 * pi)
        setup.e_kinetic_core = self.ekincore
        setup.vbar_g = self.v0r_g * sqrt(4 * pi)
        setup.vbar_g[1:] /= self.rgd.r_g[1:]
        setup.vbar_g[0] = setup.vbar_g[1]
        setup.Z = aea.Z
        setup.Nc = self.ncore
        setup.Nv = self.nvalence
        setup.e_kinetic = aea.ekin
        setup.e_xc = aea.exc
        setup.e_electrostatic = aea.eH + aea.eZ
        setup.e_total = aea.exc + aea.ekin + aea.eH + aea.eZ
        setup.rgd = self.rgd
        setup.rcgauss = 1 / sqrt(self.alpha)

        self.calculate_exx_integrals()
        setup.ExxC = self.exxcc
        setup.X_p = pack2(self.exxcv_ii[I][:, I])

        setup.tauc_g = self.tauc_g * (4 * pi)**0.5
        setup.tauct_g = self.tauct_g * (4 * pi)**0.5

        if self.aea.scalar_relativistic:
            reltype = 'scalar-relativistic'
        else:
            reltype = 'non-relativistic'
        attrs = [('type', reltype), ('version', 2),
                 ('name', 'gpaw-%s' % version)]
        setup.generatorattrs = attrs

        setup.l0 = self.l0
        setup.e0 = 0.0
        setup.r0 = self.r0
        setup.nderiv0 = self.nderiv0

        setup.basis = self.basis

        if self.core_hole:
            n, l, occ = self.core_hole
            phi_g = self.aea.channels[l].phi_ng[n - l - 1]
            setup.ncorehole = n
            setup.lcorehole = l
            setup.fcorehole = occ
            setup.phicorehole_g = phi_g
            setup.has_corehole = True

        return setup
    def update(self, density):
        """Calculate effective potential.

        The XC-potential and the Hartree potential are evaluated on
        the fine grid, and the sum is then restricted to the coarse
        grid."""

        self.timer.start("Hamiltonian")

        if self.vt_sg is None:
            self.timer.start("Initialize Hamiltonian")
            self.vt_sg = self.finegd.empty(self.ns)
            self.vHt_g = self.finegd.zeros()
            self.vt_sG = self.gd.empty(self.ns)
            self.poisson.initialize()
            self.timer.stop("Initialize Hamiltonian")

        Ekin, Epot, Ebar, Eext, Exc, W_aL = self.update_pseudo_potential(density)

        self.timer.start("Atomic")
        self.dH_asp = None  # XXXX

        dH_asp = {}
        for a, D_sp in density.D_asp.items():
            W_L = W_aL[a]
            setup = self.setups[a]

            D_p = D_sp[: self.nspins].sum(0)
            dH_p = setup.K_p + setup.M_p + setup.MB_p + 2.0 * np.dot(setup.M_pp, D_p) + np.dot(setup.Delta_pL, W_L)
            Ekin += np.dot(setup.K_p, D_p) + setup.Kc
            Ebar += setup.MB + np.dot(setup.MB_p, D_p)
            Epot += setup.M + np.dot(D_p, (setup.M_p + np.dot(setup.M_pp, D_p)))

            if self.vext is not None:
                vext = self.vext.get_taylor(spos_c=self.spos_ac[a, :])
                # Tailor expansion to the zeroth order
                Eext += vext[0][0] * (sqrt(4 * pi) * density.Q_aL[a][0] + setup.Z)
                dH_p += vext[0][0] * sqrt(4 * pi) * setup.Delta_pL[:, 0]
                if len(vext) > 1:
                    # Tailor expansion to the first order
                    Eext += sqrt(4 * pi / 3) * np.dot(vext[1], density.Q_aL[a][1:4])
                    # there must be a better way XXXX
                    Delta_p1 = np.array([setup.Delta_pL[:, 1], setup.Delta_pL[:, 2], setup.Delta_pL[:, 3]])
                    dH_p += sqrt(4 * pi / 3) * np.dot(vext[1], Delta_p1)

            dH_asp[a] = dH_sp = np.zeros_like(D_sp)

            if setup.HubU is not None:
                assert self.collinear
                nspins = len(D_sp)

                l_j = setup.l_j
                l = setup.Hubl
                scale = setup.Hubs
                nl = np.where(np.equal(l_j, l))[0]
                nn = (2 * np.array(l_j) + 1)[0 : nl[0]].sum()

                for D_p, H_p in zip(D_sp, dH_asp[a]):
                    [N_mm, V] = self.aoom(unpack2(D_p), a, l, scale)
                    N_mm = N_mm / 2 * nspins

                    Eorb = setup.HubU / 2.0 * (N_mm - np.dot(N_mm, N_mm)).trace()
                    Vorb = setup.HubU * (0.5 * np.eye(2 * l + 1) - N_mm)
                    Exc += Eorb
                    if nspins == 1:
                        # add contribution of other spin manyfold
                        Exc += Eorb

                    if len(nl) == 2:
                        mm = (2 * np.array(l_j) + 1)[0 : nl[1]].sum()

                        V[nn : nn + 2 * l + 1, nn : nn + 2 * l + 1] *= Vorb
                        V[mm : mm + 2 * l + 1, nn : nn + 2 * l + 1] *= Vorb
                        V[nn : nn + 2 * l + 1, mm : mm + 2 * l + 1] *= Vorb
                        V[mm : mm + 2 * l + 1, mm : mm + 2 * l + 1] *= Vorb
                    else:
                        V[nn : nn + 2 * l + 1, nn : nn + 2 * l + 1] *= Vorb

                    Htemp = unpack(H_p)
                    Htemp += V
                    H_p[:] = pack2(Htemp)

            dH_sp[: self.nspins] += dH_p
            if self.ref_dH_asp:
                dH_sp += self.ref_dH_asp[a]
            # We are not yet done with dH_sp; still need XC correction below

        Ddist_asp = self.dh_distributor.distribute(density.D_asp)

        dHdist_asp = {}
        Exca = 0.0
        self.timer.start("XC Correction")
        for a, D_sp in Ddist_asp.items():
            setup = self.setups[a]
            dH_sp = np.zeros_like(D_sp)
            Exca += self.xc.calculate_paw_correction(setup, D_sp, dH_sp, a=a)
            # XXX Exc are added on the "wrong" distribution; sum only works
            # when gd.comm and distribution comm are the same
            dHdist_asp[a] = dH_sp
        self.timer.stop("XC Correction")

        dHdist_asp = self.dh_distributor.collect(dHdist_asp)

        # Exca has contributions from all cores so modify it so it is
        # parallel in the same way as the other energies.
        Exca = self.world.sum(Exca)
        if self.gd.comm.rank == 0:
            Exc += Exca

        assert len(dHdist_asp) == len(self.atom_partition.my_indices)

        for a, D_sp in density.D_asp.items():
            dH_sp = dH_asp[a]
            dH_sp += dHdist_asp[a]
            Ekin -= (D_sp * dH_sp).sum()  # NCXXX
        self.dH_asp = dH_asp
        self.timer.stop("Atomic")

        # Make corrections due to non-local xc:
        # xcfunc = self.xc.xcfunc
        self.Enlxc = 0.0  # XXXxcfunc.get_non_local_energy()
        Ekin += self.xc.get_kinetic_energy_correction() / self.gd.comm.size

        energies = np.array([Ekin, Epot, Ebar, Eext, Exc])
        self.timer.start("Communicate energies")
        self.gd.comm.sum(energies)
        # Make sure that all CPUs have the same energies
        self.world.broadcast(energies, 0)
        self.timer.stop("Communicate energies")
        (self.Ekin0, self.Epot, self.Ebar, self.Eext, self.Exc) = energies

        # self.Exc += self.Enlxc
        # self.Ekin0 += self.Enlkin

        self.timer.stop("Hamiltonian")
示例#11
0
    def update(self, density):
        """Calculate effective potential.

        The XC-potential and the Hartree potential are evaluated on
        the fine grid, and the sum is then restricted to the coarse
        grid."""

        self.timer.start('Hamiltonian')

        if self.vt_sg is None:
            self.timer.start('Initialize Hamiltonian')
            self.vt_sg = self.finegd.empty(self.nspins)
            self.vHt_g = self.finegd.zeros()
            self.vt_sG = self.gd.empty(self.nspins)
            self.poisson.initialize()
            self.timer.stop('Initialize Hamiltonian')

        self.timer.start('vbar')
        Ebar = self.finegd.integrate(self.vbar_g, density.nt_g,
                                     global_integral=False)

        vt_g = self.vt_sg[0]
        vt_g[:] = self.vbar_g
        self.timer.stop('vbar')

        Eext = 0.0
        if self.vext_g is not None:
            vt_g += self.vext_g.get_potential(self.finegd)
            Eext = self.finegd.integrate(vt_g, density.nt_g,
                                         global_integral=False) - Ebar

        if self.nspins == 2:
            self.vt_sg[1] = vt_g

        self.timer.start('XC 3D grid')
        Exc = self.xc.calculate(self.finegd, density.nt_sg, self.vt_sg)
        Exc /= self.gd.comm.size
        self.timer.stop('XC 3D grid')

        self.timer.start('Poisson')
        # npoisson is the number of iterations:
        self.npoisson = self.poisson.solve(self.vHt_g, density.rhot_g,
                                           charge=-density.charge)
        self.timer.stop('Poisson')

        self.timer.start('Hartree integrate/restrict')
        Epot = 0.5 * self.finegd.integrate(self.vHt_g, density.rhot_g,
                                           global_integral=False)
        Ekin = 0.0
        for vt_g, vt_G, nt_G in zip(self.vt_sg, self.vt_sG, density.nt_sG):
            vt_g += self.vHt_g
            self.restrict(vt_g, vt_G)
            Ekin -= self.gd.integrate(vt_G, nt_G - density.nct_G,
                                      global_integral=False)
        self.timer.stop('Hartree integrate/restrict')
            
        # Calculate atomic hamiltonians:
        self.timer.start('Atomic')
        W_aL = {}
        for a in density.D_asp:
            W_aL[a] = np.empty((self.setups[a].lmax + 1)**2)
        density.ghat.integrate(self.vHt_g, W_aL)
        self.dH_asp = {}
        for a, D_sp in density.D_asp.items():
            W_L = W_aL[a]
            setup = self.setups[a]

            D_p = D_sp.sum(0)
            dH_p = (setup.K_p + setup.M_p +
                    setup.MB_p + 2.0 * np.dot(setup.M_pp, D_p) +
                    np.dot(setup.Delta_pL, W_L))
            Ekin += np.dot(setup.K_p, D_p) + setup.Kc
            Ebar += setup.MB + np.dot(setup.MB_p, D_p)
            Epot += setup.M + np.dot(D_p, (setup.M_p +
                                           np.dot(setup.M_pp, D_p)))

            if self.vext_g is not None:
                vext = self.vext_g.get_taylor(spos_c=self.spos_ac[a, :])
                # Tailor expansion to the zeroth order
                Eext += vext[0][0] * (sqrt(4 * pi) * density.Q_aL[a][0]
                                      + setup.Z)
                dH_p += vext[0][0] * sqrt(4 * pi) * setup.Delta_pL[:, 0]
                if len(vext) > 1:
                    # Tailor expansion to the first order
                    Eext += sqrt(4 * pi / 3) * np.dot(vext[1],
                                                      density.Q_aL[a][1:4])
                    # there must be a better way XXXX
                    Delta_p1 = np.array([setup.Delta_pL[:, 1],
                                          setup.Delta_pL[:, 2],
                                          setup.Delta_pL[:, 3]])
                    dH_p += sqrt(4 * pi / 3) * np.dot(vext[1], Delta_p1)

            self.dH_asp[a] = dH_sp = np.zeros_like(D_sp)
            self.timer.start('XC Correction')
            Exc += setup.xc_correction.calculate(self.xc, D_sp, dH_sp, a)
            self.timer.stop('XC Correction')

            if setup.HubU is not None:
                nspins = len(D_sp)
                
                l_j = setup.l_j
                l   = setup.Hubl
                nl  = np.where(np.equal(l_j,l))[0]
                nn  = (2*np.array(l_j)+1)[0:nl[0]].sum()
                
                for D_p, H_p in zip(D_sp, self.dH_asp[a]):
                    [N_mm,V] =self.aoom(unpack2(D_p),a,l)
                    N_mm = N_mm / 2 * nspins
                     
                    Eorb = setup.HubU / 2. * (N_mm - np.dot(N_mm,N_mm)).trace()
                    Vorb = setup.HubU * (0.5 * np.eye(2*l+1) - N_mm)
                    Exc += Eorb
                    if nspins == 1:
                        # add contribution of other spin manyfold
                        Exc += Eorb
                    
                    if len(nl)==2:
                        mm  = (2*np.array(l_j)+1)[0:nl[1]].sum()
                        
                        V[nn:nn+2*l+1,nn:nn+2*l+1] *= Vorb
                        V[mm:mm+2*l+1,nn:nn+2*l+1] *= Vorb
                        V[nn:nn+2*l+1,mm:mm+2*l+1] *= Vorb
                        V[mm:mm+2*l+1,mm:mm+2*l+1] *= Vorb
                    else:
                        V[nn:nn+2*l+1,nn:nn+2*l+1] *= Vorb
                    
                    Htemp = unpack(H_p)
                    Htemp += V
                    H_p[:] = pack2(Htemp)

            dH_sp += dH_p

            Ekin -= (D_sp * dH_sp).sum()

        self.timer.stop('Atomic')

        # Make corrections due to non-local xc:
        #xcfunc = self.xc.xcfunc
        self.Enlxc = 0.0#XXXxcfunc.get_non_local_energy()
        Ekin += self.xc.get_kinetic_energy_correction() / self.gd.comm.size

        energies = np.array([Ekin, Epot, Ebar, Eext, Exc])
        self.timer.start('Communicate energies')
        self.gd.comm.sum(energies)
        self.timer.stop('Communicate energies')
        (self.Ekin0, self.Epot, self.Ebar, self.Eext, self.Exc) = energies

        #self.Exc += self.Enlxc
        #self.Ekin0 += self.Enlkin

        self.timer.stop('Hamiltonian')
    def make_paw_setup(self, tag=None):
        aea = self.aea

        from gpaw.setup_data import SetupData
        setup = SetupData(aea.symbol, aea.xc.name, tag, readxml=False)

        setup.id_j = []

        J = []  # new reordered j and i indices
        I = []

        # Bound states:
        j = 0
        i = 0
        for l, waves in enumerate(self.waves_l):
            for n, f, e, phi_g, phit_g, pt_g in zip(waves.n_n, waves.f_n,
                                                    waves.e_n, waves.phi_ng,
                                                    waves.phit_ng,
                                                    waves.pt_ng):
                if n != -1:
                    setup.append(n, l, f, e, waves.rcut, phi_g, phit_g, pt_g)
                    id = '%d%s' % (n, 'spdf'[l])
                    setup.id_j.append(id)
                    J.append(j)
                    I.extend(range(i, i + 2 * l + 1))
                j += 1
                i += 2 * l + 1

        # Excited states:
        j = 0
        i = 0
        for l, waves in enumerate(self.waves_l):
            ne = 0
            for n, f, e, phi_g, phit_g, pt_g in zip(waves.n_n, waves.f_n,
                                                    waves.e_n, waves.phi_ng,
                                                    waves.phit_ng,
                                                    waves.pt_ng):
                if n == -1:
                    setup.append(n, l, f, e, waves.rcut, phi_g, phit_g, pt_g)
                    ne += 1
                    id = '%s%d' % ('spdf'[l], ne)
                    setup.id_j.append(id)
                    J.append(j)
                    I.extend(range(i, i + 2 * l + 1))
                j += 1
                i += 2 * l + 1

        nj = sum(len(waves) for waves in self.waves_l)
        e_kin_jj = np.zeros((nj, nj))
        j1 = 0
        for waves in self.waves_l:
            j2 = j1 + len(waves)
            e_kin_jj[j1:j2, j1:j2] = waves.dekin_nn
            j1 = j2
        setup.e_kin_jj = e_kin_jj[J][:, J].copy()

        setup.nc_g = self.nc_g * sqrt(4 * pi)
        setup.nct_g = self.nct_g * sqrt(4 * pi)
        setup.e_kinetic_core = self.ekincore
        setup.vbar_g = self.v0r_g * sqrt(4 * pi)
        setup.vbar_g[1:] /= self.rgd.r_g[1:]
        setup.vbar_g[0] = setup.vbar_g[1]
        setup.Z = aea.Z
        setup.Nc = self.ncore
        setup.Nv = self.nvalence
        setup.e_kinetic = aea.ekin
        setup.e_xc = aea.exc
        setup.e_electrostatic = aea.eH + aea.eZ
        setup.e_total = aea.exc + aea.ekin + aea.eH + aea.eZ
        setup.rgd = self.rgd
        setup.rcgauss = 1 / sqrt(self.alpha)

        self.calculate_exx_integrals()
        setup.ExxC = self.exxcc
        setup.X_p = pack2(self.exxcv_ii[I][:, I])

        setup.tauc_g = self.tauc_g * (4 * pi)**0.5
        setup.tauct_g = self.tauct_g * (4 * pi)**0.5

        if self.aea.scalar_relativistic:
            reltype = 'scalar-relativistic'
        else:
            reltype = 'non-relativistic'
        attrs = [('type', reltype),
                 ('version', 2),
                 ('name', 'gpaw-%s' % version)]
        setup.generatorattrs = attrs

        setup.l0 = self.l0
        setup.e0 = 0.0
        setup.r0 = self.r0
        setup.nderiv0 = self.nderiv0

        setup.basis = self.basis

        if self.core_hole:
            n, l, occ = self.core_hole
            phi_g = self.aea.channels[l].phi_ng[n - l - 1]
            setup.ncorehole = n
            setup.lcorehole = l
            setup.fcorehole = occ
            setup.phicorehole_g = phi_g
            setup.has_corehole = True

        return setup
示例#13
0
    def update(self, density):
        """Calculate effective potential.

        The XC-potential and the Hartree potential are evaluated on
        the fine grid, and the sum is then restricted to the coarse
        grid."""

        self.timer.start('Hamiltonian')

        if self.vt_sg is None:
            self.timer.start('Initialize Hamiltonian')
            self.vt_sg = self.finegd.empty(self.nspins * self.ncomp**2)
            self.vHt_g = self.finegd.zeros()
            self.vt_sG = self.gd.empty(self.nspins * self.ncomp**2)
            self.poisson.initialize()
            self.timer.stop('Initialize Hamiltonian')

        Ekin, Epot, Ebar, Eext, Exc, W_aL = \
            self.update_pseudo_potential(density)

        self.timer.start('Atomic')
        self.dH_asp = {}
        for a, D_sp in density.D_asp.items():
            W_L = W_aL[a]
            setup = self.setups[a]

            D_p = D_sp[:self.nspins].sum(0)
            dH_p = (setup.K_p + setup.M_p +
                    setup.MB_p + 2.0 * np.dot(setup.M_pp, D_p) +
                    np.dot(setup.Delta_pL, W_L))
            Ekin += np.dot(setup.K_p, D_p) + setup.Kc
            Ebar += setup.MB + np.dot(setup.MB_p, D_p)
            Epot += setup.M + np.dot(D_p, (setup.M_p +
                                           np.dot(setup.M_pp, D_p)))

            if self.vext is not None:
                vext = self.vext.get_taylor(spos_c=self.spos_ac[a, :])
                # Tailor expansion to the zeroth order
                Eext += vext[0][0] * (sqrt(4 * pi) * density.Q_aL[a][0]
                                      + setup.Z)
                dH_p += vext[0][0] * sqrt(4 * pi) * setup.Delta_pL[:, 0]
                if len(vext) > 1:
                    # Tailor expansion to the first order
                    Eext += sqrt(4 * pi / 3) * np.dot(vext[1],
                                                      density.Q_aL[a][1:4])
                    # there must be a better way XXXX
                    Delta_p1 = np.array([setup.Delta_pL[:, 1],
                                          setup.Delta_pL[:, 2],
                                          setup.Delta_pL[:, 3]])
                    dH_p += sqrt(4 * pi / 3) * np.dot(vext[1], Delta_p1)

            self.dH_asp[a] = dH_sp = np.zeros_like(D_sp)
            self.timer.start('XC Correction')
            Exc += self.xc.calculate_paw_correction(setup, D_sp, dH_sp, a=a)
            self.timer.stop('XC Correction')

            if setup.HubU is not None:
                assert self.collinear
                nspins = len(D_sp)
                
                l_j = setup.l_j
                l   = setup.Hubl
                scale = setup.Hubs
                nl  = np.where(np.equal(l_j,l))[0]
                nn  = (2*np.array(l_j)+1)[0:nl[0]].sum()
                
                for D_p, H_p in zip(D_sp, self.dH_asp[a]):
                    [N_mm,V] =self.aoom(unpack2(D_p),a,l, scale)
                    N_mm = N_mm / 2 * nspins
                     
                    Eorb = setup.HubU / 2. * (N_mm - np.dot(N_mm,N_mm)).trace()
                    Vorb = setup.HubU * (0.5 * np.eye(2*l+1) - N_mm)
                    Exc += Eorb
                    if nspins == 1:
                        # add contribution of other spin manyfold
                        Exc += Eorb
                    
                    if len(nl)==2:
                        mm  = (2*np.array(l_j)+1)[0:nl[1]].sum()
                        
                        V[nn:nn+2*l+1,nn:nn+2*l+1] *= Vorb
                        V[mm:mm+2*l+1,nn:nn+2*l+1] *= Vorb
                        V[nn:nn+2*l+1,mm:mm+2*l+1] *= Vorb
                        V[mm:mm+2*l+1,mm:mm+2*l+1] *= Vorb
                    else:
                        V[nn:nn+2*l+1,nn:nn+2*l+1] *= Vorb
                    
                    Htemp = unpack(H_p)
                    Htemp += V
                    H_p[:] = pack2(Htemp)

            dH_sp[:self.nspins] += dH_p

            Ekin -= (D_sp * dH_sp).sum()  # NCXXX

        self.timer.stop('Atomic')

        # Make corrections due to non-local xc:
        #xcfunc = self.xc.xcfunc
        self.Enlxc = 0.0  # XXXxcfunc.get_non_local_energy()
        Ekin += self.xc.get_kinetic_energy_correction() / self.gd.comm.size

        energies = np.array([Ekin, Epot, Ebar, Eext, Exc])
        self.timer.start('Communicate energies')
        self.gd.comm.sum(energies)
        # Make sure that all CPUs have the same energies
        self.world.broadcast(energies, 0)
        self.timer.stop('Communicate energies')
        (self.Ekin0, self.Epot, self.Ebar, self.Eext, self.Exc) = energies

        #self.Exc += self.Enlxc
        #self.Ekin0 += self.Enlkin

        self.timer.stop('Hamiltonian')
示例#14
0
    def update(self, density):
        """Calculate effective potential.

        The XC-potential and the Hartree potential are evaluated on
        the fine grid, and the sum is then restricted to the coarse
        grid."""

        self.timer.start('Hamiltonian')

        if self.vt_sg is None:
            self.timer.start('Initialize Hamiltonian')
            self.vt_sg = self.finegd.empty(self.ns)
            self.vHt_g = self.finegd.zeros()
            self.vt_sG = self.gd.empty(self.ns)
            self.poisson.initialize()
            self.timer.stop('Initialize Hamiltonian')

        Ekin, Epot, Ebar, Eext, Exc, W_aL = \
            self.update_pseudo_potential(density)

        self.timer.start('Atomic')
        self.dH_asp = None  # XXXX

        dH_asp = {}
        for a, D_sp in density.D_asp.items():
            W_L = W_aL[a]
            setup = self.setups[a]

            D_p = D_sp[:self.nspins].sum(0)
            dH_p = (setup.K_p + setup.M_p + setup.MB_p +
                    2.0 * np.dot(setup.M_pp, D_p) +
                    np.dot(setup.Delta_pL, W_L))
            Ekin += np.dot(setup.K_p, D_p) + setup.Kc
            Ebar += setup.MB + np.dot(setup.MB_p, D_p)
            Epot += setup.M + np.dot(D_p,
                                     (setup.M_p + np.dot(setup.M_pp, D_p)))

            if self.vext is not None:
                vext = self.vext.get_taylor(spos_c=self.spos_ac[a, :])
                # Tailor expansion to the zeroth order
                Eext += vext[0][0] * (sqrt(4 * pi) * density.Q_aL[a][0] +
                                      setup.Z)
                dH_p += vext[0][0] * sqrt(4 * pi) * setup.Delta_pL[:, 0]
                if len(vext) > 1:
                    # Tailor expansion to the first order
                    Eext += sqrt(4 * pi / 3) * np.dot(vext[1],
                                                      density.Q_aL[a][1:4])
                    # there must be a better way XXXX
                    Delta_p1 = np.array([
                        setup.Delta_pL[:, 1], setup.Delta_pL[:, 2],
                        setup.Delta_pL[:, 3]
                    ])
                    dH_p += sqrt(4 * pi / 3) * np.dot(vext[1], Delta_p1)

            dH_asp[a] = dH_sp = np.zeros_like(D_sp)

            if setup.HubU is not None:
                assert self.collinear
                nspins = len(D_sp)

                l_j = setup.l_j
                l = setup.Hubl
                scale = setup.Hubs
                nl = np.where(np.equal(l_j, l))[0]
                nn = (2 * np.array(l_j) + 1)[0:nl[0]].sum()

                for D_p, H_p in zip(D_sp, dH_asp[a]):
                    [N_mm, V] = self.aoom(unpack2(D_p), a, l, scale)
                    N_mm = N_mm / 2 * nspins

                    Eorb = setup.HubU / 2. * (N_mm -
                                              np.dot(N_mm, N_mm)).trace()
                    Vorb = setup.HubU * (0.5 * np.eye(2 * l + 1) - N_mm)
                    Exc += Eorb
                    if nspins == 1:
                        # add contribution of other spin manyfold
                        Exc += Eorb

                    if len(nl) == 2:
                        mm = (2 * np.array(l_j) + 1)[0:nl[1]].sum()

                        V[nn:nn + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb
                        V[mm:mm + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb
                        V[nn:nn + 2 * l + 1, mm:mm + 2 * l + 1] *= Vorb
                        V[mm:mm + 2 * l + 1, mm:mm + 2 * l + 1] *= Vorb
                    else:
                        V[nn:nn + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb

                    Htemp = unpack(H_p)
                    Htemp += V
                    H_p[:] = pack2(Htemp)

            dH_sp[:self.nspins] += dH_p
            if self.ref_dH_asp:
                dH_sp += self.ref_dH_asp[a]
            # We are not yet done with dH_sp; still need XC correction below

        Ddist_asp = self.dh_distributor.distribute(density.D_asp)

        dHdist_asp = {}
        Exca = 0.0
        self.timer.start('XC Correction')
        for a, D_sp in Ddist_asp.items():
            setup = self.setups[a]
            dH_sp = np.zeros_like(D_sp)
            Exca += self.xc.calculate_paw_correction(setup, D_sp, dH_sp, a=a)
            # XXX Exc are added on the "wrong" distribution; sum only works
            # when gd.comm and distribution comm are the same
            dHdist_asp[a] = dH_sp
        self.timer.stop('XC Correction')

        dHdist_asp = self.dh_distributor.collect(dHdist_asp)

        # Exca has contributions from all cores so modify it so it is
        # parallel in the same way as the other energies.
        Exca = self.world.sum(Exca)
        if self.gd.comm.rank == 0:
            Exc += Exca

        assert len(dHdist_asp) == len(self.atom_partition.my_indices)

        for a, D_sp in density.D_asp.items():
            dH_sp = dH_asp[a]
            dH_sp += dHdist_asp[a]
            Ekin -= (D_sp * dH_sp).sum()  # NCXXX
        self.dH_asp = dH_asp
        self.timer.stop('Atomic')

        # Make corrections due to non-local xc:
        #xcfunc = self.xc.xcfunc
        self.Enlxc = 0.0  # XXXxcfunc.get_non_local_energy()
        Ekin += self.xc.get_kinetic_energy_correction() / self.gd.comm.size

        energies = np.array([Ekin, Epot, Ebar, Eext, Exc])
        self.timer.start('Communicate energies')
        self.gd.comm.sum(energies)
        # Make sure that all CPUs have the same energies
        self.world.broadcast(energies, 0)
        self.timer.stop('Communicate energies')
        (self.Ekin0, self.Epot, self.Ebar, self.Eext, self.Exc) = energies

        #self.Exc += self.Enlxc
        #self.Ekin0 += self.Enlkin

        self.timer.stop('Hamiltonian')
示例#15
0
    def update_corrections(self, dens, W_aL):
        self.timer.start('Atomic')
        self.dH_asp = None  # XXXX

        e_kinetic = 0.0
        e_coulomb = 0.0
        e_zero = 0.0
        e_external = 0.0
        e_xc = 0.0

        D_asp = self.atomdist.to_work(dens.D_asp)
        dH_asp = self.setups.empty_atomic_matrix(self.nspins, D_asp.partition)

        for a, D_sp in D_asp.items():
            W_L = W_aL[a]
            setup = self.setups[a]

            D_p = D_sp.sum(0)
            dH_p = (setup.K_p + setup.M_p + setup.MB_p +
                    2.0 * np.dot(setup.M_pp, D_p) +
                    np.dot(setup.Delta_pL, W_L))
            e_kinetic += np.dot(setup.K_p, D_p) + setup.Kc
            e_zero += setup.MB + np.dot(setup.MB_p, D_p)
            e_coulomb += setup.M + np.dot(
                D_p, (setup.M_p + np.dot(setup.M_pp, D_p)))

            dH_asp[a] = dH_sp = np.zeros_like(D_sp)

            if setup.HubU is not None:
                nspins = len(D_sp)

                l_j = setup.l_j
                l = setup.Hubl
                scale = setup.Hubs
                nl = np.where(np.equal(l_j, l))[0]
                nn = (2 * np.array(l_j) + 1)[0:nl[0]].sum()

                for D_p, H_p in zip(D_sp, dH_asp[a]):
                    [N_mm, V] = self.aoom(unpack2(D_p), a, l, scale)
                    N_mm = N_mm / 2 * nspins

                    Eorb = setup.HubU / 2. * (N_mm -
                                              np.dot(N_mm, N_mm)).trace()
                    Vorb = setup.HubU * (0.5 * np.eye(2 * l + 1) - N_mm)
                    e_xc += Eorb
                    if nspins == 1:
                        # add contribution of other spin manyfold
                        e_xc += Eorb

                    if len(nl) == 2:
                        mm = (2 * np.array(l_j) + 1)[0:nl[1]].sum()

                        V[nn:nn + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb
                        V[mm:mm + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb
                        V[nn:nn + 2 * l + 1, mm:mm + 2 * l + 1] *= Vorb
                        V[mm:mm + 2 * l + 1, mm:mm + 2 * l + 1] *= Vorb
                    else:
                        V[nn:nn + 2 * l + 1, nn:nn + 2 * l + 1] *= Vorb

                    Htemp = unpack(H_p)
                    Htemp += V
                    H_p[:] = pack2(Htemp)

            dH_sp += dH_p
            if self.ref_dH_asp:
                dH_sp += self.ref_dH_asp[a]

        self.timer.start('XC Correction')
        for a, D_sp in D_asp.items():
            e_xc += self.xc.calculate_paw_correction(self.setups[a],
                                                     D_sp,
                                                     dH_asp[a],
                                                     a=a)
        self.timer.stop('XC Correction')

        for a, D_sp in D_asp.items():
            e_kinetic -= (D_sp * dH_asp[a]).sum()  # NCXXX

        self.dH_asp = self.atomdist.from_work(dH_asp)
        self.timer.stop('Atomic')

        # Make corrections due to non-local xc:
        self.Enlxc = 0.0  # XXXxcfunc.get_non_local_energy()
        e_kinetic += self.xc.get_kinetic_energy_correction() / self.world.size
        return np.array([e_kinetic, e_coulomb, e_zero, e_external, e_xc])