Ejemplo n.º 1
0
def test():
    # bond length in bohr
    dist = 2.0
    # positions of protons
    posH1 = (0.0, 0.0, -dist / 2.0)
    posH2 = (0.0, 0.0, +dist / 2.0)

    atomlist = [(1, posH1), (1, posH2)]

    # Set resolution of multicenter grid
    settings.radial_grid_factor = 20
    settings.lebedev_order = 23

    # energy of continuum orbital
    E = 1.0

    # same functional as used in the calculation of pseudo orbitals
    xc = XCFunctionals.libXCFunctional(Parameters.pseudo_orbital_x,
                                       Parameters.pseudo_orbital_c)
    dft = BasissetFreeDFT(atomlist, xc)

    print "initial orbital guess from DFTB calculation"
    orbitals = dft.getOrbitalGuess()

    norb = len(orbitals)
    # all orbitals are doubly occupied
    nelec = 2 * norb

    bound_orbitals = dft.getOrbitalGuess()

    # effective potential
    rho = density_func(bound_orbitals)
    veff = effective_potential_func(atomlist, rho, xc, nelec=nelec)

    # radius that separates inner from outer region
    r0 = vdw_sphere_radius(atomlist, fac=2.0)
    # basis sets
    bs_core = AtomicBasisSet(atomlist, orbital_set="core")
    bs_valence = AtomicBasisSet(atomlist, orbital_set="valence")
    bs_continuum = AtomicScatteringBasisSet(atomlist, E, lmax=1)
    # combine basis functions from all basis sets
    bfs = bs_core.bfs + bs_valence.bfs + bs_continuum.bfs

    A, D, S = fvvm_matrix_elements(atomlist, bfs, veff, E, r0)

    # solve generalized eigenvalue problem
    #   A.C = b.D.C
    b, C = sla.eigh(A, D)

    return b, C
Ejemplo n.º 2
0
def onsite_integrals(atom_name='h', confined=True):
    """
    compute on-site Coulomb and exchange integrals for an atom

    Parameters
    ----------
    atom_name      :  name of atom, e.g. 'h', 'c', etc.

    Optional
    --------
    confined      :   controls where confined atoms (True) or free atoms (False)
                      are used
    """
    print(
        "computing on-site Coulomb and exchange integrals between valence orbitals of '%s'"
        % atom_name)
    Zat = atomic_number(atom_name)
    atomlist = [(Zat, (0, 0, 0))]
    basis = AtomicBasisSet(atomlist, confined=confined)
    density = AtomicDensitySuperposition(atomlist, confined=confined)
    #xc_functional = XCFunctionals.libXCFunctional("lda_x", "lda_c_pw")
    xc_functional = XCFunctionals.libXCFunctional("gga_x_pbe", "gga_c_pbe")

    for a, bfA in enumerate(basis.bfs):
        stra = "%d%s" % (bfA.n, angmom_to_xyz[(bfA.l, bfA.m)]
                         )  # name of valence orbital, e.g. 1s, 2px, etc.
        for b, bfB in enumerate(basis.bfs):
            strb = "%d%s" % (bfB.n, angmom_to_xyz[(bfB.l, bfB.m)])
            # Coulomb integral    (aa|(1/r12 + fxc[rho0])|bb)
            eri_aabb = electron_repulsion_integral(atomlist, bfA, bfA, bfB,
                                                   bfB, density, xc_functional)
            print("Coulomb  (%s,%s|{1/r12+f_xc[rho0]}|%s,%s)= %e" %
                  (stra, stra, strb, strb, eri_aabb))
            if a != b:
                # exchange integral    (ab|(1/r12 + fxc[rho0])|ab)
                eri_abab = electron_repulsion_integral(atomlist, bfA, bfB, bfA,
                                                       bfB, density,
                                                       xc_functional)
                print("exchange (%s,%s|{1/r12+f_xc[rho0]}|%s,%s)= %e" %
                      (stra, strb, stra, strb, eri_abab))
Ejemplo n.º 3
0
def test_h2_continuum_orbital():
    """
    The sigma continuum orbital is approximated as a linear
    combination of two s continuum orbitals and is then
    improved iteratively
    """
    # bond length in bohr
    dist = 2.0
    # positions of protons
    posH1 = (0.0, 0.0, -dist / 2.0)
    posH2 = (0.0, 0.0, +dist / 2.0)

    atomlist = [(1, posH1), (1, posH2)]

    # Set resolution of multicenter grid
    settings.radial_grid_factor = 20
    settings.lebedev_order = 23

    # energy of continuum orbital
    E = 1.0

    # same functional as used in the calculation of pseudo orbitals
    xc = XCFunctionals.libXCFunctional(Parameters.pseudo_orbital_x,
                                       Parameters.pseudo_orbital_c)
    dft = BasissetFreeDFT(atomlist, xc)

    print("initial orbital guess from DFTB calculation")
    orbitals = dft.getOrbitalGuess()

    norb = len(orbitals)
    # all orbitals are doubly occupied
    nelec = 2 * norb

    bound_orbitals = dft.getOrbitalGuess()

    # electron density (closed shell)
    rho = density_func(bound_orbitals)
    # effective Kohn-Sham potential
    veff = effective_potential_func(atomlist,
                                    rho,
                                    xc,
                                    nelec=nelec,
                                    nuclear=True)
    # effective Kohn-Sham potential without nuclear attraction
    # (only electron-electron interaction)
    veff_ee = effective_potential_func(atomlist,
                                       rho,
                                       xc,
                                       nelec=nelec,
                                       nuclear=False)

    ps = AtomicPotentialSet(atomlist)

    lmax = 0
    bs = AtomicScatteringBasisSet(atomlist, E, lmax=lmax)

    #test_AO_basis(atomlist, bs, ps, E)

    R = residual2_matrix(atomlist, veff, ps, bs)
    S = continuum_overlap(bs.bfs, E)
    print("continuum overlap")
    print(S)
    print("residual^2 matrix")
    print(R)

    eigvals, eigvecs = sla.eigh(R, S)
    print(eigvals)
    print("eigenvector belonging to lowest eigenvalue")
    print(eigvecs[:, 0])

    # LCAO continuum orbitals
    continuum_orbitals = orbital_transformation(atomlist, bs.bfs, eigvecs)

    # improve continuum orbital by adding a correction term
    #
    #    phi = phi0 + dphi
    #
    # The orbital correction dphi is the solution of the inhomogeneous
    # Schroedinger equation
    #
    #   (H-E)dphi = -(H-E)phi0
    #
    print("orbital correction...")
    phi0 = continuum_orbitals[0]

    phi = improve_continuum_orbital(atomlist, phi0, veff_ee, E)
Ejemplo n.º 4
0
        s = sigma(r, 0 * r, 0 * r)
        n = rho(r, 0 * r, 0 * r)

        # dimensional quantity  x = |grad rho|/rho^{4/3}
        x = np.sqrt(s) / n**(4.0 / 3.0)

        # van Leeuven and Baerends correction to exchange-correction
        # potential with asymptotic -1/r behaviour. The functional
        # contains one parameter  beta
        beta = 0.05
        vx_LB_correction = -beta * n**(1.0 / 3.0) * x**2 / (
            1.0 + 3 * beta * x * np.arcsinh(x))

        # LDA exchange
        xc_LDA = XCFunctionals.libXCFunctional("lda_x", "lda_c_xalpha")
        vx_LDA = xc_LDA.func_x.vxc(n.flatten(), s.flatten())

        vx_LB = vx_LDA + vx_LB_correction

        # libxc's implementation
        xc_LB = XCFunctionals.libXCFunctional("gga_x_lb", "lda_c_xalpha")
        # only exchange part
        vx_LB_libxc = xc_LB.func_x.vxc(n.flatten(), s.flatten())

        # LB approximation
        l, = plt.plot(r, vx_LB, label=r"$v_{x}^{LB}$ $\alpha=%e$" % alpha)
        plt.plot(r,
                 vx_LB_libxc,
                 ls="-.",
                 label=r"$v_{x}^{LB}$ (libxc) $\alpha=%e$" % alpha,
Ejemplo n.º 5
0
def onsite_integrals_unique(atom_name='h', confined=True):
    """
    compute the 5 unique on-site electron integrals for an atom.
    Only s- and p-valence orbitals are considered. The 5 integrals
    are

      (ss|ss)
      (sp|sp)   = (s px|s px) = (s py|s py) = (s pz|s pz)
      (ss|pp)   = (s s |pxpx) = (s s |pypy) = (s s |pzpz)
      (pp|pp)   = (pxpx|pxpx) = (pypy|pypy) = (pzpz|pzpz)
      (pp'|pp') = (pxpy|pxpy) = (pxpz|pxpz) = (pypz|pypz)

    Optional
    --------
    confined      :   controls where confined atoms (True) or free atoms (False)
                      are used

    Returns
    -------
    unique_integrals  :  numpy array with unique on-site integrals
                         [(ss|ss), (sp|sp), (ss|pp), (pp|pp), (pp'|pp')]

    References
    ----------
    [1] http://openmopac.net/manual/1c2e.html
    """
    print(
        "computing unique on-site electron integrals between valence orbitals of '%s'"
        % atom_name)
    print("only s- and p-functions are considered")
    Zat = atomic_number(atom_name)
    atomlist = [(Zat, (0, 0, 0))]
    basis = AtomicBasisSet(atomlist, confined=confined)
    density = AtomicDensitySuperposition(atomlist, confined=confined)
    #xc_functional = XCFunctionals.libXCFunctional("lda_x", "lda_c_pw")
    xc_functional = XCFunctionals.libXCFunctional("gga_x_pbe", "gga_c_pbe")

    unique_integrals = np.zeros(5)
    for a, bfA in enumerate(basis.bfs):
        for b, bfB in enumerate(basis.bfs):
            # choose index into unique_integrals to which the integrals is written
            if (bfA.l == 0 and bfB.l == 0):
                # (ss|ss)
                i = 0
            elif (bfA.l == 0 and bfB.l == 1 and bfB.m == 0):
                # (sp|sp) and (ss|pp)
                i = 1
            elif (bfA.l == 1 and bfA.m == 0 and bfB.l == 1 and bfB.m == 0):
                # (pp|pp)
                i = 3
            elif (bfA.l == 1 and bfA.m == 0 and bfB.l == 1 and bfB.m == 1):
                # (pp'|pp')
                i = 4
            else:
                continue

            # compute Coulomb integral    (ab|(1/r12 + fxc[rho0])|ab)
            eri_abab = electron_repulsion_integral(atomlist, bfA, bfB, bfA,
                                                   bfB, density, xc_functional)
            unique_integrals[i] = eri_abab

            if (i == 1):
                # in addition to (sp|sp) we also need to calculated (ss|pp)
                eri_aabb = electron_repulsion_integral(atomlist, bfA, bfA, bfB,
                                                       bfB, density,
                                                       xc_functional)
                unique_integrals[2] = eri_aabb
            elif (i == 4):
                # in addition to (pp'|pp') we also compute (pp|p'p') and verify the identity
                #  (pp|p'p') = (pp|pp) - 2 (pp'|pp')
                eri_aabb = electron_repulsion_integral(atomlist, bfA, bfA, bfB,
                                                       bfB, density,
                                                       xc_functional)
                assert (
                    eri_aabb -
                    (unique_integrals[3] - 2 * unique_integrals[4])) < 1.0e-5

    print("unique 1-center integrals (in eV) for atom '%s'" % atom_name)
    print("       (ss|ss)     (sp|sp)     (ss|pp)      (pp|pp)     (pp'|pp')")
    print("    %+.7f  %+.7f  %+.7f  %+.7f  %+.7f" %
          tuple(unique_integrals * hartree_to_eV))

    return unique_integrals
Ejemplo n.º 6
0
from DFTB.SlaterKoster import XCFunctionals
from DFTB.MolecularIntegrals.BasissetFreeDFT import BasissetFreeDFT
from DFTB.MolecularIntegrals import settings

import os.path
import sys

if __name__ == "__main__":
    if len(sys.argv) < 4:
        print "Usage: %s xyz-file  rfac  Lmax" % os.path.basename(sys.argv[0])
        print "  compute DFT ground state"
        exit(-1)

    # load geometry
    xyz_file = sys.argv[1]
    atomlist = XYZ.read_xyz(xyz_file)[0]
    # set resolution of multicenter grid
    rfac = int(sys.argv[2])
    Lmax = int(sys.argv[3])

    settings.radial_grid_factor = rfac  # controls size of radial grid
    settings.lebedev_order = Lmax  # controls size of angular grid

    charge = 0

    # PBE functional
    xc = XCFunctionals.libXCFunctional('gga_x_pbe', 'gga_c_pbe')

    RDFT = BasissetFreeDFT(atomlist, xc, charge=charge)
    RDFT.solveKohnSham_new(thresh=1.0e-8)
Ejemplo n.º 7
0
    (0, 0): "s ",
    (1, -1): "px",
    (1, 1): "py",
    (1, 0): "pz",
    (2, -2): "dxy",
    (2, -1): "dyz",
    (2, 0): "dz2",
    (2, 1): "dzx",
    (2, 2): "dx2y2"
}

if __name__ == "__main__":
    # set accuracy of multicenter grid
    settings.radial_grid_factor = 3
    settings.lebedev_order = 23

    atomlist = [(6, (0, 0, 0))]
    basis = AtomicBasisSet(atomlist)
    density = AtomicDensitySuperposition(atomlist)
    xc_functional = XCFunctionals.libXCFunctional("lda_x", "lda_c_pw")

    for a, bfA in enumerate(basis.bfs):
        for b, bfB in enumerate(basis.bfs):
            for c, bfC in enumerate(basis.bfs):
                for d, bfD in enumerate(basis.bfs):
                    eri = electron_repulsion_integral(atomlist, bfA, bfB, bfC,
                                                      bfD, density,
                                                      xc_functional)
                    print "(%d,%d|{1/r12+f_xc[rho0]}|%d,%d)= %e" % (a, b, c, d,
                                                                    eri)
Ejemplo n.º 8
0
def test_lcao_continuum():
    import matplotlib.pyplot as plt

    # bond length in bohr
    dist = 2.0
    # positions of protons
    posH1 = (0.0, 0.0, -dist / 2.0)
    posH2 = (0.0, 0.0, +dist / 2.0)

    atomlist = [(1, posH1), (1, posH2)]

    # Set resolution of multicenter grid
    settings.radial_grid_factor = 20
    settings.lebedev_order = 23

    # energy of continuum orbital
    E = 1.0

    # same functional as used in the calculation of pseudo orbitals
    xc = XCFunctionals.libXCFunctional(Parameters.pseudo_orbital_x,
                                       Parameters.pseudo_orbital_c)
    dft = BasissetFreeDFT(atomlist, xc)

    print("initial orbital guess from DFTB calculation")
    orbitals = dft.getOrbitalGuess()

    norb = len(orbitals)
    # all orbitals are doubly occupied
    nelec = 2 * norb

    bound_orbitals = dft.getOrbitalGuess()

    # effective potential
    rho = density_func(bound_orbitals)
    veff = effective_potential_func(atomlist, rho, xc, nelec=nelec)

    ps = AtomicPotentialSet(atomlist)

    r = np.linspace(-15.0, 15.0, 10000)
    x = 0.0 * r
    y = 0.0 * r
    z = r

    for lmax in [0, 1, 2, 3]:
        bs = AtomicScatteringBasisSet(atomlist, E, lmax=lmax)

        #test_AO_basis(atomlist, bs, ps, E)

        R = residual2_matrix(atomlist, veff, ps, bs)
        S = continuum_overlap(bs.bfs, E)
        print("continuum overlap")
        print(S)
        print("residual^2 matrix")
        print(R)

        eigvals, eigvecs = sla.eigh(R, S)
        print(eigvals)
        print("eigenvector belonging to lowest eigenvalue")
        print(eigvecs[:, 0])

        # LCAO continuum orbitals
        continuum_orbitals = orbital_transformation(atomlist, bs.bfs, eigvecs)

        # improve continuum orbital by adding a correction term
        #
        #    phi = phi0 + dphi
        #
        # The orbital correction dphi is the solution of the inhomogeneous
        # Schroedinger equation
        #
        #   (H-E)dphi = -(H-E)phi0
        #
        print("orbital correction...")
        phi0 = continuum_orbitals[0]

        phi = improve_continuum_orbital(atomlist, phi0, veff, E)
        exit(-1)

        residual_0 = residual_func(atomlist, phi0, veff, E)

        def source(x, y, z):
            return -residual_0(x, y, z)

        delta_phi = inhomogeneous_schroedinger(atomlist, veff, source, E)
        residual_d = residual_func(atomlist, delta_phi, veff, E)

        a, b = variational_mixture_continuum(atomlist, phi0, delta_phi, veff,
                                             E)

        phi = add_two_functions(atomlist, phi0, delta_phi, a, b)
        residual = residual_func(atomlist, phi, veff, E)

        plt.plot(r, 1.0 / np.sqrt(2.0) * bs.bfs[0](x, y, z), label=r"AO")
        plt.plot(r, phi0(x, y, z), label=r"$\phi_0$")
        plt.plot(r, delta_phi(x, y, z), label=r"$\Delta \phi$")
        plt.plot(r, phi(x, y, z), label=r"$\phi_0 + \Delta \phi$")
        plt.legend()
        plt.show()
        """
        dphi = delta_phi(x,y,z)
        imin = np.argmin(abs(r-1.0))
        dphi[abs(r) < 1.0] = dphi[imin] - (dphi[abs(r) < 1.0] - dphi[imin])
        plt.plot(r, dphi, label=r"$\Delta \phi$")
        """
        plt.plot(r, residual_0(x, y, z), label=r"$(H-E) \phi_0$")
        plt.plot(r, residual_d(x, y, z), label=r"$(H-E)\Delta \phi$")
        plt.plot(r,
                 residual(x, y, z),
                 label=r"$(H-E)(a \phi_0 + b \Delta \phi)$")
        plt.plot(r,
                 a * residual_0(x, y, z) + b * residual_d(x, y, z),
                 ls="-.",
                 label=r"$(H-E)(a \phi_0 + b \Delta \phi)$ (separate)")

        plt.legend()
        plt.show()

        averaged_angular_distribution(atomlist, bound_orbitals,
                                      continuum_orbitals, E)

        # save continuum MOs to cubefiles
        for i, phi in enumerate(continuum_orbitals):

            def func(grid, dV):
                x, y, z = grid
                return phi(x, y, z)

            Cube.function_to_cubefile(
                atomlist,
                func,
                filename="/tmp/cmo_lmax_%2.2d_orb%4.4d.cube" % (lmax, i),
                ppb=5.0)
        #

        for i, phi in enumerate(continuum_orbitals):
            residual = residual_func(atomlist, phi, veff, E)
            delta_e = energy_correction(atomlist,
                                        residual,
                                        phi,
                                        method="Becke")
            print(" orbital %d   energy <%d|H-E|%d> = %e" % (i, i, i, delta_e))

            l, = plt.plot(r,
                          phi(x, y, z),
                          label=r"$\phi_{%d}$ ($l_{max}$ = %d)" % (i, lmax))
            plt.plot(r,
                     residual(x, y, z),
                     ls="-.",
                     label=r"$(H-E)\phi_{%d}$" % i,
                     color=l.get_color())

        plt.legend()
        plt.show()
def numerical_gamma_integrals(atom_nameA,
                              atom_nameB,
                              distances,
                              confined=True):
    """
    compute the integrals

      gamma_{A,lA,B,lB} = (F_{A,lA}|1/r12 + f_xc[rho0A+rho0B]|F_{B,lB})

    numerically on a multicenter grid

    Parameters
    ----------
    atom_nameA, atom_nameB  :  names of interacting atoms, e.g. 'h' or 'c'
    distances               :  numpy array with interatomic separations (in bohr) for which
                               the gamma integrals should be calculated

    Optional
    --------
    confined      :   controls where confined atoms (True) or free atoms (False)
                      are used

    Returns
    -------
    gamma_dic               :  dictionary with values of gamma integrals on the distance grid,
                               gamma_dic[(lA,lB)] is a numpy array holding the integrals between
                               shell lA on atom A and shell lB on atom B
    """
    # atomic numbers
    Za = atomic_number(atom_nameA)
    Zb = atomic_number(atom_nameB)
    # charge fluctuation functions for each shell
    lsA, FsA = charge_fluctuation_functions(atom_nameA, confined=confined)
    lsB, FsB = charge_fluctuation_functions(atom_nameB, confined=confined)

    xc_functional = XCFunctionals.libXCFunctional("lda_x", "lda_c_pw")

    gamma_dic = {}
    for la, Fa in zip(lsA, FsA):
        for lb, Fb in zip(lsB, FsB):
            print("  integral between %s-shell and %s-shell" %
                  (l2spec[la], l2spec[lb]))
            gamma_ab = np.zeros(len(distances))
            for i, r_ab in enumerate(distances):

                print("   %3.d of %d   interatomic distance : %4.7f bohr" %
                      (i + 1, len(distances), r_ab))
                # atoms A and B are placed symmetrically on the z-axis,
                # separated by a distance of r_ab
                atomlist = [(Za, (0, 0, -0.5 * r_ab)),
                            (Zb, (0, 0, +0.5 * r_ab))]

                # define displaced charge fluctuation functions
                def rhoAB(x, y, z):
                    return Fa(x, y, z - 0.5 * r_ab)

                def rhoCD(x, y, z):
                    return Fb(x, y, z + 0.5 * r_ab)

                #
                rho0 = AtomicDensitySuperposition(atomlist, confined=confined)

                # evaluate integral
                gamma_ab[i] = electron_repulsion_integral_rho(
                    atomlist, rhoAB, rhoCD, rho0, xc_functional)

            # save gamma integral for the interaction of a shell with angular momentum la on atom A
            # and a shell with angular momentum lb on atom B
            gamma_dic[(la, lb)] = gamma_ab

    return gamma_dic
Ejemplo n.º 10
0
    print("effective potential...")

    # List of (exchange, correlation) functionals implemented
    # in libXC
    functionals = [
        ("lda_x", "lda_c_xalpha"),
        ("lda_x_erf", "lda_c_xalpha"),
        ("lda_x_rae", "lda_c_xalpha"),
        ("gga_x_lb", "lda_c_xalpha"),
    ]

    r = np.linspace(0.1, 100.0, 1000)
    plt.xlabel(r"distance r / bohr")
    plt.ylabel(r"potential / Hartree")

    # correct asymptotic HF potential
    plt.plot(r, -2.0 / r, "-.", lw=2, label=r"$-2/r$")

    for (x_func, c_func) in functionals:
        xc = XCFunctionals.libXCFunctional(x_func, c_func)
        # potential energy for Li nucleus and 2 core electrons
        potential = effective_potential_func(atomlist, rho, xc)

        plt.plot(r,
                 potential(r, 0 * r, 0 * r),
                 label=r"%s, %s" % (x_func, c_func))

    plt.ylim((-5.0, +0.1))
    plt.legend()
    plt.show()