Exemple #1
0
def solve_radial_eigenproblem(n, l, r, u, relat=0, params=None):
    """
    Solves the radial Schroedinger (Dirac) eigenproblem.

    Input::

        n, l ..... quantum numbers
        r ........ radial mesh (NumPy array)
        u ........ Potential on the radial mesh (for example -Z/r)
        relat .... 0 solves Schroedinger equation
                   2 solves Dirac equation, spin up
                   3 solves Dirac equation, spin down
        params ... optional dictionary with solver specific parameters (not all
                    parameters apply for each solver):
                solver ... type of solver (dftatom, elk)
                Z ... atomic number Z in the potential -Z/r
                E_init, E_delta ... energy is sought in the interval
                        (Emin, Emax), where
                            E_min = E_init - E_delta
                            E_max = E_init + E_delta
                eps ... accuracy for |Emax - Emin| < eps, default 1e-10
                c ... speed of light in atomic units (default c = 137.035999037,
                        from http://arxiv.org/abs/1012.3627)


    Returns (E, R), where E is the energy, and R(r) is the radial wave
    function (normalized as \int R(r)**2 * r**2 \d r = 1)
    """
    if params is None:
        params = {}
    solver = params.get("solver", "dftatom")
    c = params.get("c", 137.035999037)
    if solver == "dftatom":
        if "Z" in params:
            Z = params["Z"]
        else:
            # Disable the fragile estimation of Z below for now:
            raise NotImplementedError("Z not specified. You can enable automatic determination of Z in qsnake/atom.py.")
            # Estimate Z by assuming a coulombic potential u = -Z/r near the
            # origin:
            Z = -u[0] * r[0]
        E_init = params.get("E_init", -3000)
        E_delta = params.get("E_delta", 2000)
        eps = params.get("eps", 1e-9)
        from dftatom.rdirac import (solve_radial_eigenproblem,
                ConvergeError as dftatom_ConvergeError)
        try:
            E, R = solve_radial_eigenproblem(c, n, l, E_init, E_delta, eps,
                    u, r, Z, relat)
        except dftatom_ConvergeError, e:
            raise ConvergeError(str(e))
        return E, R
Exemple #2
0
def solve_hydrogen_like_atom(Z, mesh_params, solver_params, verbose=False):
    from sympy.physics.hydrogen import E_nl_dirac, E_nl
    from sympy import TableForm
    r_min = mesh_params["r_min"]
    r_max = mesh_params["r_max"]
    a = mesh_params["a"]
    N = mesh_params["N"]
    r = mesh_exp(r_min, r_max, a, N)
    if verbose:
        print "Mesh parameters:"
        print TableForm([[r_min], [r_max], [a], [N]],
                headings=(("r_min", "r_max", "a", "N"), ("Mesh parameters",)))
        #print r

    c = solver_params.get("c", 137.035999037)
    solver_params["c"] = c
    solver_params["Z"] = Z
    dirac = solver_params.get("dirac", False)


    # Potential:
    vr = -Z/r

    tot_error = -1
    data = []
    # (n, l):
    # either k == l, or k == l + 1:
    for n in range(1, 7):
        for l in range(0, n):
            if dirac:
                relat_list = [2]
                if l > 0:
                    relat_list.append(3)
            else:
                relat_list = [0]

            for relat in relat_list:
                try:
                    E, R = solve_radial_eigenproblem(n, l, r, vr, relat,
                            solver_params)
                except ConvergeError:
                    if verbose:
                        print "Radial solver didn't converge"
                    raise
                    return 1e6
                if dirac:
                    spin_up = (relat == 2)
                    E_exact = E_nl_dirac(n, l, spin_up=spin_up, Z=Z, c=c)
                else:
                    E_exact = E_nl(n, Z=Z)
                E_exact = float(E_exact)
                delta = abs(E-E_exact)
                if delta > tot_error:
                    tot_error = delta
                if dirac:
                    k = int(spin_up)
                else:
                    k = 0
                data.append([n, l, k,
                    "%.6f" % E, "%.6f" % E_exact, "%.2e" % delta])
    t = TableForm(data, alignment="right",
            headings=(None, ("n", "l", "k", "E_calc", "E_exact", "delta")))
    if verbose:
        print t
    return tot_error