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
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