Beispiel #1
0
    def test_sub_addrs(self):
        addrs = cistring.sub_addrs(6, 3, (0, 2, 3, 5))
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b1101', '0b100101', '0b101001', '0b101100'])

        addrs = cistring.sub_addrs(6, 3, (3, 0, 5, 2))
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b101001', '0b1101', '0b101100', '0b100101'])

        addrs = cistring.sub_addrs(6, 3, (3, 0, 5, 2), 2)
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)], [
            '0b111', '0b1011', '0b1110', '0b10101', '0b11001', '0b11100',
            '0b100011', '0b100110', '0b101010', '0b110001', '0b110100',
            '0b111000'
        ])

        addrs = cistring.sub_addrs(6, 3, (0, 2, 3, 5), 2)
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)], [
            '0b111', '0b1011', '0b1110', '0b10101', '0b11001', '0b11100',
            '0b100011', '0b100110', '0b101010', '0b110001', '0b110100',
            '0b111000'
        ])

        addrs = cistring.sub_addrs(6, 3, (0, 2, 3, 5), 1)
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b10011', '0b10110', '0b11010', '0b110010'])
Beispiel #2
0
def pspace(h1e, eri, norb, nelec, hdiag=None, np=400):
    '''pspace Hamiltonian to improve Davidson preconditioner. See, CPL, 169, 463
    '''
    if norb > 63:
        raise NotImplementedError('norb > 63')

    neleca, nelecb = _unpack_nelec(nelec)
    h1e = numpy.ascontiguousarray(h1e)
    eri = ao2mo.restore(1, eri, norb)
    nb = cistring.num_strings(norb, nelecb)
    if hdiag is None:
        hdiag = make_hdiag(h1e, eri, norb, nelec)
    if hdiag.size < np:
        addr = numpy.arange(hdiag.size)
    else:
        try:
            addr = numpy.argpartition(hdiag, np-1)[:np]
        except AttributeError:
            addr = numpy.argsort(hdiag)[:np]
    addra, addrb = divmod(addr, nb)
    stra = cistring.addrs2str(norb, neleca, addra)
    strb = cistring.addrs2str(norb, nelecb, addrb)
    np = len(addr)
    h0 = numpy.zeros((np,np))
    libfci.FCIpspace_h0tril(h0.ctypes.data_as(ctypes.c_void_p),
                            h1e.ctypes.data_as(ctypes.c_void_p),
                            eri.ctypes.data_as(ctypes.c_void_p),
                            stra.ctypes.data_as(ctypes.c_void_p),
                            strb.ctypes.data_as(ctypes.c_void_p),
                            ctypes.c_int(norb), ctypes.c_int(np))

    for i in range(np):
        h0[i,i] = hdiag[addr[i]]
    h0 = lib.hermi_triu(h0)
    return addr, h0
Beispiel #3
0
def ddaddrs2csdaddrs(norb, neleca, nelecb, ddaddrs):
    ''' Convert double-determinant (DD) CI vector element addresses, [deta, detb], into
        configuration-spin-determinant (CSD) vector element addresses, [npair, dconf, sconf, spinstate],
        to facilitate a later transformation into CSFs. In the CSD format,
            max (0, neleca + nelecb - norb) <= npair <= nelecb is the number of electron pairs 

            dconf is the address for a particular configuration of npair pairs'
            use cistring for npair 'electrons' in norb orbitals

            sconf is the address for a particular configuration of the neleca + nelecb - 2*npair (= nunp)
            unpaired electrons given dconf; use cistring for nunp electrons in norb - npair orbitals

            spinstate is the state of (nunp + neleca - nelecb)/2 alpha and (nunp - neleca + nelecb)/2 beta spins;
            use cistring for (nunp + neleca - nelecb)/2 'electrons' in nunp 'orbitals'

        Args:
        norb, neleca, nelecb are integers
        ddaddrs is an array that specifies double determinant CI vector element address
            If 1d, interpreted as deta_addr*ndetb + detb_addr
            If 2d, interpreted as row/column i is interpreted as the ith index pair [deta, detb], if there are 2 columns/rows

        Returns:
        csdaddrs, list of integers for the CI vector in the form of a 1d array

    '''

    ddaddrs = format_ddaddrs(norb, neleca, nelecb, ddaddrs)
    ddstrs = np.asarray([
        cistring.addrs2str(norb, neleca, ddaddrs[0]),
        cistring.addrs2str(norb, nelecb, ddaddrs[1])
    ],
                        dtype=np.int64)
    csdstrs = ddstrs2csdstrs(norb, neleca, nelecb, ddstrs)
    csdaddrs = csdstrs2csdaddrs(norb, neleca, nelecb, csdstrs)
    return csdaddrs
Beispiel #4
0
def make_hdiag_csf (h1e, eri, norb, nelec, transformer, hdiag_det=None):
    smult = transformer.smult
    if hdiag_det is None:
        hdiag_det = make_hdiag_det (None, h1e, eri, norb, nelec)
    eri = ao2mo.restore(1, eri, norb)
    tlib = wlib = 0
    neleca, nelecb = _unpack_nelec (nelec)
    min_npair, npair_csd_offset, npair_dconf_size, npair_sconf_size, npair_sdet_size = get_csdaddrs_shape (norb, neleca, nelecb)
    _, npair_csf_offset, _, _, npair_csf_size = get_csfvec_shape (norb, neleca, nelecb, smult)
    npair_econf_size = npair_dconf_size * npair_sconf_size
    max_npair = min (neleca, nelecb)
    ncsf_all = count_all_csfs (norb, neleca, nelecb, smult)
    ndeta_all = cistring.num_strings(norb, neleca)
    ndetb_all = cistring.num_strings(norb, nelecb)
    ndet_all = ndeta_all * ndetb_all
    hdiag_csf = np.ascontiguousarray (np.zeros (ncsf_all, dtype=np.float64))
    hdiag_csf_check = np.ones (ncsf_all, dtype=np.bool)
    for npair in range (min_npair, max_npair+1):
        ipair = npair - min_npair
        nconf = npair_econf_size[ipair]
        ndet = npair_sdet_size[ipair]
        ncsf = npair_csf_size[ipair]
        if ncsf == 0:
            continue
        nspin = neleca + nelecb - 2*npair
        csd_offset = npair_csd_offset[ipair]
        csf_offset = npair_csf_offset[ipair]
        hdiag_conf = np.ascontiguousarray (np.zeros ((nconf, ndet, ndet), dtype=np.float64))
        det_addr = transformer.csd_mask[csd_offset:][:nconf*ndet]
        if ndet == 1:
            # Closed-shell singlets
            assert (ncsf == 1)
            hdiag_csf[csf_offset:][:nconf] = hdiag_det[det_addr.flat]
            hdiag_csf_check[csf_offset:][:nconf] = False
            continue
        det_addra, det_addrb = divmod (det_addr, ndetb_all)
        det_stra = np.ascontiguousarray (cistring.addrs2str (norb, neleca, det_addra).reshape (nconf, ndet, order='C'))
        det_strb = np.ascontiguousarray (cistring.addrs2str (norb, nelecb, det_addrb).reshape (nconf, ndet, order='C'))
        det_addr = det_addr.reshape (nconf, ndet, order='C')
        hdiag_conf = np.ascontiguousarray (np.zeros ((nconf, ndet, ndet), dtype=np.float64))
        hdiag_conf_det = np.ascontiguousarray (hdiag_det[det_addr], dtype=np.float64)
        t1 = time.process_time ()
        w1 = time.time ()
        libcsf.FCICSFhdiag (hdiag_conf.ctypes.data_as (ctypes.c_void_p),
                            hdiag_conf_det.ctypes.data_as (ctypes.c_void_p),
                            eri.ctypes.data_as (ctypes.c_void_p),
                            det_stra.ctypes.data_as (ctypes.c_void_p),
                            det_strb.ctypes.data_as (ctypes.c_void_p),
                            ctypes.c_uint (norb), ctypes.c_uint (nconf), ctypes.c_uint (ndet))
        tlib += time.process_time () - t1
        wlib += time.time () - w1
        umat = get_spin_evecs (nspin, neleca, nelecb, smult)
        hdiag_conf = np.tensordot (hdiag_conf, umat, axes=1)
        hdiag_conf *= umat[np.newaxis,:,:]
        hdiag_csf[csf_offset:][:nconf*ncsf] = hdiag_conf.sum (1).ravel (order='C')
        hdiag_csf_check[csf_offset:][:nconf*ncsf] = False
    assert (np.count_nonzero (hdiag_csf_check) == 0), np.count_nonzero (hdiag_csf_check)
    #print ("Time in hdiag_csf library: {}, {}".format (tlib, wlib))
    return hdiag_csf
Beispiel #5
0
def pspace(h1e, eri, norb, nelec, hdiag=None, np=400):
    '''pspace Hamiltonian to improve Davidson preconditioner. See, CPL, 169, 463
    '''
    if norb > 63:
        raise NotImplementedError('norb > 63')

    if h1e.dtype == numpy.complex or eri.dtype == numpy.complex:
        raise NotImplementedError('Complex Hamiltonian')

    neleca, nelecb = _unpack_nelec(nelec)
    h1e = numpy.ascontiguousarray(h1e)
    eri = ao2mo.restore(1, eri, norb)
    nb = cistring.num_strings(norb, nelecb)
    if hdiag is None:
        hdiag = make_hdiag(h1e, eri, norb, nelec)
    if hdiag.size < np:
        addr = numpy.arange(hdiag.size)
    else:
        try:
            addr = numpy.argpartition(hdiag, np - 1)[:np].copy()
        except AttributeError:
            addr = numpy.argsort(hdiag)[:np].copy()
    addra, addrb = divmod(addr, nb)
    stra = cistring.addrs2str(norb, neleca, addra)
    strb = cistring.addrs2str(norb, nelecb, addrb)
    np = len(addr)
    h0 = numpy.zeros((np, np))
    libfci.FCIpspace_h0tril(h0.ctypes.data_as(ctypes.c_void_p),
                            h1e.ctypes.data_as(ctypes.c_void_p),
                            eri.ctypes.data_as(ctypes.c_void_p),
                            stra.ctypes.data_as(ctypes.c_void_p),
                            strb.ctypes.data_as(ctypes.c_void_p),
                            ctypes.c_int(norb), ctypes.c_int(np))

    HERMITIAN_THRESHOLD = 1e-10
    if (abs(h1e - h1e.T).max() < HERMITIAN_THRESHOLD and
            abs(eri - eri.transpose(1, 0, 3, 2)).max() < HERMITIAN_THRESHOLD):
        # symmetric Hamiltonian
        h0 = lib.hermi_triu(h0)
    else:
        # Fill the upper triangular part
        h0 = numpy.asarray(h0, order='F')
        h1e = numpy.asarray(h1e.T, order='C')
        eri = numpy.asarray(eri.transpose(1, 0, 3, 2), order='C')
        libfci.FCIpspace_h0tril(h0.ctypes.data_as(ctypes.c_void_p),
                                h1e.ctypes.data_as(ctypes.c_void_p),
                                eri.ctypes.data_as(ctypes.c_void_p),
                                stra.ctypes.data_as(ctypes.c_void_p),
                                strb.ctypes.data_as(ctypes.c_void_p),
                                ctypes.c_int(norb), ctypes.c_int(np))

    idx = numpy.arange(np)
    h0[idx, idx] = hdiag[addr]
    return addr, h0
Beispiel #6
0
def fock2hilbert(ci, norb, nelec):
    assert (norb <= MAX_NORB)
    nelec = _unpack_nelec(nelec)
    ci = np.asarray(ci).reshape(-1, 2**norb, 2**norb)
    nroots = ci.shape[0]
    ndeta = cistring.num_strings(norb, nelec[0])
    ndetb = cistring.num_strings(norb, nelec[1])
    ci1 = np.empty((nroots, ndeta, ndetb), dtype=ci.dtype)
    strsa = cistring.addrs2str(norb, nelec[0], list(range(ndeta)))
    strsb = cistring.addrs2str(norb, nelec[1], list(range(ndetb)))
    ci1[:, :, :] = ci[:, strsa[:, None], strsb]
    return ci1
Beispiel #7
0
def csfaddrs2str (norb, neleca, nelecb, smult, addrs):
    npair, domo_addrs, somo_addrs, spincpl_addrs = unpack_csfaddrs (norb, neleca, nelecb, smult, addrs)
    domo_str = np.zeros (len (addrs), dtype=np.int64)
    somo_str = np.zeros (len (addrs), dtype=np.int64)
    spincpl_str = np.zeros (len (addrs), dtype=np.int64)
    for uniq_npair in np.unique (npair):
        idx_uniq = (npair == uniq_npair)
        notdomo = norb - uniq_npair
        nspin = neleca + nelecb - 2*uniq_npair
        domo_str[idx_uniq] = cistring.addrs2str (norb, uniq_npair, domo_addrs[idx_uniq]) if uniq_npair > 0 else -1
        somo_str[idx_uniq] = cistring.addrs2str (notdomo, nspin, somo_addrs[idx_uniq])
        spincpl_str[idx_uniq] = addrs2str (nspin, smult, spincpl_addrs[idx_uniq])
    return domo_str, somo_str, spincpl_str
Beispiel #8
0
def pspace(h1e, eri, norb, nelec, hdiag=None, np=400):
    '''pspace Hamiltonian to improve Davidson preconditioner. See, CPL, 169, 463
    '''
    if norb > 63:
        raise NotImplementedError('norb > 63')

    neleca, nelecb = _unpack_nelec(nelec)
    h1e = numpy.ascontiguousarray(h1e)
    eri = ao2mo.restore(1, eri, norb)
    nb = cistring.num_strings(norb, nelecb)
    if hdiag is None:
        hdiag = make_hdiag(h1e, eri, norb, nelec)
    if hdiag.size < np:
        addr = numpy.arange(hdiag.size)
    else:
        try:
            addr = numpy.argpartition(hdiag, np-1)[:np]
        except AttributeError:
            addr = numpy.argsort(hdiag)[:np]
    addra, addrb = divmod(addr, nb)
    stra = cistring.addrs2str(norb, neleca, addra)
    strb = cistring.addrs2str(norb, nelecb, addrb)
    np = len(addr)
    h0 = numpy.zeros((np,np))
    libfci.FCIpspace_h0tril(h0.ctypes.data_as(ctypes.c_void_p),
                            h1e.ctypes.data_as(ctypes.c_void_p),
                            eri.ctypes.data_as(ctypes.c_void_p),
                            stra.ctypes.data_as(ctypes.c_void_p),
                            strb.ctypes.data_as(ctypes.c_void_p),
                            ctypes.c_int(norb), ctypes.c_int(np))

    HERMITIAN_THRESHOLD = 1e-10
    if (abs(h1e - h1e.T).max() < HERMITIAN_THRESHOLD and
        abs(eri - eri.transpose(1,0,3,2)).max() < HERMITIAN_THRESHOLD):
        # symmetric Hamiltonian
        h0 = lib.hermi_triu(h0)
    else:
        # Fill the upper triangular part
        h0 = numpy.asarray(h0, order='F')
        h1e = numpy.asarray(h1e.T, order='C')
        eri = numpy.asarray(eri.transpose(1,0,3,2), order='C')
        libfci.FCIpspace_h0tril(h0.ctypes.data_as(ctypes.c_void_p),
                                h1e.ctypes.data_as(ctypes.c_void_p),
                                eri.ctypes.data_as(ctypes.c_void_p),
                                stra.ctypes.data_as(ctypes.c_void_p),
                                strb.ctypes.data_as(ctypes.c_void_p),
                                ctypes.c_int(norb), ctypes.c_int(np))

    idx = numpy.arange(np)
    h0[idx,idx] = hdiag[addr]
    return addr, h0
Beispiel #9
0
def pretty_ddaddrs (norb, neleca, nelecb, ddaddrs):
    ''' Printable string for dd strings based on their addresses '''
    ddaddrs = format_ddaddrs (norb, neleca, nelecb, ddaddrs)
    ddstrs = np.asarray ([cistring.addrs2str (norb, neleca, ddaddrs[0]), cistring.addrs2str (norb, nelecb, ddaddrs[1])], dtype=np.int64)
    output = []
    for i in range (len (ddstrs[0])):
        dstra = bin (ddstrs[0,i])[2:]
        dstrb = bin (ddstrs[1,i])[2:]
        while len (dstra) < norb:
            dstra = '0' + dstra
        while len (dstrb) < norb:
            dstrb = '0' + dstrb
        out = dstra + ' ' + dstrb
        output.append (out)
    return output
Beispiel #10
0
def large_ci(ci, norb, nelec, tol=.1, return_strs=True):
    '''Search for the largest CI coefficients
    '''
    neleca, nelecb = _unpack(nelec)
    addra, addrb = numpy.where(abs(ci) > tol)
    strsa = cistring.addrs2str(norb, neleca, addra)
    strsb = cistring.addrs2str(norb, nelecb, addrb)
    if return_strs:
        strsa = [bin(x) for x in strsa]
        strsb = [bin(x) for x in strsb]
        return list(zip(ci[addra, addrb], strsa, strsb))
    else:
        occslsta = cistring._strs2occslst(strsa, norb)
        occslstb = cistring._strs2occslst(strsb, norb)
        return list(zip(ci[addra, addrb], occslsta, occslstb))
Beispiel #11
0
def test_spin_evecs (nspin, neleca, nelecb, smult, S2mat=None):
    s = (smult - 1) / 2
    ms = (neleca - nelecb) / 2
    assert (ms <= s)
    assert (smult-1 <= nspin)
    assert (nspin >= neleca + nelecb)

    na = (nspin + neleca - nelecb) // 2
    ndet = special.comb (nspin, na, exact=True)
    ncsf = count_csfs (nspin, smult)

    spinstrs = cistring.addrs2str (nspin, na, list (range (ndet)))

    if S2mat is None:
        S2mat = np.zeros ((ndet, ndet), dtype=np.float_)
        twoS = smult - 1
        twoMS = int (round (2 * ms))

        t_start = time.time ()    
        libcsf.FCICSFmakeS2mat (S2mat.ctypes.data_as (ctypes.c_void_p),
                             spinstrs.ctypes.data_as (ctypes.c_void_p),
                             ctypes.c_int (ndet),
                             ctypes.c_int (nspin),
                             ctypes.c_int (twoS),
                             ctypes.c_int (twoMS))
        print ("TIME: {} seconds to make S2mat for {} spins with s={}, ms={}".format (
            time.time() - t_start, nspin, (smult-1)/2, ms))
        print ("MEMORY: {} MB for {}-spin S2 matrix with s={}, ms={}".format (S2mat.nbytes / 1e6,
            nspin, (smult-1)/2, ms))

    umat = get_spin_evecs (nspin, neleca, nelecb, smult)
    print ("MEMORY: {} MB for {}-spin csfs with s={}, ms={}".format (umat.nbytes / 1e6,
        nspin, (smult-1)/2, ms))
    assert (umat.shape == tuple((ndet, ncsf))), "umat shape should be ({},{}); is {}".format (ndet, ncsf, umat.shape)
    
    s = (smult-1)/2
    t_start = time.time ()
    isorth = np.allclose (np.dot (umat.T, umat), np.eye (umat.shape[1]))
    ortherr = linalg.norm (np.dot (umat.T, umat) - np.eye (umat.shape[1]))
    S2mat_csf = reduce (np.dot, (umat.T, S2mat, umat))
    S2mat_csf_comp = s * (s+1) * np.eye (umat.shape[1])
    S2mat_csf_err = linalg.norm (S2mat_csf - S2mat_csf_comp)
    diagsS2 = np.allclose (S2mat_csf, S2mat_csf_comp)
    passed = isorth and diagsS2
    print ("TIME: {} seconds to analyze umat for {} spins with s={}, ms={}".format (
        time.time() - t_start, nspin, s, ms))
    

    print (('For a system of {} spins with total spin {} and spin projection {}'
            ', {} CSFs found from {} determinants by Clebsch-Gordan algorithm').format (
            nspin, s, ms, umat.shape[1], len (spinstrs)))
    print ('Did the Clebsch-Gordan algorithm give orthonormal eigenvectors? {}'.format (
        ('NO (err = {})'.format (ortherr), 'Yes')[isorth]))
    print ('Did the Clebsch-Gordan algorithm diagonalize the S2 matrix with the correct eigenvalues? {}'.format (
        ('NO (err = {})'.format (S2mat_csf_err), 'Yes')[diagsS2]))
    print ('nspin = {}, S = {}, MS = {}: {}'.format (nspin, s, ms, ('FAILED','Passed')[passed]))
    sys.stdout.flush ()

    return umat, S2mat
Beispiel #12
0
def large_ci(ci, norb, nelec, tol=.1, return_strs=True):
    '''Search for the largest CI coefficients
    '''
    neleca, nelecb = _unpack(nelec)
    addra, addrb = numpy.where(abs(ci) > tol)
    if addra.size == 0:  # No large CI coefficient > tol
        addra, addrb = numpy.unravel_index(numpy.argmax(abs(ci)), ci.shape)
        addra = numpy.asarray([addra])
        addrb = numpy.asarray([addrb])
    strsa = cistring.addrs2str(norb, neleca, addra)
    strsb = cistring.addrs2str(norb, nelecb, addrb)
    if return_strs:
        strsa = [bin(x) for x in strsa]
        strsb = [bin(x) for x in strsb]
        return list(zip(ci[addra, addrb], strsa, strsb))
    else:
        occslsta = cistring._strs2occslst(strsa, norb)
        occslstb = cistring._strs2occslst(strsb, norb)
        return list(zip(ci[addra, addrb], occslsta, occslstb))
Beispiel #13
0
    def test_str2addr(self):
        self.assertEqual(cistring.str2addr(6, 3, int('0b11001' ,2)), 7)
        self.assertEqual(cistring.str2addr(6, 3, int('0b11010' ,2)), 8)
        self.assertEqual(cistring.str2addr(7, 4, int('0b110011',2)), 9)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 7)), 7)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 8)), 8)
        self.assertEqual(cistring.str2addr(7, 4, cistring.addr2str(7, 4, 9)), 9)

        self.assertTrue(all(numpy.arange(20) ==
                            cistring.strs2addr(6, 3, cistring.addrs2str(6, 3, range(20)))))
Beispiel #14
0
def large_ci(ci, norb, nelec, tol=LARGE_CI_TOL, return_strs=RETURN_STRS):
    '''Search for the largest CI coefficients
    '''
    neleca, nelecb = _unpack(nelec)
    addra, addrb = numpy.where(abs(ci) > tol)
    if addra.size == 0:
        # No large CI coefficient > tol, search for the largest coefficient
        addra, addrb = numpy.unravel_index(numpy.argmax(abs(ci)), ci.shape)
        addra = numpy.asarray([addra])
        addrb = numpy.asarray([addrb])
    strsa = cistring.addrs2str(norb, neleca, addra)
    strsb = cistring.addrs2str(norb, nelecb, addrb)
    if return_strs:
        strsa = [bin(x) for x in strsa]
        strsb = [bin(x) for x in strsb]
        return list(zip(ci[addra,addrb], strsa, strsb))
    else:
        occslsta = cistring._strs2occslst(strsa, norb)
        occslstb = cistring._strs2occslst(strsb, norb)
        return list(zip(ci[addra,addrb], occslsta, occslstb))
Beispiel #15
0
    def test_sub_addrs(self):
        addrs = cistring.sub_addrs(6, 3, (0,2,3,5))
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b1101', '0b100101', '0b101001', '0b101100'])

        addrs = cistring.sub_addrs(6, 3, (3,0,5,2))
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b101001', '0b1101', '0b101100', '0b100101'])

        addrs = cistring.sub_addrs(6, 3, (3,0,5,2), 2)
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b111', '0b1011', '0b1110', '0b10101', '0b11001', '0b11100',
                          '0b100011', '0b100110', '0b101010', '0b110001', '0b110100', '0b111000'])

        addrs = cistring.sub_addrs(6, 3, (0,2,3,5), 2)
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b111', '0b1011', '0b1110', '0b10101', '0b11001', '0b11100',
                          '0b100011', '0b100110', '0b101010', '0b110001', '0b110100', '0b111000'])

        addrs = cistring.sub_addrs(6, 3, (0,2,3,5), 1)
        self.assertEqual([bin(x) for x in cistring.addrs2str(6, 3, addrs)],
                         ['0b10011', '0b10110', '0b11010', '0b110010'])
Beispiel #16
0
def pspace(h1e, eri, norb, nelec, hdiag=None, np=400):
    neleca, nelecb = direct_spin1._unpack_nelec(nelec)
    h1e_a = numpy.ascontiguousarray(h1e[0])
    h1e_b = numpy.ascontiguousarray(h1e[1])
    g2e_aa = ao2mo.restore(1, eri[0], norb)
    g2e_ab = ao2mo.restore(1, eri[1], norb)
    g2e_bb = ao2mo.restore(1, eri[2], norb)
    link_indexa = cistring.gen_linkstr_index_trilidx(range(norb), neleca)
    link_indexb = cistring.gen_linkstr_index_trilidx(range(norb), nelecb)
    nb = link_indexb.shape[0]
    if hdiag is None:
        hdiag = make_hdiag(h1e, eri, norb, nelec)
    if hdiag.size < np:
        addr = numpy.arange(hdiag.size)
    else:
        try:
            addr = numpy.argpartition(hdiag, np - 1)[:np]
        except AttributeError:
            addr = numpy.argsort(hdiag)[:np]
    addra = addr // nb
    addrb = addr % nb
    stra = cistring.addrs2str(norb, neleca, addra)
    strb = cistring.addrs2str(norb, nelecb, addrb)
    np = len(addr)
    h0 = numpy.zeros((np, np))
    libfci.FCIpspace_h0tril_uhf(h0.ctypes.data_as(ctypes.c_void_p),
                                h1e_a.ctypes.data_as(ctypes.c_void_p),
                                h1e_b.ctypes.data_as(ctypes.c_void_p),
                                g2e_aa.ctypes.data_as(ctypes.c_void_p),
                                g2e_ab.ctypes.data_as(ctypes.c_void_p),
                                g2e_bb.ctypes.data_as(ctypes.c_void_p),
                                stra.ctypes.data_as(ctypes.c_void_p),
                                strb.ctypes.data_as(ctypes.c_void_p),
                                ctypes.c_int(norb), ctypes.c_int(np))

    for i in range(np):
        h0[i, i] = hdiag[addr[i]]
    h0 = lib.hermi_triu(h0)
    return addr, h0
Beispiel #17
0
def large_ci(ci, norb, nelec, tol=LARGE_CI_TOL, return_strs=RETURN_STRS):
    '''Search for the largest CI coefficients
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    na = cistring.num_strings(norb, neleca)
    nb = cistring.num_strings(norb, nelecb)
    assert (ci.shape == (na, nb))
    addra, addrb = numpy.where(abs(ci) > tol)
    if addra.size == 0:
        # No large CI coefficient > tol, search for the largest coefficient
        addra, addrb = numpy.unravel_index(numpy.argmax(abs(ci)), ci.shape)
        addra = numpy.asarray([addra])
        addrb = numpy.asarray([addrb])
    strsa = cistring.addrs2str(norb, neleca, addra)
    strsb = cistring.addrs2str(norb, nelecb, addrb)
    if return_strs:
        strsa = [bin(x) for x in strsa]
        strsb = [bin(x) for x in strsb]
        return list(zip(ci[addra, addrb], strsa, strsb))
    else:
        occslsta = cistring._strs2occslst(strsa, norb)
        occslstb = cistring._strs2occslst(strsb, norb)
        return list(zip(ci[addra, addrb], occslsta, occslstb))
Beispiel #18
0
    def test_str2addr(self):
        self.assertEqual(cistring.str2addr(6, 3, int('0b11001', 2)), 7)
        self.assertEqual(cistring.str2addr(6, 3, int('0b11010', 2)), 8)
        self.assertEqual(cistring.str2addr(7, 4, int('0b110011', 2)), 9)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 7)),
                         7)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 8)),
                         8)
        self.assertEqual(cistring.str2addr(7, 4, cistring.addr2str(7, 4, 9)),
                         9)

        self.assertTrue(
            all(
                numpy.arange(20) == cistring.strs2addr(
                    6, 3, cistring.addrs2str(6, 3, range(20)))))
Beispiel #19
0
def get_scstrs (nspin, smult):
    ''' This is not a great way to do this, but I seriously can't think of any straightforward way to put the coupling strings in order... '''
    if (smult >= nspin):
        return np.ones ((0), dtype=np.int64)
    elif (nspin == 0):
        return np.zeros ((1), dtype=np.int64)
    assert (int (round (smult + nspin)) % 2 == 1), "npsin = {}; 2S+1 = {}".format (nspin, smult)
    nup = (nspin + smult - 1) // 2
    ndet = int (special.comb (nspin, nup))
    scstrs = cistring.addrs2str (nspin, nup, list (range (ndet)))
    mask = np.ones (len (scstrs), dtype=np.bool_)

    libcsf.FCICSFgetscstrs (scstrs.ctypes.data_as (ctypes.c_void_p),
                            mask.ctypes.data_as (ctypes.c_void_p),
                            ctypes.c_int (len (scstrs)),
                            ctypes.c_int (nspin))

    return np.ascontiguousarray (scstrs[mask], dtype=np.int64)
Beispiel #20
0
def get_spin_evecs(nspin, neleca, nelecb, smult):
    ms = (neleca - nelecb) / 2
    s = (smult - 1) / 2
    assert (neleca >= nelecb)
    assert (neleca - nelecb <= smult - 1)
    assert (neleca - nelecb <= nspin)
    assert ((neleca - nelecb) % 2 == (smult - 1) % 2)
    assert ((neleca - nelecb) % 2 == nspin % 2)

    na = (nspin + neleca - nelecb) // 2
    ndet = special.comb(nspin, na, exact=True)
    ncsf = count_csfs(nspin, smult)

    t_start = time.time()
    spinstrs = cistring.addrs2str(nspin, na, list(range(ndet)))
    assert (len(spinstrs) == ndet
            ), "should have {} spin strings; have {} (nspin={}, ms={}".format(
                ndet, len(spinstrs), nspin, ms)

    t_start = time.time()
    scstrs = addrs2str(nspin, smult, list(range(ncsf)))
    assert (
        len(scstrs) == ncsf
    ), "should have {} coupling strings; have {} (nspin={}, s={})".format(
        ncsf, len(scstrs), nspin, s)

    umat = np.ones((ndet, ncsf), dtype=np.float_)
    twoS = smult - 1
    twoMS = neleca - nelecb

    t_start = time.time()
    libcsf.FCICSFmakecsf(umat.ctypes.data_as(ctypes.c_void_p),
                         spinstrs.ctypes.data_as(ctypes.c_void_p),
                         scstrs.ctypes.data_as(ctypes.c_void_p),
                         ctypes.c_int(nspin), ctypes.c_int(ndet),
                         ctypes.c_int(ncsf), ctypes.c_int(twoS),
                         ctypes.c_int(twoMS))

    return umat
Beispiel #21
0
def make_hdiag_csf_slower (h1e, eri, norb, nelec, transformer, hdiag_det=None):
    ''' This is tricky because I need the diagonal blocks for each configuration in order to get
    the correct csf hdiag values, not just the diagonal elements for each determinant. '''
    smult = transformer.smult
    t0, w0 = time.process_time (), time.time ()
    tstr = tlib = tloop = wstr = wlib = wloop = 0
    if hdiag_det is None:
        hdiag_det = make_hdiag_det (None, h1e, eri, norb, nelec)
    eri = ao2mo.restore(1, eri, norb)
    neleca, nelecb = _unpack_nelec (nelec)
    min_npair, npair_csd_offset, npair_dconf_size, npair_sconf_size, npair_sdet_size = get_csdaddrs_shape (norb, neleca, nelecb)
    _, npair_csf_offset, _, _, npair_csf_size = get_csfvec_shape (norb, neleca, nelecb, smult)
    npair_econf_size = npair_dconf_size * npair_sconf_size
    max_npair = min (neleca, nelecb)
    ncsf_all = count_all_csfs (norb, neleca, nelecb, smult)
    ndeta_all = cistring.num_strings(norb, neleca)
    ndetb_all = cistring.num_strings(norb, nelecb)
    ndet_all = ndeta_all * ndetb_all
    hdiag_csf = np.ascontiguousarray (np.zeros (ncsf_all, dtype=np.float64))
    hdiag_csf_check = np.ones (ncsf_all, dtype=np.bool)
    for npair in range (min_npair, max_npair+1):
        ipair = npair - min_npair
        nconf = npair_econf_size[ipair]
        ndet = npair_sdet_size[ipair]
        ncsf = npair_csf_size[ipair]
        if ncsf == 0:
            continue
        nspin = neleca + nelecb - 2*npair
        csd_offset = npair_csd_offset[ipair]
        csf_offset = npair_csf_offset[ipair]
        hdiag_conf = np.ascontiguousarray (np.zeros ((nconf, ndet, ndet), dtype=np.float64))
        det_addr = transformer.csd_mask[csd_offset:][:nconf*ndet]
        if ndet == 1:
            # Closed-shell singlets
            assert (ncsf == 1)
            hdiag_csf[csf_offset:][:nconf] = hdiag_det[det_addr.flat]
            hdiag_csf_check[csf_offset:][:nconf] = False
            continue
        umat = get_spin_evecs (nspin, neleca, nelecb, smult)
        det_addra, det_addrb = divmod (det_addr, ndetb_all)
        t1, w1 = time.process_time (), time.time ()
        det_stra = cistring.addrs2str (norb, neleca, det_addra).reshape (nconf, ndet, order='C')
        det_strb = cistring.addrs2str (norb, nelecb, det_addrb).reshape (nconf, ndet, order='C')
        tstr += time.process_time () - t1
        wstr += time.time () - w1
        det_addr = det_addr.reshape (nconf, ndet, order='C')
        diag_idx = np.diag_indices (ndet)
        triu_idx = np.triu_indices (ndet)   
        ipair_check = 0
        # It looks like the library call below is, itself, usually responsible for about 50% of the
        # clock and wall time that this function consumes.
        t1, w1 = time.process_time (), time.time ()
        for iconf in range (nconf):
            addr = det_addr[iconf]
            assert (len (addr) == ndet)
            stra = det_stra[iconf]
            strb = det_strb[iconf]
            t2, w2 = time.process_time (), time.time ()
            libfci.FCIpspace_h0tril(hdiag_conf[iconf].ctypes.data_as(ctypes.c_void_p),
                h1e.ctypes.data_as(ctypes.c_void_p),
                eri.ctypes.data_as(ctypes.c_void_p),
                stra.ctypes.data_as(ctypes.c_void_p),
                strb.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(norb), ctypes.c_int(ndet))
            tlib += time.process_time () - t2
            wlib += time.time () - w2
            #hdiag_conf[iconf][diag_idx] = hdiag_det[addr]
            #hdiag_conf[iconf] = lib.hermi_triu(hdiag_conf[iconf])
        for iconf in range (nconf): hdiag_conf[iconf] = lib.hermi_triu (hdiag_conf[iconf])
        for iconf in range (nconf): hdiag_conf[iconf][diag_idx] = hdiag_det[det_addr[iconf]]
        tloop += time.process_time () - t1
        wloop += time.time () - w1

        hdiag_conf = np.tensordot (hdiag_conf, umat, axes=1)
        hdiag_conf = (hdiag_conf * umat[np.newaxis,:,:]).sum (1)
        hdiag_csf[csf_offset:][:nconf*ncsf] = hdiag_conf.ravel (order='C')
        hdiag_csf_check[csf_offset:][:nconf*ncsf] = False
    assert (np.count_nonzero (hdiag_csf_check) == 0), np.count_nonzero (hdiag_csf_check)
    #print ("Total time in hdiag_csf: {}, {}".format (time.process_time () - t0, time.time () - w0))
    #print ("    Loop: {}, {}".format (tloop, wloop))
    #print ("    Library: {}, {}".format (tlib, wlib))
    #print ("    Cistring: {}, {}".format (tstr, wstr))
    return hdiag_csf
Beispiel #22
0
                dtype=np.bool_)  # Boolean index array for CI vector
ref = np.array([0])  # HF determinant is usually addr = 0
addr[ref[0], ref[0]] = True
sing_addrs = []
for links, nelec, sp in zip(linkstr, mc.nelecas, ('up', 'down')):
    redun = ref
    sing = np.setdiff1d(links[ref, :, 2],
                        redun)  # E_pq|ref> = |single> (unique only)
    redun = np.append(ref, sing)
    doub = np.setdiff1d(links[sing, :, 2],
                        redun)  # E_pq|single> = |double> (unique only)
    print(
        "Reference, single excitation, and double excitation addresses for {}-spin electrons:"
        .format(sp), ref, sing, doub)
    print("Reference string for {}-spin:".format(sp),
          bin(cistring.addrs2str(mc.ncas, nelec, ref)[0]))
    print("Single-excitation strings for {}-spin:".format(sp),
          [bin(x) for x in cistring.addrs2str(mc.ncas, nelec, sing)])
    print("Double-excitation strings for {}-spin:".format(sp),
          [bin(x) for x in cistring.addrs2str(mc.ncas, nelec, doub)])
    if sp == 'up':  # Same-spin single and double excitations
        addr[sing, 0] = True
        addr[doub, 0] = True
    elif sp == 'down':
        addr[0, sing] = True
        addr[0, doub] = True
    sing_addrs.append(sing)
addr[np.ix_(
    *sing_addrs)] = True  # Combine the two spin singles to get ab-> doubles
cisd = mc.ci[addr]
print("Norm of ref+singles+doubles part of FCI vector:", linalg.norm(cisd))
Beispiel #23
0
def pspace (fci, h1e, eri, norb, nelec, transformer, hdiag_det=None, hdiag_csf=None, npsp=200):
    ''' Note that getting pspace for npsp CSFs is substantially more costly than getting it for npsp determinants,
    until I write code than can evaluate Hamiltonian matrix elements of CSFs directly. On the other hand
    a pspace of determinants contains many redundant degrees of freedom for the same reason. Therefore I have
    reduced the default pspace size by a factor of 2.'''
    if norb > 63:
        raise NotImplementedError('norb > 63')

    t0 = (time.process_time (), time.time ())
    neleca, nelecb = _unpack_nelec(nelec)
    h1e = np.ascontiguousarray(h1e)
    eri = ao2mo.restore(1, eri, norb)
    nb = cistring.num_strings(norb, nelecb)
    if hdiag_det is None:
        hdiag_det = fci.make_hdiag(h1e, eri, norb, nelec)
    if hdiag_csf is None:
        hdiag_csf = fci.make_hdiag_csf(h1e, eri, norb, nelec, hdiag_det=hdiag_det)
    csf_addr = np.arange (hdiag_csf.size, dtype=np.int)
    if transformer.wfnsym is None:
        ncsf_sym = hdiag_csf.size
    else:
        idx_sym = transformer.confsym[transformer.econf_csf_mask] == transformer.wfnsym
        ncsf_sym = np.count_nonzero (idx_sym)
        csf_addr = csf_addr[idx_sym]
    if ncsf_sym > npsp:
        try:
            csf_addr = csf_addr[np.argpartition(hdiag_csf[csf_addr], npsp-1)[:npsp]]
        except AttributeError:
            csf_addr = csf_addr[np.argsort(hdiag_csf[csf_addr])[:npsp]]

    # To build 
    econf_addr = np.unique (transformer.econf_csf_mask[csf_addr])
    det_addr = np.concatenate ([np.nonzero (transformer.econf_det_mask == conf)[0]
        for conf in econf_addr])
    lib.logger.debug (fci, ("csf.pspace: Lowest-energy %s CSFs correspond to %s configurations"
        " which are spanned by %s determinants"), npsp, econf_addr.size, det_addr.size)

    addra, addrb = divmod(det_addr, nb)
    stra = cistring.addrs2str(norb, neleca, addra)
    strb = cistring.addrs2str(norb, nelecb, addrb)
    npsp_det = len(det_addr)
    h0 = np.zeros((npsp_det,npsp_det))
    h1e_ab = unpack_h1e_ab (h1e)
    h1e_a = np.ascontiguousarray(h1e_ab[0])
    h1e_b = np.ascontiguousarray(h1e_ab[1])
    g2e = ao2mo.restore(1, eri, norb)
    g2e_ab = g2e_bb = g2e_aa = g2e
    _debug_g2e (fci, g2e, eri, norb) # Exploring g2e nan bug; remove later?
    t0 = lib.logger.timer (fci, "csf.pspace: index manipulation", *t0)
    libfci.FCIpspace_h0tril_uhf(h0.ctypes.data_as(ctypes.c_void_p),
                                h1e_a.ctypes.data_as(ctypes.c_void_p),
                                h1e_b.ctypes.data_as(ctypes.c_void_p),
                                g2e_aa.ctypes.data_as(ctypes.c_void_p),
                                g2e_ab.ctypes.data_as(ctypes.c_void_p),
                                g2e_bb.ctypes.data_as(ctypes.c_void_p),
                                stra.ctypes.data_as(ctypes.c_void_p),
                                strb.ctypes.data_as(ctypes.c_void_p),
                                ctypes.c_int(norb), ctypes.c_int(npsp_det))
    t0 = lib.logger.timer (fci, "csf.pspace: pspace Hamiltonian in determinant basis", *t0)

    for i in range(npsp_det):
        h0[i,i] = hdiag_det[det_addr[i]]
    h0 = lib.hermi_triu(h0)

    try:
        if fci.verbose >= lib.logger.DEBUG: evals_before = scipy.linalg.eigh (h0)[0]
    except ValueError as e:
        lib.logger.debug (fci, ("ERROR: h0 has {} infs, {} nans; h1e_a has {} infs, {} nans; "
            "h1e_b has {} infs, {} nans; g2e has {} infs, {} nans, norb = {}, npsp_det = {}").format (
            np.count_nonzero (np.isinf (h0)), np.count_nonzero (np.isnan (h0)),
            np.count_nonzero (np.isinf (h1e_a)), np.count_nonzero (np.isnan (h1e_a)),
            np.count_nonzero (np.isinf (h1e_b)), np.count_nonzero (np.isnan (h1e_b)),
            np.count_nonzero (np.isinf (g2e)), np.count_nonzero (np.isnan (g2e)),
            norb, npsp_det))
        evals_before = np.zeros (npsp_det)

    h0, csf_addr = transformer.mat_det2csf_confspace (h0, econf_addr)
    t0 = lib.logger.timer (fci, "csf.pspace: transform pspace Hamiltonian into CSF basis", *t0)

    if fci.verbose >= lib.logger.DEBUG:
        lib.logger.debug2 (fci, "csf.pspace: eigenvalues of h0 before transformation %s", evals_before)
        evals_after = scipy.linalg.eigh (h0)[0]
        lib.logger.debug2 (fci, "csf.pspace: eigenvalues of h0 after transformation %s", evals_after)
        idx = [np.argmin (np.abs (evals_before - ev)) for ev in evals_after]
        resid = evals_after - evals_before[idx]
        lib.logger.debug2 (fci, "csf.pspace: best h0 eigenvalue matching differences after transformation: %s", resid)
        lib.logger.debug (fci, "csf.pspace: if the transformation of h0 worked the following number will be zero: %s", np.max (np.abs(resid)))

    # We got extra CSFs from building the configurations most of the time.
    if csf_addr.size > npsp:
        try:
            csf_addr_2 = np.argpartition(np.diag (h0), npsp-1)[:npsp]
        except AttributeError:
            csf_addr_2 = np.argsort(np.diag (h0))[:npsp]
        csf_addr = csf_addr[csf_addr_2]
        h0 = h0[np.ix_(csf_addr_2,csf_addr_2)]
    npsp_csf = csf_addr.size
    lib.logger.debug (fci, "csf_solver.pspace: asked for %s-CSF pspace; found %s CSFs", npsp, npsp_csf)

    t0 = lib.logger.timer (fci, "csf.pspace wrapup", *t0)
    return csf_addr, h0
Beispiel #24
0
def csdaddrs2csdstrs(norb, neleca, nelecb, csdaddrs):
    ''' This is extremely slow because of the amount of repetition in dconf_addr, sconf_addr, and spins_addr! '''
    t_start = time.time()
    min_npair, npair_offset, npair_dconf_size, npair_sconf_size, npair_spins_size = get_csdaddrs_shape(
        norb, neleca, nelecb)
    csdstrs = np.empty((4, len(csdaddrs)), dtype=np.int64)
    for npair, offset, dconf_size, sconf_size, spins_size in zip(
            range(min_npair,
                  min(neleca, nelecb) + 1), npair_offset, npair_dconf_size,
            npair_sconf_size, npair_spins_size):
        nspins = neleca + nelecb - 2 * npair
        nup = (nspins + neleca - nelecb) // 2
        assert ((nspins + neleca - nelecb) % 2 == 0)
        next_offset = offset + (dconf_size * sconf_size * spins_size)

        idx = (csdaddrs >= offset) & (csdaddrs < next_offset)
        if len(idx) == 1:
            if not idx[0]:
                continue
            else:
                idx = 0
        try:
            dconf_addr = (csdaddrs[idx] - offset) // (sconf_size * spins_size)
        except:
            print(idx)
            assert (False)
        dconf_rem = (csdaddrs[idx] - offset) % (sconf_size * spins_size)
        sconf_addr = dconf_rem // spins_size
        spins_addr = dconf_rem % spins_size
        csdstrs[0, idx] = npair

        t_ref = time.time()
        dconf_addr_uniq, dconf_addr_uniq2full = np.unique(dconf_addr,
                                                          return_inverse=True)
        try:
            csdstrs[1, idx] = cistring.addrs2str(
                norb, npair, dconf_addr_uniq)[dconf_addr_uniq2full]
        except TypeError:
            csdstrs[1, idx] = cistring.addr2str(norb, npair, dconf_addr_uniq)

        sconf_addr_uniq, sconf_addr_uniq2full = np.unique(sconf_addr,
                                                          return_inverse=True)
        try:
            csdstrs[2, idx] = cistring.addrs2str(
                norb - npair, nspins, sconf_addr_uniq)[sconf_addr_uniq2full]
        except TypeError:
            csdstrs[2, idx] = cistring.addr2str(norb - npair, nspins,
                                                sconf_addr_uniq)

        spins_addr_uniq, spins_addr_uniq2full = np.unique(spins_addr,
                                                          return_inverse=True)
        try:
            csdstrs[3, idx] = cistring.addrs2str(
                nspins, nup, spins_addr_uniq)[spins_addr_uniq2full]
        except TypeError:
            csdstrs[3, idx] = cistring.addr2str(nspins, nup, spins_addr_uniq)
        #print ("{:.2f} seconds in cistring".format (time.time () - t_ref))
        '''
        t_ref = time.time ()
        try:
            csdstrs[1,idx] = cistring.addrs2str (norb, npair, dconf_addr)
            csdstrs[2,idx] = cistring.addrs2str (norb - npair, nspins, sconf_addr)
            csdstrs[3,idx] = cistring.addrs2str (nspins, nup, spins_addr)
        except TypeError:
            csdstrs[1,idx] = cistring.addr2str (norb, npair, dconf_addr)
            csdstrs[2,idx] = cistring.addr2str (norb - npair, nspins, sconf_addr)
            csdstrs[3,idx] = cistring.addr2str (nspins, nup, spins_addr)
        print ("{:.2f} seconds in cistring".format (time.time () - t_ref))
        '''

    #print ("{:.2f} seconds spent in csdaddrs2csdstrs".format (time.time () - t_start))
    return csdstrs