Ejemplo n.º 1
0
def load_pseudo_atoms(atomlist, confined=True, orbital_set="valence"):
    """
    load radial parts of valence or core orbitals for each atom

    Optional
    ========
    confined    :  if True, the confined orbitals are loaded instead
                   of the free ones
    orbital_set :  load either 'core' or 'valence' orbitals

    Returns
    =======
    qnumbers    :  dictionary with list of quantum numbers (n-1,l,m)
                   of the loaded orbitals for each atom type
    radial_wfn  :  dictionary with list of splines evaluating the
                   radial wavefunctions for each atom type
    """
    atomtypes = list(set([Zi for (Zi, posi) in atomlist]))
    atomtypes.sort()
    # radial wavefunctions of orbitals for each atom
    radial_wfn = {}
    # quantum numbers (n-1,l,m) of orbitals for each atom
    qnumbers = {}
    for Zi in atomtypes:
        # load radial orbitals of pseudo atoms
        confined_atom, free_atom = import_pseudo_atom(Zi)
        if confined == True:
            atom = confined_atom
        else:
            atom = free_atom

        # Which orbitals (core or valence) should be loaded?
        if orbital_set == "core":
            # find indices of core orbitals
            core_orbitals = []
            for i, occ in enumerate(atom.orbital_occupation):
                if (occ > 0) and not (i in atom.valence_orbitals):
                    # Core orbitals are occupied orbitals that
                    # do not form part of the valence set.
                    core_orbitals.append(i)

            orbital_indices = core_orbitals
        elif orbital_set == "valence":
            orbital_indices = atom.valence_orbitals
        else:
            # by default valence orbitals are loaded
            orbital_indices = atom.valence_orbitals

        #
        qnumbers[Zi] = []
        radial_wfn[Zi] = []
        for i in orbital_indices:
            R_spl = spline_wavefunction(atom.r, \
                                        atom.radial_wavefunctions[i])
            n, l = atom.nshell[i], atom.angular_momenta[i]
            for m in range(-l, l + 1):
                qnumbers[Zi].append((n - 1, l, m))
                radial_wfn[Zi].append(R_spl)
    return qnumbers, radial_wfn
def load_pseudo_atoms_scattering(atomlist,
                                 E,
                                 rmin=rmin,
                                 rmax=rmax,
                                 Npts=Npts,
                                 unscreened_charge=0.0,
                                 lmax=2):
    """
    find the continuum orbitals at the photokinetic energy E for each atom type
    present in the molecule. The density of the pseudoatoms are read from file and
    the continuum orbitals are calculated by solving the radial Schroedinger equation
    for a single electron in the effective atomic potential of the cation (electrostatic + xc).
    The radial grid on which the continuum orbital is calculated can be specified using
    the keywords rmin, rmax and Npts.

    lmax is the angular momentum of the highest shell
    """
    atomtypes = list(set([Zi for (Zi, posi) in atomlist]))
    atomtypes.sort()
    valorbs = {}
    radial_val = {}
    phase_shifts = {}
    for Zi in atomtypes:
        # load pseudo atoms
        at = pseudo_atoms_list[Zi - 1]
        # cation
        Nelec = at.Z - unscreened_charge
        atomdft = PseudoAtomDFT(at.Z, Nelec, numerov_conv, en_conv)
        atomdft.setRadialGrid(rmin, rmax, Npts)
        atomdft.initialDensityGuess((at.r, at.radial_density * Nelec / at.Z))
        atomdft.KS_pot.getRadialPotential()

        # definition of valence shell
        valorbs[Zi] = []
        radial_val[Zi] = []
        phase_shifts[Zi] = []
        # compute scattering orbitals
        for l in range(
                0, lmax +
                1):  # each atom has an s-, 3 p-, 5-d,  ... scattering orbitals
            delta_l, u_l = atomdft.KS_pot.scattering_state(E, l)
            R_spl = spline_wavefunction(
                atomdft.getRadialGrid(),
                u_l,
                ug_asymptotic=CoulombWave(E, atomdft.KS_pot.unscreened_charge,
                                          l, delta_l))
            n = np.inf
            for m in range(-l, l + 1):
                valorbs[Zi].append((n, l, m))
                radial_val[Zi].append(R_spl)
                phase_shifts[Zi].append(delta_l)
    return valorbs, radial_val, phase_shifts
Ejemplo n.º 3
0
def load_pseudo_atoms_old(atomlist, confined=True):
    atomtypes = list(set([Zi for (Zi, posi) in atomlist]))
    atomtypes.sort()
    radial_val = {}
    valorbs = {}
    for Zi in atomtypes:
        # load radial orbitals of pseudo atoms
        confined_atom, free_atom = import_pseudo_atom(Zi)
        if confined == True:
            atom = confined_atom
        else:
            atom = free_atom
        # definition of valence shell
        valorbs[Zi] = []
        radial_val[Zi] = []
        for i in atom.valence_orbitals:
            R_spl = spline_wavefunction(atom.r, \
                                        atom.radial_wavefunctions[i])
            n, l = atom.nshell[i], atom.angular_momenta[i]
            for m in range(-l, l + 1):
                valorbs[Zi].append((n - 1, l, m))
                radial_val[Zi].append(R_spl)
    return valorbs, radial_val
    def getSKIntegrals(self, d, grid, E):
        k = np.sqrt(2 * E)
        wavelength = 2.0 * np.pi / k

        Npts = 25000  # number of radial grid points
        rmin = 0.0
        # make sure the grid is large enough so that the amplitude of the radial wavefunction
        # is close to that of the asymptotic solution
        rmax = 500.0 + 2.0 * wavelength
        print "rmax = %s bohr" % rmax

        # E is the energy of the scattering state
        R_valence1 = self.A1.getValenceOrbitals()
        R_valence2 = self.A2.getValenceOrbitals()
        # for the second atom the unbound orbitals are calculated
        # in the effective potential of the atom
        Z2 = self.A2.atom.Z
        at = pseudo_atoms_list[Z2 - 1]
        # cation, Nelec = Z - 1
        Nelec = at.Z - 0.99999
        atomdft = PseudoAtomDFT(at.Z, Nelec, numerov_conv, en_conv)
        atomdft.setRadialGrid(rmin, rmax, Npts)
        atomdft.initialDensityGuess((at.r, at.radial_density * Nelec / at.Z))
        atomdft.KS_pot.getRadialPotential()
        en2 = E
        # effective potentials
        Veff1_spl = self.A1.getEffectivePotential()
        Veff2_spl = self.A2.getEffectivePotential()

        self.S = {}
        self.H = {}
        self.PhaseShifts = {}
        self.d = d

        # overlaps and hamiltonian matrix elements
        print "OVERLAPS AND HAMILTONIANS"
        for i in T.index2tau.keys():
            l1, m1, l2, m2 = T.index2tau[i]
            print "l1=%s m1=%s l2=%s m2=%s" % (l1, m1, l2, m2)
            if (not R_valence1.has_key(l1)):
                continue
            """
            if (not R_valence2.has_key(l2)):
                # only add scattering orbitals if there is also a bound
                # orbital with the same l
                #  H: 1s bound      => only s scattering state
                #  C: 2s,2p bound   => s and p scattering states
                continue
            """
            en1, R1_spl = R_valence1[l1]
            # compute scattering orbital
            delta_l2, u_l2 = atomdft.KS_pot.scattering_state(en2, l2)
            R2_spl = spline_wavefunction(atomdft.getRadialGrid(), u_l2)

            # integration on two center polar grid
            olap = []
            Hpart = []
            for k, dk in enumerate(self.d):
                rhos, zs, areas = grid[0][k], grid[1][k], grid[2][k]
                #
                s,h,p1,p2 = integrands_tau((zs,rhos),dk/2.0, \
                        en1,l1,m1,R1_spl,Veff1_spl,self.A1.atom.r0, \
                        en2,l2,m2,R2_spl,Veff2_spl,self.A2.atom.r0)
                norm1 = sum(p1 * areas)
                norm2 = sum(p2 * areas)
                #                print "norm1 = %s" % norm1
                #                print "norm2 = %s" % norm2
                olap.append(sum(s * areas))
                Hpart.append(sum(h * areas))
            olap = np.array(olap)
            Hpart = np.array(Hpart)
            self.S[(l1, l2, i)] = olap
            #            self.H[(l1,l2,i)] = en2*olap + Hpart
            self.H[(l1, l2, i)] = en1 * olap + Hpart
            self.PhaseShifts[l2] = delta_l2
        # dipoles
        print "DIPOLES"
        self.Dipole = {}
        for i in Tdip.index2tau.keys():
            l1, m1, lM, mM, l2, m2 = Tdip.index2tau[i]
            print "l1=%s m1=%s l2=%s m2=%s" % (l1, m1, l2, m2)
            if not R_valence1.has_key(l1):
                continue
            """
            if (not R_valence2.has_key(l2)):
                # only add scattering orbitals if there is also a bound
                # orbital with the same l
                #  H: 1s bound      => only s scattering state
                #  C: 2s,2p bound   => s and p scattering states
                continue
            """
            en1, R1_spl = R_valence1[l1]
            # compute scattering orbital
            delta_l2, u_l2 = atomdft.KS_pot.scattering_state(en2, l2)
            R2_spl = spline_wavefunction(atomdft.getRadialGrid(), u_l2)

            # integration on two center polar grid
            Dippart = []
            for k, dk in enumerate(self.d):
                rhos, zs, areas = grid[0][k], grid[1][k], grid[2][k]
                #
                """
                if dk > 3.0:
                    from matplotlib.pyplot import plot,show
                    plot(rhos, zs, "o")
                    show()
                """
                #
                dip = integrands_tau_dipole((zs,rhos),dk/2.0, \
                        l1,m1,R1_spl, lM,mM, l2,m2,R2_spl)
                Dippart.append(sum(dip * areas))
            Dippart = np.array(Dippart)
            self.Dipole[(l1, l2, i)] = Dippart

        return self.S, self.H, (self.Dipole)
    def getSKIntegrals(self, d, grid, E):
        k = np.sqrt(2 * E)
        wavelength = 2.0 * np.pi / k

        Npts = 25000  # number of radial grid points
        rmin = 0.0
        rmax = 500.0 + 2.0 * wavelength

        # E is the energy of the scattering state
        Z1 = self.A1.atom.Z
        at1 = pseudo_atoms_list[Z1 - 1]
        atomdft1 = PseudoAtomDFT(at1.Z, at1.Z, numerov_conv, en_conv)
        atomdft1.setRadialGrid(rmin, rmax, Npts)
        atomdft1.initialDensityGuess((at1.r, at1.radial_density))
        atomdft1.KS_pot.getRadialPotential()
        en1 = E
        # for the second atom the unbound orbitals are calculated
        # in the effective potential of the atom
        Z2 = self.A2.atom.Z
        at2 = pseudo_atoms_list[Z2 - 1]
        atomdft2 = PseudoAtomDFT(at2.Z, at2.Z, numerov_conv, en_conv)
        atomdft2.setRadialGrid(rmin, rmax, Npts)
        atomdft2.initialDensityGuess((at2.r, at2.radial_density))
        atomdft2.KS_pot.getRadialPotential()
        en2 = E
        # effective potentials
        Veff1_spl = self.A1.getEffectivePotential()
        Veff2_spl = self.A2.getEffectivePotential()

        self.S = {}
        self.H = {}
        self.d = d

        # overlaps and hamiltonian matrix elements
        for i in T.index2tau.keys():
            l1, m1, l2, m2 = T.index2tau[i]
            print "l1 = %s  m1 = %s  l2 = %s  m2 = %s" % (l1, m1, l2, m2)
            # compute scattering orbital on atom 1
            delta_l1, u_l1 = atomdft1.KS_pot.scattering_state(en1, l1)
            R1_spl = spline_wavefunction(atomdft1.getRadialGrid(), u_l1)
            # compute scattering orbital on atom 2
            delta_l2, u_l2 = atomdft2.KS_pot.scattering_state(en2, l2)
            R2_spl = spline_wavefunction(atomdft2.getRadialGrid(), u_l2)

            # integration on two center polar grid
            olap = []
            Hpart = []
            for k, dk in enumerate(self.d):
                rhos, zs, areas = grid[0][k], grid[1][k], grid[2][k]
                #
                s,h,p1,p2 = integrands_tau((zs,rhos),dk/2.0, \
                        en1,l1,m1,R1_spl,Veff1_spl,self.A1.atom.r0, \
                        en2,l2,m2,R2_spl,Veff2_spl,self.A2.atom.r0)
                norm1 = sum(p1 * areas)
                norm2 = sum(p2 * areas)
                #                print "norm1 = %s" % norm1
                #                print "norm2 = %s" % norm2
                olap.append(sum(s * areas))
                Hpart.append(sum(h * areas))
            olap = np.array(olap)
            Hpart = np.array(Hpart)
            self.S[(l1, l2, i)] = olap
            #            self.H[(l1,l2,i)] = en2*olap + Hpart
            self.H[(l1, l2, i)] = en1 * olap + Hpart
            self.PhaseShifts[(l1, l2)] = np.exp(1.0j * (-delta_l1 + delta_l2))
        # dipoles
        self.Dipole = {}

        for i in Tdip.index2tau.keys():
            l1, m1, lM, mM, l2, m2 = Tdip.index2tau[i]
            # compute scattering orbital on atom 1
            delta_l1, u_l1 = atomdft1.KS_pot.scattering_state(en1, l1)
            R1_spl = spline_wavefunction(atomdft1.getRadialGrid(), u_l1)
            # compute scattering orbital on atom 2
            delta_l2, u_l2 = atomdft2.KS_pot.scattering_state(en2, l2)
            R2_spl = spline_wavefunction(atomdft2.getRadialGrid(), u_l2)

            # integration on two center polar grid
            Dippart = []
            for k, dk in enumerate(self.d):
                rhos, zs, areas = grid[0][k], grid[1][k], grid[2][k]
                #
                """
                if dk > 3.0:
                    from matplotlib.pyplot import plot,show
                    plot(rhos, zs, "o")
                    show()
                """
                #
                dip = integrands_tau_dipole((zs,rhos),dk/2.0, \
                        l1,m1,R1_spl, lM,mM, l2,m2,R2_spl)
                Dippart.append(sum(dip * areas))
            Dippart = np.array(Dippart)
            self.Dipole[(l1, l2, i)] = Dippart

        return self.S, self.H, (self.Dipole)