def __init__(self, l_max=8, n=3, k=5, r0=None, timer=None):
        """
        Instantiate a new MultipoleExpansion object which computes
        the electrostatic interaction by direct summation using a
        telescoped multipole expansion.

        Parameters:
        -----------
        l_max:   Order of the expansion (maximum angular momentum,
                 typically 5 to 8)
        n:       Number of cells to combine during each telescoping step
        k:       Summation cutoff. The interaction range will be n**k 
                 (number of cells, typically k = 5).
        """
        if l_max < 1:
            raise ValueError('l_max must be >= 1.')
        if np.any(np.array(n) < 1):
            raise ValueError('n must be >= 1.')
        if np.any(np.array(k) < 1):
            raise ValueError('k must be >= 1.')

        self.l_max = l_max

        if type(n) == int:
            n = np.array([n] * 3)
        else:
            n = np.array(n)

        if len(n) != 3:
            raise TypeError('n must be an integer scalar or a 3-tuple.')

        # The multipole-to-multipole operation is carried out over the
        # range [self.n1, self.n2]
        self.n1 = -((n - 1) // 2)
        self.n2 = n // 2
        #self.dx = -0.5*(self.n1 + self.n2)

        # The multipole-to-local operation is carried out over cells farther
        # away, hence the range [self.m1, self.m2]
        n **= 2
        self.m1 = -((n - 1) // 2)
        self.m2 = n // 2

        if type(k) == int:
            self.k = np.array([k] * 3)
        else:
            self.k = np.array(k)

        if len(self.k) != 3:
            raise TypeError('k must be an integer scalar or a 3-tuple.')

        self.r0_v = None
        if r0 is not None:
            self.r0_v = np.asarray(r0).copy()

        if timer is None:
            self.timer = Timer('MultipoleExpansion')
        else:
            self.timer = timer

        # Last positions
        self.r_av = None
        # Last charges
        self.q_a = None
Beispiel #2
0
    def __init__(self,
                 symbol,
                 configuration={},
                 valence=[],
                 confinement=None,
                 xc='PW92',
                 convergence={
                     'density': 1E-7,
                     'energies': 1E-7
                 },
                 scalarrel=False,
                 rmax=100.0,
                 nodegpts=500,
                 mix=0.2,
                 itmax=200,
                 timing=False,
                 verbose=False,
                 txt=None,
                 restart=None,
                 write=None):
        """
        Make Kohn-Sham all-electron calculation for given atom.

        Examples:
        ---------
        atom=KSAllElectron('C')
        atom=KSAllElectron('C',confinement={'mode':'quadratic','r0':1.234})
        atom.run()

        Parameters:
        -----------
        symbol:         chemical symbol
        configuration:  e.g. {'2s':2,'2p':2}. Overrides (for orbitals given in dict) default
                        configuration from box.data.
        valence:        valence orbitals, e.g. ['2s','2p']. Overrides default valence from box.data.
        confinement:    additional confining potential (see ConfinementPotential class)
        etol:           sp energy tolerance for eigensolver (Hartree)
        convergence:    convergence criterion dictionary
                        * density: max change for integrated |n_old-n_new|
                        * energies: max change in single-particle energy (Hartree)
        scalarrel:      Use scalar relativistic corrections
        rmax:           radial cutoff
        nodegpts:       total number of grid points is nodegpts times the max number
                        of antinodes for all orbitals
        mix:            effective potential mixing constant
        itmax:          maximum number of iterations for self-consistency.
        timing:         output of timing summary
        verbose:        increase verbosity during iterations
        txt:            output file name for log data
        write:          filename: save rgrid, effective potential and
                        density to a file for further calculations.
        restart:        filename: make an initial guess for effective
                        potential and density from another calculation.
        """
        self.symbol = symbol
        self.valence = valence
        self.confinement = confinement
        self.xc = xc
        self.convergence = convergence
        self.scalarrel = scalarrel
        self.set_output(txt)
        self.itmax = itmax
        self.verbose = verbose
        self.nodegpts = nodegpts
        self.mix = mix
        self.timing = timing
        self.timer = Timer('KSAllElectron', txt=self.txt, enabled=self.timing)
        self.timer.start('init')
        self.restart = restart
        self.write = write

        # element data
        self.data = copy(data[self.symbol])
        self.Z = self.data['Z']
        if self.valence == []:
            self.valence = copy(data[self.symbol]['valence_orbitals'])

        # ... more specific
        self.occu = copy(data[self.symbol]['configuration'])
        nel_neutral = self.Z
        assert sum(self.occu.values()) == nel_neutral
        self.occu.update(configuration)
        self.nel = sum(self.occu.values())
        self.charge = nel_neutral - self.nel
        if self.confinement == None:
            self.confinement_potential = ConfinementPotential('none')
        else:
            self.confinement_potential = ConfinementPotential(
                **self.confinement)
        self.conf = None
        self.nucl = None
        self.exc = None
        if self.xc == 'PW92':
            self.xcf = XC_PW92()
        else:
            raise NotImplementedError('Not implemented xc functional: %s' % xc)

        # technical stuff
        self.maxl = 9
        self.maxn = 9
        self.plotr = {}
        self.unlg = {}
        self.Rnlg = {}
        self.unl_fct = {}
        self.Rnl_fct = {}
        self.veff_fct = None
        self.total_energy = 0.0

        maxnodes = max([n - l - 1 for n, l, nl in self.list_states()])
        self.rmin, self.rmax, self.N = (1E-2 / self.Z, rmax,
                                        (maxnodes + 1) * self.nodegpts)
        if self.scalarrel:
            print >> self.txt, 'Using scalar relativistic corrections.'
        print >> self.txt, 'max %i nodes, %i grid points' % (maxnodes, self.N)
        self.xgrid = np.linspace(0, np.log(self.rmax / self.rmin), self.N)
        self.rgrid = self.rmin * np.exp(self.xgrid)
        self.grid = RadialGrid(self.rgrid)
        self.timer.stop('init')
        print >> self.txt, self.get_comment()
        self.solved = False