Пример #1
0
 def check_transformer_cache (self):
     assert (isinstance (self.smult, (int, np.number)))
     neleca, nelecb = _unpack_nelec (self.nelec)
     if self.transformer is None:
         self.transformer = CSFTransformer (self.norb, neleca, nelecb, self.smult)
     else:
         self.transformer._update_spin_cache (self.norb, neleca, nelecb, self.smult)
Пример #2
0
def hilbert_sector_weight(ci, norb, nelec, smult, is_hilbert=False):
    if np.asarray(nelec).size == 1:
        nelec = _unpack_nelec(nelec, spin=(smult - 1))
    if not is_hilbert:
        ci = fock2hilbert(ci, norb, nelec)
    norm = CSFTransformer(norb, nelec[0], nelec[1],
                          smult).vec_det2csf(ci,
                                             normalize=False,
                                             return_norm=True)[1]
    return norm**2
Пример #3
0
 def check_transformer_cache(self):
     assert (isinstance(self.smult, (int, np.number)))
     neleca, nelecb = _unpack_nelec(self.nelec)
     if isinstance(self.wfnsym, str):
         wfnsym = symm.irrep_name2id(self.mol.groupname, self.wfnsym)
     else:
         wfnsym = self.wfnsym
     if self.transformer is None:
         self.transformer = CSFTransformer(self.norb,
                                           neleca,
                                           nelecb,
                                           self.smult,
                                           orbsym=self.orbsym,
                                           wfnsym=wfnsym)
     else:
         self.transformer._update_spin_cache(self.norb, neleca, nelecb,
                                             self.smult)
         self.transformer._update_symm_cache(self.orbsym)
         self.transformer.wfnsym = wfnsym
Пример #4
0
 def debug_lagrange(self,
                    Lvec,
                    bvec,
                    Aop,
                    Adiag,
                    iroot=None,
                    mo=None,
                    ci=None,
                    **kwargs):
     if iroot is None: iroot = self.iroot
     if mo is None: mo = self.base.mo_coeff
     if ci is None: ci = self.base.ci
     lib.logger.info(
         self,
         '{} gradient: iroot = {}'.format(self.base.__class__.__name__,
                                          iroot))
     ngorb = self.ngorb
     nci = self.nci
     nroots = self.nroots
     ndet = nci // nroots
     ncore = self.base.ncore
     ncas = self.base.ncas
     nelecas = self.base.nelecas
     nocc = ncore + ncas
     nlag = self.nlag
     ci = np.asarray(self.base.ci).reshape(nroots, -1)
     err = Aop(Lvec) + bvec
     eorb = self.base.unpack_uniq_var(err[:ngorb])
     eci = err[ngorb:].reshape(nroots, -1)
     borb = self.base.unpack_uniq_var(bvec[:ngorb])
     bci = bvec[ngorb:].reshape(nroots, -1)
     Lorb = self.base.unpack_uniq_var(Lvec[:ngorb])
     Lci = Lvec[ngorb:].reshape(nroots, ndet)
     Aci = Adiag[ngorb:].reshape(nroots, ndet)
     Lci_ci_ovlp = (
         np.asarray(ci).reshape(nroots, -1).conjugate() @ Lci.T).T
     Lci_Lci_ovlp = (Lci.conjugate() @ Lci.T).T
     eci_ci_ovlp = (
         np.asarray(ci).reshape(nroots, -1).conjugate() @ eci.T).T
     bci_ci_ovlp = (
         np.asarray(ci).reshape(nroots, -1).conjugate() @ bci.T).T
     ci_ci_ovlp = ci.conjugate() @ ci.T
     lib.logger.debug(
         self,
         "{} gradient RHS, inactive-active orbital rotations:\n{}".format(
             self.base.__class__.__name__, borb[:ncore, ncore:nocc]))
     lib.logger.debug(
         self,
         "{} gradient RHS, inactive-external orbital rotations:\n{}".format(
             self.base.__class__.__name__, borb[:ncore, nocc:]))
     lib.logger.debug(
         self,
         "{} gradient RHS, active-external orbital rotations:\n{}".format(
             self.base.__class__.__name__, borb[ncore:nocc, nocc:]))
     lib.logger.debug(
         self,
         "{} gradient residual, inactive-active orbital rotations:\n{}".
         format(self.base.__class__.__name__, eorb[:ncore, ncore:nocc]))
     lib.logger.debug(
         self,
         "{} gradient residual, inactive-external orbital rotations:\n{}".
         format(self.base.__class__.__name__, eorb[:ncore, nocc:]))
     lib.logger.debug(
         self,
         "{} gradient residual, active-external orbital rotations:\n{}".
         format(self.base.__class__.__name__, eorb[ncore:nocc, nocc:]))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, inactive-active orbital rotations:\n{}"
         .format(self.base.__class__.__name__, Lorb[:ncore, ncore:nocc]))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, inactive-external orbital rotations:\n{}"
         .format(self.base.__class__.__name__, Lorb[:ncore, nocc:]))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, active-external orbital rotations:\n{}"
         .format(self.base.__class__.__name__, Lorb[ncore:nocc, nocc:]))
     '''
     lib.logger.debug (self, "{} gradient RHS, inactive-inactive orbital rotations (redundant!):\n{}".format (
         self.base.__class__.__name__, borb[:ncore,:ncore]))
     lib.logger.debug (self, "{} gradient RHS, active-active orbital rotations (redundant!):\n{}".format (
         self.base.__class__.__name__, borb[ncore:nocc,ncore:nocc]))
     lib.logger.debug (self, "{} gradient RHS, external-external orbital rotations (redundant!):\n{}".format (
         self.base.__class__.__name__, borb[nocc:,nocc:]))
     lib.logger.debug (self, "{} gradient Lagrange factor, inactive-inactive orbital rotations (redundant!):\n{}".format (
         self.base.__class__.__name__, Lorb[:ncore,:ncore]))
     lib.logger.debug (self, "{} gradient Lagrange factor, active-active orbital rotations (redundant!):\n{}".format (
         self.base.__class__.__name__, Lorb[ncore:nocc,ncore:nocc]))
     lib.logger.debug (self, "{} gradient Lagrange factor, external-external orbital rotations (redundant!):\n{}".format (
         self.base.__class__.__name__, Lorb[nocc:,nocc:]))
     '''
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, CI part overlap with true CI SA space:\n{}"
         .format(self.base.__class__.__name__, Lci_ci_ovlp))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, CI part self overlap matrix:\n{}".
         format(self.base.__class__.__name__, Lci_Lci_ovlp))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, CI vector self overlap matrix:\n{}".
         format(self.base.__class__.__name__, ci_ci_ovlp))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, CI part response overlap with SA space:\n{}"
         .format(self.base.__class__.__name__, bci_ci_ovlp))
     lib.logger.debug(
         self,
         "{} gradient Lagrange factor, CI part residual overlap with SA space:\n{}"
         .format(self.base.__class__.__name__, eci_ci_ovlp))
     neleca, nelecb = _unpack_nelec(nelecas)
     spin = neleca - nelecb + 1
     csf = CSFTransformer(ncas, neleca, nelecb, spin)
     ecsf = csf.vec_det2csf(eci, normalize=False, order='C')
     err_norm_det = linalg.norm(err)
     err_norm_csf = linalg.norm(np.append(eorb, ecsf.ravel()))
     lib.logger.debug(
         self,
         "{} gradient: determinant residual = {}, CSF residual = {}".format(
             self.base.__class__.__name__, err_norm_det, err_norm_csf))
     ci_lbls, ci_csf = csf.printable_largest_csf(ci,
                                                 10,
                                                 isdet=True,
                                                 normalize=True,
                                                 order='C')
     bci_lbls, bci_csf = csf.printable_largest_csf(bci,
                                                   10,
                                                   isdet=True,
                                                   normalize=False,
                                                   order='C')
     eci_lbls, eci_csf = csf.printable_largest_csf(eci,
                                                   10,
                                                   isdet=True,
                                                   normalize=False,
                                                   order='C')
     Lci_lbls, Lci_csf = csf.printable_largest_csf(Lci,
                                                   10,
                                                   isdet=True,
                                                   normalize=False,
                                                   order='C')
     Aci_lbls, Aci_csf = csf.printable_largest_csf(Aci,
                                                   10,
                                                   isdet=True,
                                                   normalize=False,
                                                   order='C')
     ncsf = bci_csf.shape[1]
     for iroot in range(self.nroots):
         lib.logger.debug(
             self,
             "{} gradient Lagrange factor, CI part root {} spin square: {}".
             format(self.base.__class__.__name__, iroot,
                    spin_square0(Lci[iroot], ncas, nelecas)))
         lib.logger.debug(self, "Base CI vector")
         for icsf in range(ncsf):
             lib.logger.debug(
                 self, '{} {}'.format(ci_lbls[iroot, icsf], ci_csf[iroot,
                                                                   icsf]))
         lib.logger.debug(self, "CI gradient:")
         for icsf in range(ncsf):
             lib.logger.debug(
                 self, '{} {}'.format(bci_lbls[iroot, icsf], bci_csf[iroot,
                                                                     icsf]))
         lib.logger.debug(self, "CI residual:")
         for icsf in range(ncsf):
             lib.logger.debug(
                 self, '{} {}'.format(eci_lbls[iroot, icsf], eci_csf[iroot,
                                                                     icsf]))
         lib.logger.debug(self, "CI Lagrange vector:")
         for icsf in range(ncsf):
             lib.logger.debug(
                 self, '{} {}'.format(Lci_lbls[iroot, icsf], Lci_csf[iroot,
                                                                     icsf]))
         lib.logger.debug(self, "Diagonal of Hessian matrix CI part:")
         for icsf in range(ncsf):
             lib.logger.debug(
                 self, '{} {}'.format(Aci_lbls[iroot, icsf], Aci_csf[iroot,
                                                                     icsf]))
     '''
Пример #5
0
class FCISolver (direct_spin1.FCISolver):
    r''' get_init_guess uses csfstring.py and csdstring.py to construct a spin-symmetry-adapted initial guess, and the Davidson algorithm is carried
    out in the CSF basis. However, the ci attribute is put in the determinant basis at the end of it all, and "ci0" is also assumed
    to be in the determinant basis.'''

    pspace_size = getattr(__config__, 'fci_csf_FCI_pspace_size', 200)

    def __init__(self, mol=None, smult=None):
        self.smult = smult
        self.transformer = None
        self.mask_cache = [0, 0, 0, 0]
        super().__init__(mol)

    def get_init_guess(self, norb, nelec, nroots, hdiag_csf, **kwargs):
        self.norb = norb
        self.nelec = nelec
        self.check_transformer_cache ()
        return get_init_guess (norb, nelec, nroots, hdiag_csf, self.transformer)

    def make_hdiag_csf (self, h1e, eri, norb, nelec, hdiag_det=None):
        self.norb = norb
        self.nelec = nelec
        self.check_transformer_cache ()
        return make_hdiag_csf (h1e, eri, norb, nelec, self.transformer, hdiag_det=hdiag_det)

    make_hdiag = make_hdiag_det

    def absorb_h1e (self, h1e, eri, norb, nelec, fac=1):
        h1e_c, h1e_s = unpack_h1e_cs (h1e)
        h2eff = super().absorb_h1e (h1e_c, eri, norb, nelec, fac)
        if h1e_s is not None:
            h2eff = tag_array (h2eff, h1e_s=h1e_s)
        return h2eff

    def contract_2e(self, eri, fcivec, norb, nelec, link_index=None, **kwargs):
        hc = super().contract_2e(eri, fcivec, norb, nelec, link_index, **kwargs)
        if hasattr (eri, 'h1e_s'):
           hc += direct_uhf.contract_1e ([eri.h1e_s, -eri.h1e_s], fcivec, norb, nelec, link_index)  
        return hc

    '''
    01/14/2019: Changing strategy; I'm now replacing the kernel and pspace functions instead of make_precond and eig
    '''

    def pspace (self, h1e, eri, norb, nelec, hdiag_det=None, hdiag_csf=None, npsp=200, **kwargs):
        self.norb = norb
        self.nelec = nelec
        self.check_transformer_cache ()
        return pspace (self, h1e, eri, norb, nelec, self.transformer, hdiag_det=hdiag_det,
            hdiag_csf=hdiag_csf, npsp=npsp)
        
    def kernel(self, h1e, eri, norb, nelec, ci0=None, **kwargs):
        self.norb = norb
        self.nelec = nelec
        if 'smult' in kwargs:
            self.smult = kwargs['smult']
            kwargs.pop ('smult')
        self.check_transformer_cache ()
        e, c = kernel (self, h1e, eri, norb, nelec, smult=self.smult,
            idx_sym=None, ci0=ci0, transformer=self.transformer, **kwargs)
        self.eci, self.ci = e, c
        return e, c

    def check_transformer_cache (self):
        assert (isinstance (self.smult, (int, np.number)))
        neleca, nelecb = _unpack_nelec (self.nelec)
        if self.transformer is None:
            self.transformer = CSFTransformer (self.norb, neleca, nelecb, self.smult)
        else:
            self.transformer._update_spin_cache (self.norb, neleca, nelecb, self.smult)
Пример #6
0
class FCISolver(direct_spin1_symm.FCISolver):
    r''' get_init_guess uses csfstring.py and csdstring.py to construct a spin-symmetry-adapted initial guess, and the Davidson algorithm is carried
    out in the CSF basis. However, the ci attribute is put in the determinant basis at the end of it all, and "ci0" is also assumed
    to be in the determinant basis.

    ...However, I want to also do point-group symmetry better than direct_spin1_symm...
    '''

    pspace_size = getattr(__config__, 'fci_csf_FCI_pspace_size', 200)

    def __init__(self, mol=None, smult=None):
        self.smult = smult
        self.transformer = None
        super().__init__(mol)

    make_hdiag = make_hdiag_det

    def absorb_h1e(self, h1e, eri, norb, nelec, fac=1):
        h1e_c, h1e_s = unpack_h1e_cs(h1e)
        h2eff = super().absorb_h1e(h1e_c, eri, norb, nelec, fac)
        if h1e_s is not None:
            h2eff = tag_array(h2eff, h1e_s=h1e_s)
        return h2eff

    def contract_2e(self, eri, fcivec, norb, nelec, link_index=None, **kwargs):
        hc = super().contract_2e(eri, fcivec, norb, nelec, link_index,
                                 **kwargs)
        if hasattr(eri, 'h1e_s'):
            hc += direct_uhf.contract_1e([eri.h1e_s, -eri.h1e_s], fcivec, norb,
                                         nelec, link_index)
        return hc

    def make_hdiag_csf(self, h1e, eri, norb, nelec, hdiag_det=None):
        self.norb, self.nelec = norb, nelec
        self.check_transformer_cache()
        return make_hdiag_csf(h1e,
                              eri,
                              norb,
                              nelec,
                              self.transformer,
                              hdiag_det=hdiag_det)

    def pspace(self,
               h1e,
               eri,
               norb,
               nelec,
               hdiag_det=None,
               hdiag_csf=None,
               npsp=200,
               **kwargs):
        self.norb, self.nelec = norb, nelec
        self.check_transformer_cache()
        return pspace(self,
                      h1e,
                      eri,
                      norb,
                      nelec,
                      self.transformer,
                      hdiag_det=hdiag_det,
                      hdiag_csf=hdiag_csf,
                      npsp=npsp)

    def kernel(self, h1e, eri, norb, nelec, ci0=None, **kwargs):
        ''' Over the top of the existing kernel, I just need to set the parameters and cache values related to spin.

        ...and electron configuration point group '''
        if 'nroots' not in kwargs:
            nroots = self.nroots
            kwargs['nroots'] = nroots
        orbsym_back = self.orbsym
        if 'orbsym' not in kwargs:
            kwargs['orbsym'] = self.orbsym
        orbsym = kwargs['orbsym']
        wfnsym_back = self.wfnsym
        if 'wfnsym' not in kwargs:
            wfnsym = self.wfnsym
            kwargs['wfnsym'] = wfnsym
        if self.verbose >= logger.WARN:
            self.check_sanity()
        self.norb = norb
        self.nelec = nelec
        if 'smult' in kwargs:
            self.smult = kwargs['smult']
            kwargs.pop('smult')

        # The order of the four things below is super sensitive
        self.orbsym = orbsym
        wfnsym = self.guess_wfnsym(norb, nelec, ci0, **kwargs)
        self.wfnsym = wfnsym
        kwargs['wfnsym'] = wfnsym
        self.check_transformer_cache()

        idx_sym = self.transformer.confsym[
            self.transformer.econf_csf_mask] == wfnsym
        e, c = kernel(self,
                      h1e,
                      eri,
                      norb,
                      nelec,
                      smult=self.smult,
                      idx_sym=idx_sym,
                      ci0=ci0,
                      transformer=self.transformer,
                      **kwargs)
        self.eci, self.ci = e, c

        self.orbsym = orbsym_back
        self.wfnsym = wfnsym_back
        return e, c

    def get_init_guess(self, norb, nelec, nroots, hdiag_csf, **kwargs):
        orbsym = kwargs['orbsym'] if 'orbsym' in kwargs else self.orbsym
        wfnsym = kwargs['wfnsym'] if 'wfnsym' in kwargs else self.wfnsym
        self.orbsym = orbsym
        self.wfnsym = wfnsym
        assert ((self.orbsym is not None) and (self.wfnsym is not None))
        self.norb = norb
        self.nelec = nelec
        self.check_transformer_cache()
        return get_init_guess(norb, nelec, nroots, hdiag_csf, self.transformer)

    def check_transformer_cache(self):
        assert (isinstance(self.smult, (int, np.number)))
        neleca, nelecb = _unpack_nelec(self.nelec)
        if isinstance(self.wfnsym, str):
            wfnsym = symm.irrep_name2id(self.mol.groupname, self.wfnsym)
        else:
            wfnsym = self.wfnsym
        if self.transformer is None:
            self.transformer = CSFTransformer(self.norb,
                                              neleca,
                                              nelecb,
                                              self.smult,
                                              orbsym=self.orbsym,
                                              wfnsym=wfnsym)
        else:
            self.transformer._update_spin_cache(self.norb, neleca, nelecb,
                                                self.smult)
            self.transformer._update_symm_cache(self.orbsym)
            self.transformer.wfnsym = wfnsym