Example #1
0
    def kernel(self, x0=None):
        '''TDA diagonalization solver
        '''
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        self.converged, self.e, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=self.nstates, lindep=self.lindep,
                              max_space=self.max_space,
                              verbose=self.verbose)

        mo_occ = self._scf.mo_occ
        tot_x_a = sum((occ>0).sum()*(occ==0).sum() for occ in mo_occ[0])
        self.xy = [(_unpack(xi, mo_occ),  # (X_alpha, X_beta)
                    (0, 0))  # (Y_alpha, Y_beta)
                   for xi in x1]
        #TODO: analyze CIS wfn point group symmetry
        return self.e, self.xy
Example #2
0
    def kernel(self, x0=None, nstates=None):
        '''TDDFT diagonalization solver
        '''
        mf = self._scf
        if mf._numint.libxc.is_hybrid_xc(mf.xc):
            raise RuntimeError('%s cannot be used with hybrid functional'
                               % self.__class__)
        self.check_sanity()
        self.dump_flags()
        if nstates is None:
            nstates = self.nstates
        else:
            self.nstates = nstates

        log = lib.logger.Logger(self.stdout, self.verbose)

        vind, hdiag = self.gen_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        def pickeig(w, v, nroots, envs):
            idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0]
            return w[idx], v[:,idx], idx

        self.converged, w2, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=nstates, lindep=self.lindep,
                              max_space=self.max_space, pick=pickeig,
                              verbose=log)

        mo_energy = self._scf.mo_energy
        mo_occ = self._scf.mo_occ
        occidx = numpy.where(mo_occ==2)[0]
        viridx = numpy.where(mo_occ==0)[0]
        e_ia = (mo_energy[viridx,None] - mo_energy[occidx]).T
        e_ia = numpy.sqrt(e_ia)
        def norm_xy(w, z):
            zp = e_ia * z.reshape(e_ia.shape)
            zm = w/e_ia * z.reshape(e_ia.shape)
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = lib.norm(x)**2 - lib.norm(y)**2
            norm = numpy.sqrt(.5/norm)  # normalize to 0.5 for alpha spin
            return (x*norm, y*norm)

        idx = numpy.where(w2 > POSTIVE_EIG_THRESHOLD**2)[0]
        self.e = numpy.sqrt(w2[idx])
        self.xy = [norm_xy(self.e[i], x1[i]) for i in idx]

        if self.chkfile:
            lib.chkfile.save(self.chkfile, 'tddft/e', self.e)
            lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy)

        log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV)
        return self.e, self.xy
Example #3
0
    def eig(self, op, x0=None, precond=None, **kwargs):
        if isinstance(op, numpy.ndarray):
            self.converged = True
            return scipy.linalg.eigh(op)

        self.converged, e, ci = \
                lib.davidson1(lambda xs: [op(x) for x in xs],
                              x0, precond, lessio=self.lessio, **kwargs)
        if kwargs['nroots'] == 1:
            self.converged = self.converged[0]
            e = e[0]
            ci = ci[0]
        return e, ci
Example #4
0
    def eig(self, op, x0=None, precond=None, **kwargs):
        if isinstance(op, numpy.ndarray):
            self.converged = True
            return scipy.linalg.eigh(op)

        # TODO: check the hermitian of Hamiltonian then determine whether to
        # call the non-hermitian diagonlization solver davidson_nosym1
        self.converged, e, ci = \
                lib.davidson1(lambda xs: [op(x) for x in xs],
                              x0, precond, lessio=self.lessio, **kwargs)
        if kwargs.get('nroots', 1) == 1:
            self.converged = self.converged[0]
            e = e[0]
            ci = ci[0]
        return e, ci
Example #5
0
File: cisd.py Project: eronca/pyscf
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(myci.stdout, verbose)

    mol = myci.mol
    nmo = myci.nmo
    nocc = myci.nocc
    nvir = nmo - nocc
    mo_energy = eris.fock.diagonal()
    diag = make_diagonal(mol, mo_energy, eris, nocc)
    ehf = diag[0]
    diag -= ehf

    if ci0 is None:
# MP2 initial guess
        e_i = mo_energy[:nocc]
        e_a = mo_energy[nocc:]
        ci0 = numpy.zeros(1+nocc*nvir+(nocc*nvir)**2)
        ci0[0] = 1
        t2 = 2*eris.voov.transpose(1,2,0,3) - eris.voov.transpose(1,2,3,0)
        t2 /= lib.direct_sum('i+j-a-b', e_i, e_i, e_a, e_a)
        ci0[1+nocc*nvir:] = t2.ravel()

    def op(xs):
        return [myci.contract(x, eris) for x in xs]

    def precond(x, e, *args):
        diagd = diag - (e-myci.level_shift)
        diagd[abs(diagd)<1e-8] = 1e-8
        return x / diagd

    def cisd_dot(x1, x2):
        return dot(x1, x2, nocc, nvir)

    conv, ecisd, ci = lib.davidson1(op, ci0, precond, tol=tol,
                                    max_cycle=max_cycle, max_space=myci.max_space,
                                    lindep=myci.lindep, dot=cisd_dot,
                                    nroots=myci.nroots, verbose=log)
    if myci.nroots == 1:
        ecisd = ecisd[0]
        ci = ci[0]
    return conv, ecisd, ci
Example #6
0
    def kernel(self, x0=None, nstates=None):
        '''TDA diagonalization solver
        '''
        self.check_sanity()
        self.dump_flags()
        if nstates is None:
            nstates = self.nstates
        else:
            self.nstates = nstates

        log = logger.Logger(self.stdout, self.verbose)

        vind, hdiag = self.gen_vind(self._scf)
        precond = self.get_precond(hdiag)

        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        def pickeig(w, v, nroots, envs):
            idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0]
            return w[idx], v[:,idx], idx

        self.converged, self.e, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=nstates, lindep=self.lindep,
                              max_space=self.max_space, pick=pickeig,
                              verbose=log)

        nocc = (self._scf.mo_occ>0).sum()
        nmo = self._scf.mo_occ.size
        nvir = nmo - nocc
# 1/sqrt(2) because self.x is for alpha excitation amplitude and 2(X^+*X) = 1
        self.xy = [(xi.reshape(nocc,nvir)*numpy.sqrt(.5),0) for xi in x1]

        if self.chkfile:
            lib.chkfile.save(self.chkfile, 'tddft/e', self.e)
            lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy)

        log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV)
        return self.e, self.xy
Example #7
0
    def kernel(self, x0=None):
        '''TDA diagonalization solver
        '''
        self.check_sanity()

        mo_energy = self._scf.mo_energy
        nocc = (self._scf.mo_occ>0).sum()
        eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])

        if x0 is None:
            x0 = self.init_guess(eai, self.nstates)

        precond = self.get_precond(eai.ravel())

        self.e, x1 = lib.davidson1(self.get_vind, x0, precond,
                                   tol=self.conv_tol,
                                   nroots=self.nstates, lindep=self.lindep,
                                   max_space=self.max_space,
                                   verbose=self.verbose)[1:]
# 1/sqrt(2) because self.x is for alpha excitation amplitude and 2(X^+*X) = 1
        self.xy = [(xi.reshape(eai.shape)*numpy.sqrt(.5),0) for xi in x1]
        return self.e, self.xy
Example #8
0
    def kernel(self, x0=None):
        '''TDDFT diagonalization solver
        '''
        mf = self._scf
        if mf._numint.libxc.is_hybrid_xc(mf.xc):
            raise RuntimeError('%s cannot be applied with hybrid functional'
                               % self.__class__)
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.gen_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        w2, x1 = lib.davidson1(vind, x0, precond,
                               tol=self.conv_tol,
                               nroots=self.nstates, lindep=self.lindep,
                               max_space=self.max_space,
                               verbose=self.verbose)[1:]

        mo_energy = self._scf.mo_energy
        mo_occ = self._scf.mo_occ
        occidx = numpy.where(mo_occ==2)[0]
        viridx = numpy.where(mo_occ==0)[0]
        eai = lib.direct_sum('a-i->ai', mo_energy[viridx], mo_energy[occidx])
        eai = numpy.sqrt(eai)
        def norm_xy(w, z):
            zp = eai * z.reshape(eai.shape)
            zm = w/eai * z.reshape(eai.shape)
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = 2*(lib.norm(x)**2 - lib.norm(y)**2)
            norm = 1/numpy.sqrt(norm)
            return (x*norm, y*norm)

        self.e = numpy.sqrt(w2)
        self.xy = [norm_xy(self.e[i], z) for i, z in enumerate(x1)]
        return self.e, self.xy
Example #9
0
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(myci.stdout, verbose)

    mol = myci.mol
    nmo = myci.nmo
    nocc = myci.nocc
    nvir = nmo - nocc
    diag = myci.make_diagonal(eris)
    ehf = diag[0]
    diag -= ehf

    if ci0 is None:
        ci0 = myci.get_init_guess(eris)[1]

    def op(xs):
        return [myci.contract(x, eris) for x in xs]

    def precond(x, e, *args):
        diagd = diag - (e-myci.level_shift)
        diagd[abs(diagd)<1e-8] = 1e-8
        return x / diagd

    def cisd_dot(x1, x2):
        return dot(x1, x2, nocc, nvir)

    conv, ecisd, ci = lib.davidson1(op, ci0, precond, tol=tol,
                                    max_cycle=max_cycle, max_space=myci.max_space,
                                    lindep=myci.lindep, dot=cisd_dot,
                                    nroots=myci.nroots, verbose=log)
    if myci.nroots == 1:
        conv = conv[0]
        ecisd = ecisd[0]
        ci = ci[0]
    return conv, ecisd, ci
Example #10
0
File: rks.py Project: v3op01/pyscf
    def kernel(self, x0=None):
        '''TDDFT diagonalization solver
        '''
        if self._scf._numint.libxc.is_hybrid_xc(self._scf.xc):
            raise RuntimeError('%s cannot be applied with hybrid functional'
                               % self.__class__)

        self.check_sanity()

        mo_energy = self._scf.mo_energy
        nocc = (self._scf.mo_occ>0).sum()
        eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])

        if x0 is None:
            x0 = self.init_guess(eai, self.nstates)

        precond = self.get_precond(eai.ravel()**2)

        w2, x1 = lib.davidson1(self.get_vind, x0, precond,
                               tol=self.conv_tol,
                               nroots=self.nstates, lindep=self.lindep,
                               max_space=self.max_space,
                               verbose=self.verbose)[1:]
        self.e = numpy.sqrt(w2)
        eai = numpy.sqrt(eai)
        def norm_xy(w, z):
            zp = eai * z.reshape(eai.shape)
            zm = w/eai * z.reshape(eai.shape)
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = 2*(lib.norm(x)**2 - lib.norm(y)**2)
            norm = 1/numpy.sqrt(norm)
            return x*norm,y*norm

        self.xy = [norm_xy(self.e[i], z) for i, z in enumerate(x1)]

        return self.e, self.xy
Example #11
0
    def kernel(self, x0=None):
        '''TDA diagonalization solver
        '''
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)

        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)
        self.e, x1 = lib.davidson1(vind,
                                   x0,
                                   precond,
                                   tol=self.conv_tol,
                                   nroots=self.nstates,
                                   lindep=self.lindep,
                                   max_space=self.max_space,
                                   verbose=self.verbose)[1:]

        mo_occ = self._scf.mo_occ
        # 1/sqrt(2) because self.x is for alpha excitation amplitude and 2(X^+*X) = 1
        self.xy = [(_unpack(xi * numpy.sqrt(.5), mo_occ), 0) for xi in x1]
        return self.e, self.xy
Example #12
0
    def kernel(self, x0=None):
        '''TDA diagonalization solver
        '''
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.gen_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        def pickeig(w, v, nroots, envs):
            idx = numpy.where(w > POSTIVE_EIG_THRESHOLD)[0]
            return w[idx], v[:, idx], idx

        log = logger.Logger(self.stdout, self.verbose)
        precision = self.cell.precision * 1e-2
        hermi = 1

        self.converged, self.e, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=self.nstates, lindep=self.lindep,
                              max_space=self.max_space, pick=pickeig,
                              fill_heff=purify_krlyov_heff(precision, hermi, log),
                              verbose=self.verbose)

        mo_occ = self._scf.mo_occ
        self.xy = [
            (
                _unpack(xi, mo_occ),  # (X_alpha, X_beta)
                (0, 0))  # (Y_alpha, Y_beta)
            for xi in x1
        ]
        #TODO: analyze CIS wfn point group symmetry
        return self.e, self.xy
Example #13
0
    def kernel(self, x0=None):
        '''TDA diagonalization solver
        '''
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        self.e, x1 = lib.davidson1(vind, x0, precond,
                                   tol=self.conv_tol,
                                   nroots=self.nstates, lindep=self.lindep,
                                   max_space=self.max_space,
                                   verbose=self.verbose)[1:]

        mo_occ = self._scf.mo_occ
        tot_x_a = sum((occ>0).sum()*(occ==0).sum() for occ in mo_occ[0])
        self.xy = [(_unpack(xi, mo_occ),  # (X_alpha, X_beta)
                    (0, 0))  # (Y_alpha, Y_beta)
                   for xi in x1]
        #TODO: analyze CIS wfn point group symmetry
        return self.e, self.xy
Example #14
0
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO):
    '''
    Run CISD calculation.

    Args:
        myci : CISD (inheriting) object
        eris : ccsd._ChemistsERIs (inheriting) object (poss diff for df)
            Contains the various (pq|rs) integrals needed.

    Kwargs:
        ci0 : (List of) numpy array(s) (if None it will set)
            Initial guess for CISD coeffs.
        max_cycle : integer
            Maximum number of iterations to converge to CISD solution.
            If not converged before, calculation stops without having
            converged.
        tol : float
            Convergence tolerance.
        verbose : integer
            Level of output (roughly: the higher, the more output).

    Returns:
        conv : bool
            Is it converged?
        ecisd : List of floats or float
            The lowest :attr:`myci.nroots` eigenvalues.
        ci : List of 1D arrays or 1D array
            The lowest :attr:`myci.nroots` eigenvectors.
    '''
    log = logger.new_logger(myci, verbose)
    diag = myci.make_diagonal(eris)
    # Note that ehf is not the HF energy (see `make_diagonal`).
    ehf = diag[0]
    diag -= ehf

    if ci0 is None:
        ci0 = myci.get_init_guess(eris=eris, nroots=myci.nroots, diag=diag)[1]

    def op(xs):
        return [myci.contract(x, eris) for x in xs]

    def precond(x, e, *args):
        diagd = diag - (e - myci.level_shift)
        diagd[abs(diagd) < 1e-8] = 1e-8
        return x / diagd

    if myci._dot is not None:
        nmo = myci.nmo
        nocc = myci.nocc

        def cisd_dot(x1, x2):
            return myci._dot(x1, x2, nmo, nocc)
    else:
        cisd_dot = numpy.dot

    conv, ecisd, ci = lib.davidson1(op,
                                    ci0,
                                    precond,
                                    tol=tol,
                                    max_cycle=max_cycle,
                                    max_space=myci.max_space,
                                    lindep=myci.lindep,
                                    dot=cisd_dot,
                                    nroots=myci.nroots,
                                    verbose=log)
    if myci.nroots == 1:
        conv = conv[0]
        ecisd = ecisd[0]
        ci = ci[0]
    return conv, ecisd, ci
Example #15
0
    def kernel(self, x0=None, nstates=None):
        '''TDDFT diagonalization solver
        '''
        cpu0 = (time.clock(), time.time())
        mf = self._scf
        if mf._numint.libxc.is_hybrid_xc(mf.xc):
            raise RuntimeError('%s cannot be used with hybrid functional' %
                               self.__class__)
        self.check_sanity()
        self.dump_flags()
        if nstates is None:
            nstates = self.nstates
        else:
            self.nstates = nstates
        log = lib.logger.Logger(self.stdout, self.verbose)

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)

        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        def pickeig(w, v, nroots, envs):
            idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0]
            return w[idx], v[:, idx], idx

        self.converged, w2, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=nstates, lindep=self.lindep,
                              max_space=self.max_space, pick=pickeig,
                              verbose=log)

        mo_energy = self._scf.mo_energy
        mo_occ = self._scf.mo_occ
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        e_ia = numpy.sqrt(e_ia)

        e = []
        xy = []
        for i, z in enumerate(x1):
            if w2[i] < POSTIVE_EIG_THRESHOLD**2:
                continue
            w = numpy.sqrt(w2[i])
            zp = e_ia * z
            zm = w / e_ia * z
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = lib.norm(x)**2 - lib.norm(y)**2
            if norm > 0:
                norm = 1 / numpy.sqrt(norm)
                e.append(w)
                xy.append((
                    (
                        x[:nocca * nvira].reshape(nocca, nvira) *
                        norm,  # X_alpha
                        x[nocca * nvira:].reshape(noccb, nvirb) *
                        norm),  # X_beta
                    (
                        y[:nocca * nvira].reshape(nocca, nvira) *
                        norm,  # Y_alpha
                        y[nocca * nvira:].reshape(noccb, nvirb) *
                        norm)))  # Y_beta
        self.e = numpy.array(e)
        self.xy = xy

        if self.chkfile:
            lib.chkfile.save(self.chkfile, 'tddft/e', self.e)
            lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy)

        log.timer('TDDFT', *cpu0)
        log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV)
        return self.e, self.xy
Example #16
0
    def kernel(self, x0=None, nstates=None):
        '''TDDFT diagonalization solver
        '''
        mf = self._scf
        if mf._numint.libxc.is_hybrid_xc(mf.xc):
            raise RuntimeError('%s cannot be used with hybrid functional'
                               % self.__class__)
        self.check_sanity()
        self.dump_flags()
        if nstates is None:
            nstates = self.nstates
        else:
            self.nstates = nstates
        log = lib.logger.Logger(self.stdout, self.verbose)

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)

        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        def pickeig(w, v, nroots, envs):
            idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0]
            return w[idx], v[:,idx], idx

        self.converged, w2, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=nstates, lindep=self.lindep,
                              max_space=self.max_space, pick=pickeig,
                              verbose=log)

        mo_energy = self._scf.mo_energy
        mo_occ = self._scf.mo_occ
        occidxa = numpy.where(mo_occ[0]>0)[0]
        occidxb = numpy.where(mo_occ[1]>0)[0]
        viridxa = numpy.where(mo_occ[0]==0)[0]
        viridxb = numpy.where(mo_occ[1]==0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        e_ia_a = (mo_energy[0][viridxa,None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb,None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        e_ia = numpy.sqrt(e_ia)

        e = []
        xy = []
        for i, z in enumerate(x1):
            if w2[i] < POSTIVE_EIG_THRESHOLD**2:
                continue
            w = numpy.sqrt(w2[i])
            zp = e_ia * z
            zm = w/e_ia * z
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = lib.norm(x)**2 - lib.norm(y)**2
            if norm > 0:
                norm = 1/numpy.sqrt(norm)
                e.append(w)
                xy.append(((x[:nocca*nvira].reshape(nocca,nvira) * norm,  # X_alpha
                            x[nocca*nvira:].reshape(noccb,nvirb) * norm), # X_beta
                           (y[:nocca*nvira].reshape(nocca,nvira) * norm,  # Y_alpha
                            y[nocca*nvira:].reshape(noccb,nvirb) * norm)))# Y_beta
        self.e = numpy.array(e)
        self.xy = xy

        if self.chkfile:
            lib.chkfile.save(self.chkfile, 'tddft/e', self.e)
            lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy)

        log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV)
        return self.e, self.xy
Example #17
0
    def kernel(self, x0=None, nstates=None):
        '''TDDFT diagonalization solver
        '''
        cpu0 = (lib.logger.process_clock(), lib.logger.perf_counter())
        mf = self._scf
        if mf._numint.libxc.is_hybrid_xc(mf.xc):
            raise RuntimeError('%s cannot be used with hybrid functional' %
                               self.__class__)
        self.check_sanity()
        self.dump_flags()
        if nstates is None:
            nstates = self.nstates
        else:
            self.nstates = nstates

        log = lib.logger.Logger(self.stdout, self.verbose)

        vind, hdiag = self.gen_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        def pickeig(w, v, nroots, envs):
            idx = numpy.where(w > self.positive_eig_threshold)[0]
            return w[idx], v[:, idx], idx

        self.converged, w2, x1 = \
                lib.davidson1(vind, x0, precond,
                              tol=self.conv_tol,
                              nroots=nstates, lindep=self.lindep,
                              max_cycle=self.max_cycle,
                              max_space=self.max_space, pick=pickeig,
                              verbose=log)

        mo_energy = self._scf.mo_energy
        mo_occ = self._scf.mo_occ
        occidx = numpy.where(mo_occ == 1)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        e_ia = (mo_energy[viridx, None] - mo_energy[occidx]).T
        e_ia = numpy.sqrt(e_ia)

        def norm_xy(w, z):
            zp = e_ia * z.reshape(e_ia.shape)
            zm = w / e_ia * z.reshape(e_ia.shape)
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = lib.norm(x)**2 - lib.norm(y)**2
            norm = numpy.sqrt(1. / norm)
            return (x * norm, y * norm)

        idx = numpy.where(w2 > self.positive_eig_threshold)[0]
        self.e = numpy.sqrt(w2[idx])
        self.xy = [norm_xy(self.e[i], x1[i]) for i in idx]

        if self.chkfile:
            lib.chkfile.save(self.chkfile, 'tddft/e', self.e)
            lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy)

        log.timer('TDDFT', *cpu0)
        self._finalize()
        return self.e, self.xy
Example #18
0
 def davidson(self, *args, **kwargs):
     return lib.davidson1(*args, **kwargs)
Example #19
0
def davidson(auxspc, phys, chempot=None, nroots=1, which='SM', tol=1e-14, maxiter=None, ntrial=None):
    ''' Diagonalise the result of :func:`AuxiliarySpace.get_array` using
        the sparse :func:`AuxiliarySpace.dot` method, with the Davidson
        algorithm.

        This algorithm may perform poorly for IPs or EAs if they are
        not extremal eigenvalues, which they are not in standard AGF2.

    Args:
        auxspc : AuxiliarySpace or subclass
            Auxiliary space object to solve for
        phys : 2D array
            Physical space (1p + 1h), typically the Fock matrix

    Kwargs:
        chempot : float
            If provided, use instead of :attr:`self.chempot`
        nroots : int
            Number of roots to solve for. Default 1.
        which : str
            Which eigenvalues to solve for. Options are:
             `LM` : Largest (in magnitude) eigenvalues.
             `SM` : Smallest (in magnitude) eigenvalues.
             `LA` : Largest (algebraic) eigenvalues.
             `SA` : Smallest (algebraic) eigenvalues.
            Default 'SM'.
        tol : float
            Convergence threshold
        maxiter : int
            Maximum number of iterations. Default 10*dim
        ntrial : int
            Maximum number of trial vectors. Default
            min(dim, max(2*nroots+1, 20))

    Returns:
        tuple of ndarrays (eigenvalues, eigenvectors)
    '''

    _check_phys_shape(auxspc, phys)
    dim = auxspc.nphys + auxspc.naux

    if maxiter is None:
        maxiter = 10 * dim

    if ntrial is None:
        ntrial = min(dim, max(2*nroots+1, 20))

    if which not in ['SM', 'LM', 'SA', 'LA']:
        raise ValueError(which)

    if which in ['SM', 'LM']:
        abs_op = np.absolute
    else:
        abs_op = lambda x: x

    if which in ['SM', 'SA']:
        order = 1
    else:
        order = -1

    matvec = lambda x: auxspc.dot(phys, np.asarray(x))
    diag = np.concatenate([np.diag(phys), auxspc.energy])
    guess = [np.zeros((dim)) for n in range(nroots)]

    mask = np.argsort(abs_op(diag))[::order]
    for i in range(nroots):
        guess[i][mask[i]] = 1

    def pick(w, v, nroots, callback):
        mask = np.argsort(abs_op(w))
        mask = mask[::order]
        w = w[mask]
        v = v[:,mask]
        return w, v, 0

    conv, w, v = lib.davidson1(matvec, guess, diag, tol=tol, nroots=nroots,
                               max_space=ntrial, max_cycle=maxiter, pick=pick)

    return conv, w, v
Example #20
0
    def kernel(self, x0=None):
        '''TDDFT diagonalization solver
        '''
        mf = self._scf
        if mf._numint.libxc.is_hybrid_xc(mf.xc):
            raise RuntimeError('%s cannot be applied with hybrid functional' %
                               self.__class__)
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)

        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        w2, x1 = lib.davidson1(vind,
                               x0,
                               precond,
                               tol=self.conv_tol,
                               nroots=self.nstates,
                               lindep=self.lindep,
                               max_space=self.max_space,
                               verbose=self.verbose)[1:]

        mo_energy = self._scf.mo_energy
        mo_occ = self._scf.mo_occ
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        e_ai_a = mo_energy[0][viridxa].reshape(-1, 1) - mo_energy[0][occidxa]
        e_ai_b = mo_energy[1][viridxb].reshape(-1, 1) - mo_energy[1][occidxb]
        eai = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1)))
        eai = numpy.sqrt(eai)

        e = []
        xy = []
        for i, z in enumerate(x1):
            if w2[i] < 0:
                continue
            w = numpy.sqrt(w2[i])
            zp = eai * z
            zm = w / eai * z
            x = (zp + zm) * .5
            y = (zp - zm) * .5
            norm = lib.norm(x)**2 - lib.norm(y)**2
            if norm > 0:
                norm = 1 / numpy.sqrt(norm)
                e.append(w)
                xy.append((
                    (
                        x[:nocca * nvira].reshape(nvira, nocca) *
                        norm,  # X_alpha
                        x[nocca * nvira:].reshape(nvirb, noccb) *
                        norm),  # X_beta
                    (
                        y[:nocca * nvira].reshape(nvira, nocca) *
                        norm,  # Y_alpha
                        y[nocca * nvira:].reshape(nvirb, noccb) *
                        norm)))  # Y_beta
        self.e = numpy.array(e)
        self.xy = xy
        return self.e, self.xy