예제 #1
0
def guess_wfnsym(ci, norb, nelec, orbsym):
    '''Guess the wavefunction symmetry based on the non-zero elements in the
    given CI coefficients.

    Args:
        ci : 2D array
            CI coefficients, row for alpha strings and column for beta strings.
        norb : int
            Number of orbitals.
        nelec : int or 2-item list
            Number of electrons, or 2-item list for (alpha, beta) electrons
        orbsym : list of int
            The irrep ID for each orbital.

    Returns:
        Irrep ID
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    if isinstance(ci, numpy.ndarray) and ci.ndim <= 2:
        wfnsym = _guess_wfnsym(ci, strsa, strsb, orbsym)
    else:
        wfnsym = [_guess_wfnsym(c, strsa, strsb, orbsym) for c in ci]
        if any(wfnsym[0] != x for x in wfnsym):
            warnings.warn('Different wfnsym %s found in different CI vecotrs' %
                          wfnsym)
        wfnsym = wfnsym[0]
    return wfnsym
예제 #2
0
def symmetrize_wfn(ci, norb, nelec, orbsym, wfnsym=0):
    '''Symmetrize the CI wavefunction by zeroing out the determinants which
    do not have the right symmetry.

    Args:
        ci : 2D array
            CI coefficients, row for alpha strings and column for beta strings.
        norb : int
            Number of orbitals.
        nelec : int or 2-item list
            Number of electrons, or 2-item list for (alpha, beta) electrons
        orbsym : list of int
            The irrep ID for each orbital.

    Kwags:
        wfnsym : int
            The irrep ID of target symmetry

    Returns:
        2D array which is the symmetrized CI coefficients
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    return _symmetrize_wfn(ci, strsa, strsb, orbsym, wfnsym)
예제 #3
0
def gen_frag_basis (psi, ifrag, ci_f=None, nelec=None):
    if ci_f is None: ci_f = psi.ci0_f
    norb, norb_f, nfrag = psi.norb, psi.norb_f, psi.nfrag
    ci0 = np.ones ([1,1], dtype=ci_f[0].dtype)
    n = 0
    for jfrag, (c, dn) in enumerate (zip (ci_f, norb_f)):
        if (ifrag == jfrag): continue
        n += dn
        ndet = 2**n
        ci0 = np.multiply.outer (c, ci0).transpose (0,2,1,3).reshape (ndet, ndet)
    n = norb_f[ifrag]
    ndet = 2**norb
    ci1 = np.empty ((ndet, ndet), dtype=ci_f[0].dtype)
    norb0 = sum (norb_f[ifrag+1:]) if ifrag+1<nfrag else 0 
    norb1 = norb_f[ifrag]
    norb2 = sum (norb_f[:ifrag]) if ifrag>0 else 0
    ndet0, ndet1, ndet2 = 2**norb0, 2**norb1, 2**norb2
    deta_gen, detb_gen = range (ndet1), range (ndet1)
    if nelec is not None:
        nelec = _unpack_nelec (nelec)
        deta_gen = make_strings (range (norb1), nelec[0])
        detb_gen = make_strings (range (norb1), nelec[1])
    for ideta, idetb in product (deta_gen, detb_gen):
        ci1[:,:] = 0
        ci1 = ci1.reshape (ndet0, ndet1, ndet2, ndet0, ndet1, ndet2)
        ci1[:,ideta,:,:,idetb,:] = ci0.reshape (ndet0, ndet2, ndet0, ndet2)
        ci1 = ci1.reshape (ndet, ndet)
        ci1 = psi.fermion_spin_shuffle (ci1)
        yield ideta, idetb, ci1
예제 #4
0
파일: addons.py 프로젝트: sunqm/pyscf
def symmetrize_wfn(ci, norb, nelec, orbsym, wfnsym=0):
    '''Symmetrize the CI wavefunction by zeroing out the determinants which
    do not have the right symmetry.

    Args:
        ci : 2D array
            CI coefficients, row for alpha strings and column for beta strings.
        norb : int
            Number of orbitals.
        nelec : int or 2-item list
            Number of electrons, or 2-item list for (alpha, beta) electrons
        orbsym : list of int
            The irrep ID for each orbital.

    Kwags:
        wfnsym : int
            The irrep ID of target symmetry

    Returns:
        2D array which is the symmetrized CI coefficients
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    return _symmetrize_wfn(ci, strsa, strsb, orbsym, wfnsym)
예제 #5
0
    def guess_wfnsym(self,
                     norb,
                     nelec,
                     fcivec=None,
                     orbsym=None,
                     wfnsym=None,
                     **kwargs):
        '''
        Guess point group symmetry of the FCI wavefunction.  If fcivec is
        given, the symmetry of fcivec is used.  Otherwise the symmetry is
        based on the HF determinant.
        '''
        if orbsym is None:
            orbsym = self.orbsym

        verbose = kwargs.get('verbose', None)
        log = logger.new_logger(self, verbose)

        nelec = _unpack_nelec(nelec, self.spin)
        if fcivec is None:
            # guess wfnsym if initial guess is not given
            wfnsym = _id_wfnsym(self, norb, nelec, orbsym, wfnsym)
            log.debug('Guessing CI wfn symmetry = %s', wfnsym)

        elif wfnsym is None:
            wfnsym = addons.guess_wfnsym(fcivec, norb, nelec, orbsym)
            log.debug('Guessing CI wfn symmetry = %s', wfnsym)

        else:
            # verify if the input wfnsym is consistent with the symmetry of fcivec
            neleca, nelecb = nelec
            strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
            strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
            na, nb = strsa.size, strsb.size

            orbsym_in_d2h = numpy.asarray(orbsym) % 10
            airreps = numpy.zeros(na, dtype=numpy.int32)
            birreps = numpy.zeros(nb, dtype=numpy.int32)
            for i, ir in enumerate(orbsym_in_d2h):
                airreps[numpy.bitwise_and(strsa, 1 << i) > 0] ^= ir
                birreps[numpy.bitwise_and(strsb, 1 << i) > 0] ^= ir

            wfnsym = _id_wfnsym(self, norb, nelec, orbsym, wfnsym)
            mask = (airreps.reshape(-1, 1) ^ birreps) == wfnsym

            if isinstance(fcivec, numpy.ndarray) and fcivec.ndim <= 2:
                fcivec = [fcivec]
            if all(abs(c.reshape(na, nb)[mask]).max() < 1e-5 for c in fcivec):
                raise RuntimeError(
                    'Input wfnsym is not consistent with fcivec coefficients')

        return wfnsym
예제 #6
0
    def test_spin0_contract_2e_symm(self):
        norb, nelec = 7, (4,4)
        strs = cistring.make_strings(range(norb), nelec[0])
        numpy.random.seed(11)
        mask = numpy.random.random(len(strs)) > .3
        strsa = strs[mask]
        ci_strs = (strsa, strsa)
        na = len(strsa)
        ci_coeff = numpy.random.random((na,na))
        ci_coeff = ci_coeff + ci_coeff.T
        civec_strs = selected_ci._as_SCIvector(ci_coeff, ci_strs)
        orbsym = (numpy.random.random(norb) * 4).astype(int)
        nn = norb*(norb+1)//2
        eri = ao2mo.restore(1, (numpy.random.random(nn*(nn+1)//2)-.2)**3, norb)
        oosym = orbsym[:,None] ^ orbsym
        oosym = oosym.reshape(-1,1) ^ oosym.ravel()
        eri[oosym.reshape([norb]*4)!=0] = 0

        ci0 = fci.selected_ci.to_fci(civec_strs, norb, nelec)
        ci0 = fci.addons.symmetrize_wfn(ci0, norb, nelec, orbsym)
        civec_strs = fci.selected_ci.from_fci(ci0, civec_strs._strs, norb, nelec)

        myci = selected_ci_spin0_symm.SCI()
        e1 = numpy.dot(civec_strs.ravel(), myci.contract_2e(eri, civec_strs, norb, nelec, orbsym=orbsym).ravel())
        e2 = numpy.dot(ci0.ravel(), direct_spin1_symm.contract_2e(eri, ci0, norb, nelec, orbsym=orbsym).ravel())
        self.assertAlmostEqual(e1, e2, 9)
예제 #7
0
    def test_rdm_2e(self):
        norb, nelec = 10, 1
        strs = cistring.make_strings(range(norb), nelec)
        numpy.random.seed(11)
        mask = numpy.random.random(len(strs)) > .6
        strsa = strs[mask]
        mask = numpy.random.random(len(strs)) > .7
        strsb = strs[mask]
        ci_strs = (strsa, strsb)
        ci_coeff = selected_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs)
        ci0 = selected_ci.to_fci(ci_coeff, norb, (nelec,nelec))
        dm1ref, dm2ref = direct_spin1.make_rdm12s(ci0, norb, (nelec,nelec))
        dm1 = selected_ci.make_rdm1s(ci_coeff, norb, (nelec,nelec))
        self.assertAlmostEqual(abs(dm1[0]-dm1ref[0]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm1[1]-dm1ref[1]).sum(), 0, 9)
        dm2 = selected_ci.make_rdm2s(ci_coeff, norb, (nelec,nelec))
        self.assertAlmostEqual(abs(dm2[0]-dm2ref[0]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm2[1]-dm2ref[1]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm2[2]-dm2ref[2]).sum(), 0, 9)

        ci1_coeff = selected_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs)
        ci1 = selected_ci.to_fci(ci1_coeff, norb, (nelec,nelec))
        dm1ref, dm2ref = direct_spin1.trans_rdm12s(ci1, ci0, norb, (nelec,nelec))
        dm1 = selected_ci.trans_rdm1s(ci1_coeff, ci_coeff, norb, (nelec,nelec))
        self.assertAlmostEqual(abs(dm1[0]-dm1ref[0]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm1[1]-dm1ref[1]).sum(), 0, 9)
예제 #8
0
 def test_contract_2e_1(self):
     myci = selected_ci.SCI()
     nelec = (4,3)
     strsa = cistring.make_strings(range(norb), nelec[0])
     strsb = cistring.make_strings(range(norb), nelec[1])
     ci0 = selected_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), (strsa,strsb))
     h2 = ao2mo.restore(1, eri, norb)
     c1 = myci.contract_2e(h2, ci0, norb, nelec)
     c2 = direct_spin1.contract_2e(h2, ci0, norb, nelec)
     self.assertAlmostEqual(float(abs(c1-c2).sum()), 0, 9)
     dm1_1 = myci.make_rdm1(c1, norb, nelec)
     dm1_2 = direct_spin1.make_rdm1(c2, norb, nelec)
     self.assertAlmostEqual(abs(dm1_1 - dm1_2).sum(), 0, 9)
     dm2_1 = myci.make_rdm12(c1, norb, nelec)[1]
     dm2_2 = direct_spin1.make_rdm12(c2, norb, nelec)[1]
     self.assertAlmostEqual(abs(dm2_1 - dm2_2).sum(), 0, 9)
예제 #9
0
    def test_spin0_contract_2e_symm(self):
        norb, nelec = 7, (4, 4)
        strs = cistring.make_strings(range(norb), nelec[0])
        numpy.random.seed(11)
        mask = numpy.random.random(len(strs)) > .3
        strsa = strs[mask]
        ci_strs = (strsa, strsa)
        na = len(strsa)
        ci_coeff = numpy.random.random((na, na))
        ci_coeff = ci_coeff + ci_coeff.T
        civec_strs = selected_ci._as_SCIvector(ci_coeff, ci_strs)
        orbsym = (numpy.random.random(norb) * 4).astype(int)
        nn = norb * (norb + 1) // 2
        eri = ao2mo.restore(1,
                            (numpy.random.random(nn * (nn + 1) // 2) - .2)**3,
                            norb)
        oosym = orbsym[:, None] ^ orbsym
        oosym = oosym.reshape(-1, 1) ^ oosym.ravel()
        eri[oosym.reshape([norb] * 4) != 0] = 0

        ci0 = fci.selected_ci.to_fci(civec_strs, norb, nelec)
        ci0 = fci.addons.symmetrize_wfn(ci0, norb, nelec, orbsym)
        civec_strs = fci.selected_ci.from_fci(ci0, civec_strs._strs, norb,
                                              nelec)

        myci = selected_ci_spin0_symm.SCI()
        e1 = numpy.dot(
            civec_strs.ravel(),
            myci.contract_2e(eri, civec_strs, norb, nelec,
                             orbsym=orbsym).ravel())
        e2 = numpy.dot(
            ci0.ravel(),
            direct_spin1_symm.contract_2e(eri, ci0, norb, nelec,
                                          orbsym=orbsym).ravel())
        self.assertAlmostEqual(e1, e2, 9)
예제 #10
0
    def test_guess_wfnsym(self):
        norb, nelec = 7, (4, 4)
        strs = cistring.make_strings(range(norb), nelec[0])
        numpy.random.seed(11)
        mask = numpy.random.random(len(strs)) > .3
        strsa = strs[mask]
        mask = numpy.random.random(len(strs)) > .2
        strsb = strs[mask]
        ci_strs = (strsa, strsb)
        ci0 = selected_ci._as_SCIvector(
            numpy.random.random((len(strsa), len(strsb))), ci_strs)
        fake_mol = gto.M()
        fake_mol.groupname = 'C2v'
        cis = selected_ci_symm.SelectedCI(fake_mol)
        cis.orbsym = orbsym = (numpy.random.random(norb) * 4).astype(int)

        self.assertEqual(cis.guess_wfnsym(norb, nelec), 0)
        self.assertEqual(cis.guess_wfnsym(norb, nelec, ci0), 3)
        self.assertEqual(cis.guess_wfnsym(norb, nelec, ci0, wfnsym=0), 0)
        self.assertEqual(cis.guess_wfnsym(norb, nelec, ci0, wfnsym='B2'), 3)
        ci0[:] = 0
        self.assertRaises(RuntimeError,
                          cis.guess_wfnsym,
                          norb,
                          nelec,
                          ci0,
                          wfnsym=1)
예제 #11
0
    def test_rdm_2e(self):
        norb, nelec = 10, 1
        strs = cistring.make_strings(range(norb), nelec)
        numpy.random.seed(11)
        mask = numpy.random.random(len(strs)) > .6
        strsa = strs[mask]
        mask = numpy.random.random(len(strs)) > .7
        strsb = strs[mask]
        ci_strs = (strsa, strsb)
        ci_coeff = selected_ci._as_SCIvector(
            numpy.random.random((len(strsa), len(strsb))), ci_strs)
        ci0 = selected_ci.to_fci(ci_coeff, norb, (nelec, nelec))
        dm1ref, dm2ref = direct_spin1.make_rdm12s(ci0, norb, (nelec, nelec))
        dm1 = selected_ci.make_rdm1s(ci_coeff, norb, (nelec, nelec))
        self.assertAlmostEqual(abs(dm1[0] - dm1ref[0]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm1[1] - dm1ref[1]).sum(), 0, 9)
        dm2 = selected_ci.make_rdm2s(ci_coeff, norb, (nelec, nelec))
        self.assertAlmostEqual(abs(dm2[0] - dm2ref[0]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm2[1] - dm2ref[1]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm2[2] - dm2ref[2]).sum(), 0, 9)

        ci1_coeff = selected_ci._as_SCIvector(
            numpy.random.random((len(strsa), len(strsb))), ci_strs)
        ci1 = selected_ci.to_fci(ci1_coeff, norb, (nelec, nelec))
        dm1ref, dm2ref = direct_spin1.trans_rdm12s(ci1, ci0, norb,
                                                   (nelec, nelec))
        dm1 = selected_ci.trans_rdm1s(ci1_coeff, ci_coeff, norb,
                                      (nelec, nelec))
        self.assertAlmostEqual(abs(dm1[0] - dm1ref[0]).sum(), 0, 9)
        self.assertAlmostEqual(abs(dm1[1] - dm1ref[1]).sum(), 0, 9)
예제 #12
0
 def test_des_linkstr1(self):
     norb, nelec = 10, 4
     strs = cistring.make_strings(range(norb), nelec)
     numpy.random.seed(11)
     mask = numpy.random.random(len(strs)) > .6
     strs = strs[mask]
     c_index0 = gen_cre_linkstr(strs, norb, nelec)
     c_index1 = selected_ci.gen_cre_linkstr(strs, norb, nelec)
     c_index1[:, :, 1] = 0
     self.assertTrue(numpy.all(c_index0 == c_index1))
예제 #13
0
 def test_des_linkstr(self):
     norb, nelec = 10, 4
     strs = cistring.make_strings(range(norb), nelec)
     numpy.random.seed(11)
     mask = numpy.random.random(len(strs)) > .6
     strs = strs[mask]
     c_index0 = gen_cre_linkstr(strs, norb, nelec)
     c_index1 = selected_ci.gen_cre_linkstr(strs, norb, nelec)
     c_index1[:,:,1] = 0
     self.assertTrue(numpy.all(c_index0 == c_index1))
예제 #14
0
def guess_wfnsym(ci, norb, nelec, orbsym):
    '''Guess the wavefunction symmetry based on the non-zero elements in the
    given CI coefficients.

    Args:
        ci : 2D array
            CI coefficients, row for alpha strings and column for beta strings.
        norb : int
            Number of orbitals.
        nelec : int or 2-item list
            Number of electrons, or 2-item list for (alpha, beta) electrons
        orbsym : list of int
            The irrep ID for each orbital.

    Returns:
        Irrep ID
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    return _guess_wfnsym(ci, strsa, strsb, orbsym)
예제 #15
0
파일: addons.py 프로젝트: sunqm/pyscf
def guess_wfnsym(ci, norb, nelec, orbsym):
    '''Guess the wavefunction symmetry based on the non-zero elements in the
    given CI coefficients.

    Args:
        ci : 2D array
            CI coefficients, row for alpha strings and column for beta strings.
        norb : int
            Number of orbitals.
        nelec : int or 2-item list
            Number of electrons, or 2-item list for (alpha, beta) electrons
        orbsym : list of int
            The irrep ID for each orbital.

    Returns:
        Irrep ID
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    return _guess_wfnsym(ci, strsa, strsb, orbsym)
예제 #16
0
 def test_des_des_linkstr(self):
     norb, nelec = 10, 4
     strs = cistring.make_strings(range(norb), nelec)
     numpy.random.seed(11)
     mask = numpy.random.random(len(strs)) > .4
     strs = strs[mask]
     dd_index0 = des_des_linkstr(strs, norb, nelec)
     dd_index1 = selected_ci.des_des_linkstr(strs, norb, nelec)
     self.assertTrue(numpy.all(dd_index0 == dd_index1))
     dd_index0 = des_des_linkstr_tril(strs, norb, nelec)
     dd_index1 = selected_ci.des_des_linkstr_tril(strs, norb, nelec)
     dd_index1[:,:,1] = 0
     self.assertTrue(numpy.all(dd_index0 == dd_index1))
예제 #17
0
 def test_des_des_linkstr(self):
     norb, nelec = 10, 4
     strs = cistring.make_strings(range(norb), nelec)
     numpy.random.seed(11)
     mask = numpy.random.random(len(strs)) > .4
     strs = strs[mask]
     dd_index0 = des_des_linkstr(strs, norb, nelec)
     dd_index1 = selected_ci.des_des_linkstr(strs, norb, nelec)
     self.assertTrue(numpy.all(dd_index0 == dd_index1))
     dd_index0 = des_des_linkstr_tril(strs, norb, nelec)
     dd_index1 = selected_ci.des_des_linkstr_tril(strs, norb, nelec)
     dd_index1[:, :, 1] = 0
     self.assertTrue(numpy.all(dd_index0 == dd_index1))
예제 #18
0
 def test_spin_square(self):
     norb, nelec = 10, 4
     strs = cistring.make_strings(range(norb), nelec)
     numpy.random.seed(11)
     mask = numpy.random.random(len(strs)) > .6
     strsa = strs[mask]
     mask = numpy.random.random(len(strs)) > .7
     strsb = strs[mask]
     ci_strs = (strsa, strsb)
     ci_coeff = selected_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs)
     ci0 = selected_ci.to_fci(ci_coeff, norb, (nelec,nelec))
     ss0 = selected_ci.spin_square(ci_coeff, norb, (nelec,nelec))
     ss1 = spin_op.spin_square0(ci0, norb, (nelec,nelec))
     self.assertAlmostEqual(ss0[0], ss1[0], 9)
예제 #19
0
 def test_select_strs(self):
     myci = selected_ci.SCI()
     myci.select_cutoff = 1e-3
     norb, nelec = 10, 4
     strs = cistring.make_strings(range(norb), nelec)
     numpy.random.seed(11)
     mask = numpy.random.random(len(strs)) > .8
     strs = strs[mask]
     nn = norb*(norb+1)//2
     eri = (numpy.random.random(nn*(nn+1)//2)-.2)**3
     eri[eri<.1] *= 3e-3
     eri = ao2mo.restore(1, eri, norb)
     eri_pq_max = abs(eri.reshape(norb**2,-1)).max(axis=1).reshape(norb,norb)
     civec_max = numpy.random.random(len(strs))
     strs_add0 = select_strs(myci, eri, eri_pq_max, civec_max, strs, norb, nelec)
     strs_add1 = selected_ci.select_strs(myci, eri, eri_pq_max, civec_max,
                                         strs, norb, nelec)
     self.assertTrue(numpy.all(strs_add0 == strs_add1))
예제 #20
0
def transform_ci(ci, nelec, u):
    '''Transform CI coefficients to the representation in new one-particle basis.
    Solving CI problem for Hamiltonian h1, h2 defined in old basis,
    CI_old = fci.kernel(h1, h2, ...)
    Given orbital rotation u, the CI problem can be either solved by
    transforming the Hamiltonian, or transforming the coefficients.
    CI_new = fci.kernel(u^T*h1*u, ...) = transform_ci_for_orbital_rotation(CI_old, u)

    Args:
        u : 2D array or a list of 2D array
            the orbital rotation to transform the old one-particle basis to new
            one-particle basis. If u is not a squared matrix, the resultant CI
            coefficients array may have different shape to the input CI
            coefficients.
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    if isinstance(u, numpy.ndarray) and u.ndim == 2:
        ua = ub = u
        assert ua.shape == ub.shape
    else:
        ua, ub = u
    norb_old, norb_new = ua.shape
    na_old = cistring.num_strings(norb_old, neleca)
    nb_old = cistring.num_strings(norb_old, nelecb)
    na_new = cistring.num_strings(norb_new, neleca)
    nb_new = cistring.num_strings(norb_new, nelecb)
    ci = ci.reshape(na_old, nb_old)

    one_particle_strs_old = numpy.asarray([1 << i for i in range(norb_old)])
    one_particle_strs_new = numpy.asarray([1 << i for i in range(norb_new)])

    if neleca == 0:
        trans_ci_a = numpy.ones((1, 1))
    else:
        trans_ci_a = numpy.zeros((na_old, na_new))
        strs_old = numpy.asarray(cistring.make_strings(range(norb_old),
                                                       neleca))

        # Unitary transformation array trans_ci is the overlap between two sets of CI basis.
        occ_masks_old = (strs_old[:, None] & one_particle_strs_old) != 0
        if norb_old == norb_new:
            occ_masks_new = occ_masks_old
        else:
            strs_new = numpy.asarray(
                cistring.make_strings(range(norb_new), neleca))
            occ_masks_new = (strs_new[:, None] & one_particle_strs_new) != 0

        # Perform
        #for i in range(na_old): # old basis
        #    for j in range(na_new): # new basis
        #        uij = u[occ_masks_old[i]][:,occ_masks_new[j]]
        #        trans_ci_a[i,j] = numpy.linalg.det(uij)
        occ_idx_all_strs = numpy.where(occ_masks_new)[1].reshape(
            na_new, neleca)
        for i in range(na_old):
            ui = ua[occ_masks_old[i]].T.copy()
            minors = ui[occ_idx_all_strs]
            trans_ci_a[i, :] = numpy.linalg.det(minors)

    if neleca == nelecb and numpy.allclose(ua, ub):
        trans_ci_b = trans_ci_a
    elif nelecb == 0:
        trans_ci_b = numpy.ones((1, 1))
    else:
        trans_ci_b = numpy.zeros((nb_old, nb_new))
        strs_old = numpy.asarray(cistring.make_strings(range(norb_old),
                                                       nelecb))

        occ_masks_old = (strs_old[:, None] & one_particle_strs_old) != 0
        if norb_old == norb_new:
            occ_masks_new = occ_masks_old
        else:
            strs_new = numpy.asarray(
                cistring.make_strings(range(norb_new), nelecb))
            occ_masks_new = (strs_new[:, None] & one_particle_strs_new) != 0

        occ_idx_all_strs = numpy.where(occ_masks_new)[1].reshape(
            nb_new, nelecb)
        for i in range(nb_old):
            ui = ub[occ_masks_old[i]].T.copy()
            minors = ui[occ_idx_all_strs]
            trans_ci_b[i, :] = numpy.linalg.det(minors)

    # Transform old basis to new basis for all alpha-electron excitations
    ci = lib.dot(trans_ci_a.T, ci)
    # Transform old basis to new basis for all beta-electron excitations
    ci = lib.dot(ci, trans_ci_b)
    return ci
예제 #21
0
파일: addons.py 프로젝트: MSwenne/BEP
def transform_ci_for_orbital_rotation(ci, norb, nelec, u):
    '''Transform CI coefficients to the representation in new one-particle basis.
    Solving CI problem for Hamiltonian h1, h2 defined in old basis,
    CI_old = fci.kernel(h1, h2, ...)
    Given orbital rotation u, the CI problem can be either solved by
    transforming the Hamiltonian, or transforming the coefficients.
    CI_new = fci.kernel(u^T*h1*u, ...) = transform_ci_for_orbital_rotation(CI_old, u)

    Args:
        u : 2D array or a list of 2D array
            the orbital rotation to transform the old one-particle basis to new
            one-particle basis
    '''
    neleca, nelecb = _unpack(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    one_particle_strs = numpy.asarray([1 << i for i in range(norb)])
    na = len(strsa)
    nb = len(strsb)

    if isinstance(u, numpy.ndarray) and u.ndim == 2:
        ua = ub = u
    else:
        ua, ub = u

    if neleca == 0:
        trans_ci_a = numpy.ones((1, 1))
    else:
        # Unitary transformation array trans_ci is the overlap between two sets of CI basis.
        occ_masks = (strsa[:, None] & one_particle_strs) != 0
        trans_ci_a = numpy.zeros((na, na))
        #for i in range(na): # for old basis
        #    for j in range(na):
        #        uij = u[occ_masks[i]][:,occ_masks[j]]
        #        trans_ci_a[i,j] = numpy.linalg.det(uij)
        occ_idx_all_strs = numpy.where(occ_masks)[1].reshape(na, neleca)
        for i in range(na):
            ui = ua[occ_masks[i]].T.copy()
            minors = ui[occ_idx_all_strs]
            trans_ci_a[i, :] = numpy.linalg.det(minors)

    if neleca == nelecb and numpy.allclose(ua, ub):
        trans_ci_b = trans_ci_a
    else:
        if nelecb == 0:
            trans_ci_b = numpy.ones((1, 1))
        else:
            occ_masks = (strsb[:, None] & one_particle_strs) != 0
            trans_ci_b = numpy.zeros((nb, nb))
            #for i in range(nb):
            #    for j in range(nb):
            #        uij = u[occ_masks[i]][:,occ_masks[j]]
            #        trans_ci_b[i,j] = numpy.linalg.det(uij)
            occ_idx_all_strs = numpy.where(occ_masks)[1].reshape(nb, nelecb)
            for i in range(nb):
                ui = ub[occ_masks[i]].T.copy()
                minors = ui[occ_idx_all_strs]
                trans_ci_b[i, :] = numpy.linalg.det(minors)

    # Transform old basis to new basis for all alpha-electron excitations
    ci = lib.dot(trans_ci_a.T, ci.reshape(na, nb))
    # Transform old basis to new basis for all beta-electron excitations
    ci = lib.dot(ci.reshape(na, nb), trans_ci_b)
    return ci
예제 #22
0
파일: addons.py 프로젝트: sunqm/pyscf
def transform_ci_for_orbital_rotation(ci, norb, nelec, u):
    '''Transform CI coefficients to the representation in new one-particle basis.
    Solving CI problem for Hamiltonian h1, h2 defined in old basis,
    CI_old = fci.kernel(h1, h2, ...)
    Given orbital rotation u, the CI problem can be either solved by
    transforming the Hamiltonian, or transforming the coefficients.
    CI_new = fci.kernel(u^T*h1*u, ...) = transform_ci_for_orbital_rotation(CI_old, u)

    Args:
        u : 2D array or a list of 2D array
            the orbital rotation to transform the old one-particle basis to new
            one-particle basis
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    strsa = numpy.asarray(cistring.make_strings(range(norb), neleca))
    strsb = numpy.asarray(cistring.make_strings(range(norb), nelecb))
    one_particle_strs = numpy.asarray([1<<i for i in range(norb)])
    na = len(strsa)
    nb = len(strsb)
    assert(ci.shape == (na, nb))

    if isinstance(u, numpy.ndarray) and u.ndim == 2:
        ua = ub = u
    else:
        ua, ub = u

    if neleca == 0:
        trans_ci_a = numpy.ones((1,1))
    else:
        # Unitary transformation array trans_ci is the overlap between two sets of CI basis.
        occ_masks = (strsa[:,None] & one_particle_strs) != 0
        trans_ci_a = numpy.zeros((na,na))
        #for i in range(na): # for old basis
        #    for j in range(na):
        #        uij = u[occ_masks[i]][:,occ_masks[j]]
        #        trans_ci_a[i,j] = numpy.linalg.det(uij)
        occ_idx_all_strs = numpy.where(occ_masks)[1].reshape(na,neleca)
        for i in range(na):
            ui = ua[occ_masks[i]].T.copy()
            minors = ui[occ_idx_all_strs]
            trans_ci_a[i,:] = numpy.linalg.det(minors)

    if neleca == nelecb and numpy.allclose(ua, ub):
        trans_ci_b = trans_ci_a
    else:
        if nelecb == 0:
            trans_ci_b = numpy.ones((1,1))
        else:
            occ_masks = (strsb[:,None] & one_particle_strs) != 0
            trans_ci_b = numpy.zeros((nb,nb))
            #for i in range(nb):
            #    for j in range(nb):
            #        uij = u[occ_masks[i]][:,occ_masks[j]]
            #        trans_ci_b[i,j] = numpy.linalg.det(uij)
            occ_idx_all_strs = numpy.where(occ_masks)[1].reshape(nb,nelecb)
            for i in range(nb):
                ui = ub[occ_masks[i]].T.copy()
                minors = ui[occ_idx_all_strs]
                trans_ci_b[i,:] = numpy.linalg.det(minors)

    # Transform old basis to new basis for all alpha-electron excitations
    ci = lib.dot(trans_ci_a.T, ci.reshape(na,nb))
    # Transform old basis to new basis for all beta-electron excitations
    ci = lib.dot(ci.reshape(na,nb), trans_ci_b)
    return ci