def make_hdiag(h1e, eri, norb, nelec): 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) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = len(strsa) nb = len(strsb) hdiag = numpy.empty(na * nb) jdiag_aa = numpy.asarray(numpy.einsum('iijj->ij', g2e_aa), order='C') jdiag_ab = numpy.asarray(numpy.einsum('iijj->ij', g2e_ab), order='C') jdiag_bb = numpy.asarray(numpy.einsum('iijj->ij', g2e_bb), order='C') kdiag_aa = numpy.asarray(numpy.einsum('ijji->ij', g2e_aa), order='C') kdiag_bb = numpy.asarray(numpy.einsum('ijji->ij', g2e_bb), order='C') libfci.FCImake_hdiag_uhf(hdiag.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), jdiag_aa.ctypes.data_as(ctypes.c_void_p), jdiag_ab.ctypes.data_as(ctypes.c_void_p), jdiag_bb.ctypes.data_as(ctypes.c_void_p), kdiag_aa.ctypes.data_as(ctypes.c_void_p), kdiag_bb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(neleca), ctypes.c_int(nelecb), strsa.ctypes.data_as(ctypes.c_void_p), strsb.ctypes.data_as(ctypes.c_void_p)) return numpy.asarray(hdiag)
def tn_addrs_signs(norb, nelec, n_excite): '''Compute the FCI strings (address) for CIS n-excitation amplitudes and the signs of the coefficients when transferring the reference from physics vacuum to HF vacuum. ''' if n_excite > nelec: print("Warning: Not enough occupied orbitals to excite.") return [0], [0] nocc = nelec hole_strs = cistring.gen_strings4orblist(range(nocc), nocc - n_excite) # For HF vacuum, hole operators are ordered from low-lying to high-lying # orbitals. It leads to the opposite string ordering. hole_strs = hole_strs[::-1] hole_sum = numpy.zeros(len(hole_strs), dtype=int) for i in range(nocc): hole_at_i = (hole_strs & (1 << i)) == 0 hole_sum[hole_at_i] += i # The hole operators are listed from low-lying to high-lying orbitals # (from left to right). For i-th (0-based) hole operator, the number of # orbitals which are higher than i determines the sign. This number # equals to nocc-(i+1). After removing the highest hole operator, nocc # becomes nocc-1, the sign for next hole operator j will be associated to # nocc-1-(j+1). By iteratively calling this procedure, the overall sign # for annihilating three holes is (-1)**(3*nocc - 6 - sum i) sign = (-1)**(n_excite * nocc - n_excite * (n_excite + 1) // 2 - hole_sum) particle_strs = cistring.gen_strings4orblist(range(nocc, norb), n_excite) strs = hole_strs[:, None] ^ particle_strs addrs = cistring.strs2addr(norb, nocc, strs.ravel()) signs = numpy.vstack([sign] * len(particle_strs)).T.ravel() return addrs, signs
def make_hdiag(h1e, eri, norb, nelec): '''Diagonal Hamiltonian for Davidson preconditioner ''' neleca, nelecb = _unpack_nelec(nelec) h1e = numpy.asarray(h1e, order='C') eri = ao2mo.restore(1, eri, norb) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = len(strsa) nb = len(strsb) hdiag = numpy.empty(na * nb) jdiag = numpy.asarray(numpy.einsum('iijj->ij', eri), order='C') kdiag = numpy.asarray(numpy.einsum('ijji->ij', eri), order='C') c_h1e = h1e.ctypes.data_as(ctypes.c_void_p) c_jdiag = jdiag.ctypes.data_as(ctypes.c_void_p) c_kdiag = kdiag.ctypes.data_as(ctypes.c_void_p) libfci.FCImake_hdiag_uhf(hdiag.ctypes.data_as(ctypes.c_void_p), c_h1e, c_h1e, c_jdiag, c_jdiag, c_jdiag, c_kdiag, c_kdiag, ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(neleca), ctypes.c_int(nelecb), strsa.ctypes.data_as(ctypes.c_void_p), strsb.ctypes.data_as(ctypes.c_void_p)) return hdiag
def contract_2e_hubbard(u, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec u_aa, u_ab, u_bb = u strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) fcivec = fcivec.reshape(na, nb) fcinew = numpy.zeros_like(fcivec) if u_aa != 0: # u * n_alpha^+ n_alpha for i in range(norb): maska = (strsa & (1 << i)) > 0 fcinew[maska] += u_aa * fcivec[maska] if u_ab != 0: # u * (n_alpha^+ n_beta + n_beta^+ n_alpha) for i in range(norb): maska = (strsa & (1 << i)) > 0 maskb = (strsb & (1 << i)) > 0 fcinew[maska[:, None] & maskb] += 2 * u_ab * fcivec[maska[:, None] & maskb] if u_bb != 0: # u * n_beta^+ n_beta for i in range(norb): maskb = (strsb & (1 << i)) > 0 fcinew[:, maskb] += u_bb * fcivec[:, maskb] return fcinew
def make_hdiag(h1e, eri, norb, nelec): 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) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = len(strsa) nb = len(strsb) hdiag = numpy.empty(na*nb) jdiag_aa = numpy.asarray(numpy.einsum('iijj->ij',g2e_aa), order='C') jdiag_ab = numpy.asarray(numpy.einsum('iijj->ij',g2e_ab), order='C') jdiag_bb = numpy.asarray(numpy.einsum('iijj->ij',g2e_bb), order='C') kdiag_aa = numpy.asarray(numpy.einsum('ijji->ij',g2e_aa), order='C') kdiag_bb = numpy.asarray(numpy.einsum('ijji->ij',g2e_bb), order='C') libfci.FCImake_hdiag_uhf(hdiag.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), jdiag_aa.ctypes.data_as(ctypes.c_void_p), jdiag_ab.ctypes.data_as(ctypes.c_void_p), jdiag_bb.ctypes.data_as(ctypes.c_void_p), kdiag_aa.ctypes.data_as(ctypes.c_void_p), kdiag_bb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(neleca), ctypes.c_int(nelecb), strsa.ctypes.data_as(ctypes.c_void_p), strsb.ctypes.data_as(ctypes.c_void_p)) return numpy.asarray(hdiag)
def to_fci_wfn_gs(fout, civec, norb, nelec, root=0, ncore=0): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = cistring.gen_strings4orblist(range(norb), neleca) stradic = dict(zip(strsa,range(strsa.__len__()))) strsb = cistring.gen_strings4orblist(range(norb), nelecb) strbdic = dict(zip(strsb,range(strsb.__len__()))) na = len(stradic) nb = len(strbdic) ndet = len(civec[root]) from pyscf import fci stringsa = fci.cistring.gen_strings4orblist(range(norb), neleca) stringsb = fci.cistring.gen_strings4orblist(range(norb), nelecb) fout.write('NELACTIVE, NDETS, NORBCORE, NORBACTIVE\n') fout.write(' %5d %5d %5d %5d\n' % (neleca+nelecb, ndet, ncore, norb)) fout.write('COEFFICIENT/ OCCUPIED ACTIVE SPIN ORBITALS\n') def str2orbidx(string): bstring = bin(string) return [i+1 for i,s in enumerate(bstring[::-1]) if s == '1'] n = 0 for idet, (stra, strb) in enumerate(civec[root]._strs.reshape(ndet,2,-1)): ka = stradic[stra[0]] kb = strbdic[strb[0]] idxa = ['%3d' % x for x in str2orbidx(stringsa[ka])] idxb = ['%3d' % (-x) for x in str2orbidx(stringsb[kb])] if (abs(civec[root][idet]) >= 1e-6): n = n + 1 fout.write('%18.10E %s %s\n' % (civec[root][idet], ' '.join(idxa), ' '.join(idxb))) fout.write('The purged number of dets is : %d\n' % n)
def get_init_guess(norb, nelec, nroots, hdiag, orbsym, wfnsym=0): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) airreps = numpy.zeros(strsa.size, dtype=numpy.int32) birreps = numpy.zeros(strsb.size, dtype=numpy.int32) for i in range(norb): airreps[numpy.bitwise_and(strsa, 1<<i) > 0] ^= orbsym[i] birreps[numpy.bitwise_and(strsb, 1<<i) > 0] ^= orbsym[i] na = len(strsa) nb = len(strsb) ci0 = [] iroot = 0 for addr in numpy.argsort(hdiag): x = numpy.zeros((na*nb)) addra = addr // nb addrb = addr % nb if airreps[addra] ^ birreps[addrb] == wfnsym: x[addr] = 1 ci0.append(x) iroot += 1 if iroot >= nroots: break # Add noise ci0[0][0 ] += 1e-5 ci0[0][-1] -= 1e-5 return ci0
def make_hdiag(h1e, eri, norb, nelec): '''Diagonal Hamiltonian for Davidson preconditioner ''' neleca, nelecb = _unpack_nelec(nelec) h1e = numpy.asarray(h1e, order='C') eri = ao2mo.restore(1, eri, norb) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = len(strsa) nb = len(strsb) hdiag = numpy.empty(na*nb) jdiag = numpy.asarray(numpy.einsum('iijj->ij',eri), order='C') kdiag = numpy.asarray(numpy.einsum('ijji->ij',eri), order='C') c_h1e = h1e.ctypes.data_as(ctypes.c_void_p) c_jdiag = jdiag.ctypes.data_as(ctypes.c_void_p) c_kdiag = kdiag.ctypes.data_as(ctypes.c_void_p) libfci.FCImake_hdiag_uhf(hdiag.ctypes.data_as(ctypes.c_void_p), c_h1e, c_h1e, c_jdiag, c_jdiag, c_jdiag, c_kdiag, c_kdiag, ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(neleca), ctypes.c_int(nelecb), strsa.ctypes.data_as(ctypes.c_void_p), strsb.ctypes.data_as(ctypes.c_void_p)) return hdiag
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.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(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 # 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] for i in range(na): ui = ua[occ_masks[i]].T.copy() minors = numpy.take(ui, occ_idx_all_strs, axis=0).reshape(na, neleca, neleca) trans_ci_a[i, :] = numpy.linalg.det(minors) if neleca == nelecb and numpy.allclose(ua, ub): trans_ci_b = trans_ci_a 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] for i in range(nb): ui = ub[occ_masks[i]].T.copy() minors = numpy.take(ui, occ_idx_all_strs, axis=0).reshape(nb, nelecb, nelecb) 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
def contract_ep(g, fcivec, nsite, nelec, nphonon): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) na, nb = cishape[:2] ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) nbar = float(neleca+nelecb) / nsite phonon_cre = numpy.sqrt(numpy.arange(1,nphonon+1)) for i in range(nsite): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 e_part = numpy.zeros((na,nb)) e_part[maska,:] += 1 e_part[:,maskb] += 1 e_part[:] -= float(neleca+nelecb) / nsite for ip in range(nphonon): slices1 = slices_for_cre(i, nsite, ip) slices0 = slices_for (i, nsite, ip) fcinew[slices1] += numpy.einsum('ij...,ij...->ij...', g*phonon_cre[ip]*e_part, ci0[slices0]) fcinew[slices0] += numpy.einsum('ij...,ij...->ij...', g*phonon_cre[ip]*e_part, ci0[slices1]) return fcinew.reshape(fcivec.shape)
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) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) return _symmetrize_wfn(ci, strsa, strsb, orbsym, wfnsym)
def get_init_guess(norb, nelec, nroots, hdiag, orbsym, wfnsym=0): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) airreps = numpy.zeros(strsa.size, dtype=numpy.int32) birreps = numpy.zeros(strsb.size, dtype=numpy.int32) for i in range(norb): airreps[numpy.bitwise_and(strsa, 1<<i) > 0] ^= orbsym[i] birreps[numpy.bitwise_and(strsb, 1<<i) > 0] ^= orbsym[i] na = len(strsa) nb = len(strsb) ci0 = [] iroot = 0 for addr in numpy.argsort(hdiag): x = numpy.zeros((na*nb)) addra = addr // nb addrb = addr % nb if airreps[addra] ^ birreps[addrb] == wfnsym: x[addr] = 1 ci0.append(x) iroot += 1 if iroot >= nroots: break return ci0
def contract_2e_hubbard(u, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec u_aa, u_ab, u_bb = u strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) fcivec = fcivec.reshape(na,nb) fcinew = numpy.zeros_like(fcivec) if u_aa != 0: # u * n_alpha^+ n_alpha for i in range(norb): maska = (strsa & (1<<i)) > 0 fcinew[maska] += u_aa * fcivec[maska] if u_ab != 0: # u * (n_alpha^+ n_beta + n_beta^+ n_alpha) for i in range(norb): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 fcinew[maska[:,None]&maskb] += 2*u_ab * fcivec[maska[:,None]&maskb] if u_bb != 0: # u * n_beta^+ n_beta for i in range(norb): maskb = (strsb & (1<<i)) > 0 fcinew[:,maskb] += u_bb * fcivec[:,maskb] return fcinew
def get_init_guess(norb, nelec, nroots, hdiag, orbsym, wfnsym=0): neleca, nelecb = _unpack_nelec(nelec) strsa = cistring.gen_strings4orblist(range(norb), neleca) airreps = birreps = _gen_strs_irrep(strsa, orbsym) if neleca != nelecb: strsb = cistring.gen_strings4orblist(range(norb), nelecb) birreps = _gen_strs_irrep(strsb, orbsym) return _get_init_guess(airreps, birreps, nroots, hdiag, orbsym, wfnsym)
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.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(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 # 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] for i in range(na): ui = ua[occ_masks[i]].T.copy() minors = numpy.take(ui, occ_idx_all_strs, axis=0).reshape(na,neleca,neleca) trans_ci_a[i,:] = numpy.linalg.det(minors) if neleca == nelecb and numpy.allclose(ua, ub): trans_ci_b = trans_ci_a 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] for i in range(nb): ui = ub[occ_masks[i]].T.copy() minors = numpy.take(ui, occ_idx_all_strs, axis=0).reshape(nb,nelecb,nelecb) 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
def test_strings4orblist(self): ref = ['0b1010', '0b100010', '0b101000', '0b10000010', '0b10001000', '0b10100000'] self.assertEqual(cistring.gen_strings4orblist([1,3,5,7], 2), [int(x,2) for x in ref]) ref = ['0b11', '0b101', '0b110', '0b1001', '0b1010', '0b1100', '0b10001', '0b10010', '0b10100', '0b11000'] self.assertEqual(cistring.gen_strings4orblist(range(5), 2), [int(x,2) for x in ref])
def test_strings4orblist(self): ref = ['0b1010', '0b100010', '0b101000', '0b10000010', '0b10001000', '0b10100000'] for i, x in enumerate(cistring.gen_strings4orblist([1,3,5,7], 2)): self.assertEqual(bin(x), ref[i]) ref = ['0b11', '0b101', '0b110', '0b1001', '0b1010', '0b1100', '0b10001', '0b10010', '0b10100', '0b11000'] for i, x in enumerate(cistring.gen_strings4orblist(range(5), 2)): self.assertEqual(bin(x), ref[i])
def contract_2e_hubbard(u, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for i in range(nsite): maska = (strsa & (1 << i)) > 0 maskb = (strsb & (1 << i)) > 0 fcinew[maska[:, None] & maskb] += u * ci0[maska[:, None] & maskb] return fcinew.reshape(fcivec.shape)
def contract_2e_hubbard(u, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for i in range(nsite): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 fcinew[maska[:,None]&maskb] += u * ci0[maska[:,None]&maskb] return fcinew.reshape(fcivec.shape)
def contract_2e_hubbard(u, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec u_aa, u_ab, u_bb = u strsa = cistring.gen_strings4orblist(range(norb), neleca) strsb = cistring.gen_strings4orblist(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) fcivec = fcivec.reshape(na, nb) t1a = numpy.zeros((norb, na, nb)) t1b = numpy.zeros((norb, na, nb)) fcinew = numpy.zeros_like(fcivec) for addr, s in enumerate(strsa): for i in range(norb): if s & (1 << i): t1a[i, addr] += fcivec[addr] for addr, s in enumerate(strsb): for i in range(norb): if s & (1 << i): t1b[i, :, addr] += fcivec[:, addr] if u_aa != 0: # u * n_alpha^+ n_alpha for addr, s in enumerate(strsa): for i in range(norb): if s & (1 << i): fcinew[addr] += t1a[i, addr] * u_aa if u_ab != 0: # u * n_alpha^+ n_beta for addr, s in enumerate(strsa): for i in range(norb): if s & (1 << i): fcinew[addr] += t1b[i, addr] * u_ab # u * n_beta^+ n_alpha for addr, s in enumerate(strsb): for i in range(norb): if s & (1 << i): fcinew[:, addr] += t1a[i, :, addr] * u_ab if u_bb != 0: # u * n_beta^+ n_beta for addr, s in enumerate(strsb): for i in range(norb): if s & (1 << i): fcinew[:, addr] += t1b[i, :, addr] * u_bb return fcinew
def contract_2e_hubbard(u, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec u_aa, u_ab, u_bb = u strsa = cistring.gen_strings4orblist(range(norb), neleca) strsb = cistring.gen_strings4orblist(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) fcivec = fcivec.reshape(na,nb) t1a = numpy.zeros((norb,na,nb)) t1b = numpy.zeros((norb,na,nb)) fcinew = numpy.zeros_like(fcivec) for addr, s in enumerate(strsa): for i in range(norb): if s & (1<<i): t1a[i,addr] += fcivec[addr] for addr, s in enumerate(strsb): for i in range(norb): if s & (1<<i): t1b[i,:,addr] += fcivec[:,addr] if u_aa != 0: # u * n_alpha^+ n_alpha for addr, s in enumerate(strsa): for i in range(norb): if s & (1<<i): fcinew[addr] += t1a[i,addr] * u_aa if u_ab != 0: # u * n_alpha^+ n_beta for addr, s in enumerate(strsa): for i in range(norb): if s & (1<<i): fcinew[addr] += t1b[i,addr] * u_ab # u * n_beta^+ n_alpha for addr, s in enumerate(strsb): for i in range(norb): if s & (1<<i): fcinew[:,addr] += t1a[i,:,addr] * u_ab if u_bb != 0: # u * n_beta^+ n_beta for addr, s in enumerate(strsb): for i in range(norb): if s & (1<<i): fcinew[:,addr] += t1b[i,:,addr] * u_bb return fcinew
def make_confsym (norb, neleca, nelecb, econf_det_mask, orbsym): strsa = cistring.gen_strings4orblist(range(norb), neleca) airreps = birreps = _gen_strs_irrep(strsa, orbsym) if neleca != nelecb: strsb = cistring.gen_strings4orblist(range(norb), nelecb) birreps = _gen_strs_irrep(strsb, orbsym) nconf, addr = np.unique (econf_det_mask, return_index=True) nconf = nconf.size # Note: econf_det_mask[addr] = np.arange (nconf) # All determinants of the same configuration have the same point group conf_addra = addr // len (birreps) conf_addrb = addr % len (birreps) confsym = airreps[conf_addra] ^ birreps[conf_addrb] return confsym
def test_strings4orblist(self): ref = ['0b1010', '0b100010', '0b101000', '0b10000010', '0b10001000', '0b10100000'] for i, x in enumerate(cistring.gen_strings4orblist([1,3,5,7], 2)): self.assertEqual(bin(x), ref[i]) ref = ['0b11', '0b101', '0b110', '0b1001', '0b1010', '0b1100', '0b10001', '0b10010', '0b10100', '0b11000'] for i, x in enumerate(cistring.gen_strings4orblist(range(5), 2)): self.assertEqual(bin(x), ref[i]) strs = cistring.gen_strings4orblist(range(8), 4) occlst = cistring._gen_occslst(range(8), 4) self.assertAlmostEqual(abs(occlst - cistring._strs2occslst(strs, 8)).sum(), 0, 12) self.assertAlmostEqual(abs(strs - cistring._occslst2strs(occlst)).sum(), 0, 12)
def test_rdm(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs) ci0 = select_ci.to_fci(ci_coeff, norb, (nelec,nelec)) dm1ref, dm2ref = direct_spin1.make_rdm12s(ci0, norb, (nelec,nelec)) dm1 = select_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 = select_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 = select_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs) ci1 = select_ci.to_fci(ci1_coeff, norb, (nelec,nelec)) dm1ref, dm2ref = direct_spin1.trans_rdm12s(ci1, ci0, norb, (nelec,nelec)) dm1 = select_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)
def test_contract_2e_symm(self): norb, nelec = 7, (4, 4) strs = cistring.gen_strings4orblist(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) civec_strs = select_ci._as_SCIvector( numpy.random.random((len(strsa), len(strsb))), 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.select_ci.to_fci(civec_strs, norb, nelec) ci0 = fci.addons.symmetrize_wfn(ci0, norb, nelec, orbsym) civec_strs = fci.select_ci.from_fci(ci0, civec_strs._strs, norb, nelec) e1 = numpy.dot( civec_strs.ravel(), select_ci_symm.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)
def to_fci(civec, norb, nelec, root=0): assert(norb <= 64) neleca, nelecb = nelec strsa = cistring.gen_strings4orblist(range(norb), neleca) stradic = dict(zip(strsa,range(strsa.__len__()))) strsb = cistring.gen_strings4orblist(range(norb), nelecb) strbdic = dict(zip(strsb,range(strsb.__len__()))) na = len(stradic) nb = len(strbdic) ndet = len(civec[root]) fcivec = numpy.zeros((na,nb)) for idet, (stra, strb) in enumerate(civec[root]._strs.reshape(ndet,2,-1)): ka = stradic[stra[0]] kb = strbdic[strb[0]] fcivec[ka,kb] = civec[root][idet] return fcivec
def test_contract1(self): myci = select_ci.SelectCI() nelec = (4,3) strsa = cistring.gen_strings4orblist(range(norb), nelec[0]) strsb = cistring.gen_strings4orblist(range(norb), nelec[1]) ci0 = select_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(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_rdm2(c1, norb, nelec) dm2_2 = direct_spin1.make_rdm12(c2, norb, nelec)[1] self.assertAlmostEqual(abs(dm2_1 - dm2_2).sum(), 0, 9)
def get_init_guess(norb, nelec, nroots, hdiag, orbsym, wfnsym=0): neleca, nelecb = direct_spin1._unpack_nelec(nelec) assert (neleca == nelecb) strsa = cistring.gen_strings4orblist(range(norb), neleca) airreps = direct_spin1_symm._gen_strs_irrep(strsa, orbsym) na = nb = len(airreps) init_strs = [] iroot = 0 for addr in numpy.argsort(hdiag): addra = addr // nb addrb = addr % nb if airreps[addra] ^ airreps[addrb] == wfnsym: if (addrb, addra) not in init_strs: init_strs.append((addra, addrb)) iroot += 1 if iroot >= nroots: break ci0 = [] for addra, addrb in init_strs: x = numpy.zeros((na, nb)) if addra == addrb == 0: x[addra, addrb] = 1 else: x[addra, addrb] = x[addrb, addra] = numpy.sqrt(.5) ci0.append(x.ravel()) # Add noise #ci0[0][0 ] += 1e-5 #ci0[0][-1] -= 1e-5 if len(ci0) == 0: raise RuntimeError('No determinant matches the target symmetry %s' % wfnsym) return ci0
def _parse_fci_vector(self, ci_vecmat): """ Translate the PySCF FCI matrix into a dictionary of configurations and weights Args: ci_vecmat (np.ndarray): ci vector from a PySCF FCI calculation Returns: Mapping[str, float]: dictionary of configuration weights (normalized) organized by configuration label. Configurations labeled by their active space orbital occupations: 0 (unoccupied), a (alpha electron only), b (beta electron only), or '2' (doubly occupied) Example: >>> import numpy as np >>> model = PySCFPotential(active_orbitals=2, active_electrons=2) >>> model._parse_fci_vector(np.array([[1.0, 2.0],[3.0, 4.0]])) {'20': 1.0, 'ba': 2.0, 'ab': 3.0, '02': 4.0} """ from pyscf.fci import cistring conf_bin = cistring.gen_strings4orblist(list(range(self.params.active_orbitals)), old_div(self.params.active_electrons,2)) civecs = {} for i, ca in enumerate(conf_bin): for j, cb in enumerate(conf_bin): astring = bin(ca)[2:].zfill(self.params.active_orbitals) bstring = bin(cb)[2:].zfill(self.params.active_orbitals) s = ''.join(reversed([self._OCCMAP[a, b] for a, b in zip(astring, bstring)])) civecs[s] = ci_vecmat[i, j] return civecs
def contract_ep(g, fcivec, nsite, nexciton, nmode, nphonon): # N_alpha N_beta * \sum_{p} (p^+ + p) # N_alpha, N_beta are particle number operator, p^+ and p are phonon creation annihilation operator strs = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nexciton)) cishape = make_shape(nsite, nexciton, nmode, nphonon) nstr = cishape[0] ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) nbar = 0.0 phonon_cre = numpy.sqrt(numpy.arange(1,nphonon+1)) for i in range(nsite): mask = (strs & (1<<i)) > 0 e_part = numpy.zeros((nstr,)) e_part[mask] += 1 #e_part[:] -= float(nexcitona+nexcitonb) / nsite for j in range(nmode): for ip in range(nphonon): slices1 = slices_for_cre(i, j, nsite, nmode, ip) slices0 = slices_for (i, j, nsite, nmode, ip) # fcinew[slices1] += numpy.einsum('ij...,ij...->ij...', g[i,j]*phonon_cre[ip]*e_part, ci0[slices0]) # fcinew[slices0] += numpy.einsum('ij...,ij...->ij...', g[i, j]*phonon_cre[ip]*e_part, ci0[slices1]) fcinew[slices1] += numpy.einsum('i...,i...->i...', g[i,j]*phonon_cre[ip]*e_part, ci0[slices0]) fcinew[slices0] += numpy.einsum('i...,i...->i...', g[i, j]*phonon_cre[ip]*e_part, ci0[slices1]) return fcinew.reshape(fcivec.shape)
def test_rdm(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_ci._as_SCIvector( numpy.random.random((len(strsa), len(strsb))), ci_strs) ci0 = select_ci.to_fci(ci_coeff, norb, (nelec, nelec)) dm1ref, dm2ref = direct_spin1.make_rdm12s(ci0, norb, (nelec, nelec)) dm1 = select_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 = select_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 = select_ci._as_SCIvector( numpy.random.random((len(strsa), len(strsb))), ci_strs) ci1 = select_ci.to_fci(ci1_coeff, norb, (nelec, nelec)) dm1ref, dm2ref = direct_spin1.trans_rdm12s(ci1, ci0, norb, (nelec, nelec)) dm1 = select_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)
def test_parity(self): strs = cistring.gen_strings4orblist(range(5), 3) links = cistring.gen_linkstr_index(range(5), 3) parity = [] for addr0, link in enumerate(links): parity.append([cistring.parity(strs[addr0], strs[addr1]) for addr1 in link[:,2]]) self.assertEqual(parity, links[:,:,3].tolist())
def contract_2e_hubbard(u, fcivec, nsite, nelec, nphonon): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for i in range(nsite): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 fcinew[maska[:,None]&maskb] += u * ci0[maska[:,None]&maskb] return fcinew.reshape(fcivec.shape)
def test_contract1(self): myci = select_ci.SCI() nelec = (4, 3) strsa = cistring.gen_strings4orblist(range(norb), nelec[0]) strsb = cistring.gen_strings4orblist(range(norb), nelec[1]) ci0 = select_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(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_rdm2(c1, norb, nelec) dm2_2 = direct_spin1.make_rdm12(c2, norb, nelec)[1] self.assertAlmostEqual(abs(dm2_1 - dm2_2).sum(), 0, 9)
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 the orbital rotation to transform the old one-particle basis to new one-particle basis ''' neleca, nelecb = _unpack(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) one_particle_strs = numpy.asarray([1<<i for i in range(norb)]) na = len(strsa) nb = len(strsb) # 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, stri in enumerate(strsa): # for old basis orbi_mask = occ_masks[i] ui = u[orbi_mask] minors = [ui[:,occ_masks[j]] for j in range(len(strsa))] # for new basis trans_ci_a[i,:] = numpy.linalg.det(minors) if neleca == nelecb: trans_ci_b = trans_ci_a else: occ_masks = (strsb[:,None] & one_particle_strs) != 0 trans_ci_b = numpy.zeros((nb,nb)) for i, stri in enumerate(strsb): orbi_mask = occ_masks[i] ui = u[orbi_mask] minors = [ui[:,occ_masks[j]] for j in range(len(strsb))] 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
def from_fci(fcivec, ci_strs, norb, nelec): neleca, nelecb = nelec strsa = cistring.gen_strings4orblist(range(norb), neleca) stradic = dict(zip(strsa,range(strsa.__len__()))) strsb = cistring.gen_strings4orblist(range(norb), nelecb) strbdic = dict(zip(strsb,range(strsb.__len__()))) na = len(stradic) nb = len(strbdic) fcivec = fcivec.reshape(na,nb) ta = [excitation_level(s, neleca) for s in strsa.reshape(-1,1)] tb = [excitation_level(s, nelecb) for s in strsb.reshape(-1,1)] ndet = len(ci_strs) civec = numpy.zeros(ndet) for idet, (stra, strb) in enumerate(ci_strs.reshape(ndet,2,-1)): ka = stradic[stra[0]] kb = strbdic[strb[0]] civec[idet] = fcivec[ka,kb] return as_SCIvector(civec, ci_strs)
def get_init_guess(norb, nelec, nroots, hdiag, orbsym, wfnsym=0): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) airreps = numpy.zeros(strsa.size, dtype=numpy.int32) birreps = numpy.zeros(strsb.size, dtype=numpy.int32) for i in range(norb): airreps[numpy.bitwise_and(strsa, 1<<i) > 0] ^= orbsym[i] birreps[numpy.bitwise_and(strsb, 1<<i) > 0] ^= orbsym[i] na = len(strsa) nb = len(strsb) init_strs = [] iroot = 0 for addr in numpy.argsort(hdiag): addra = addr // nb addrb = addr % nb if airreps[addra] ^ birreps[addrb] == wfnsym: if (addrb,addra) not in init_strs: init_strs.append((addra,addrb)) iroot += 1 if iroot >= nroots: break ci0 = [] for addra,addrb in init_strs: x = numpy.zeros((na,nb)) if addra == addrb == 0: x[addra,addrb] = 1 else: x[addra,addrb] = x[addrb,addra] = numpy.sqrt(.5) ci0.append(x.ravel()) # Add noise #ci0[0][0 ] += 1e-5 #ci0[0][-1] -= 1e-5 if len(ci0) == 0: raise RuntimeError('No determinant matches the target symmetry %s' % wfnsym) return ci0
def reorder(ci, nelec, orbidxa, orbidxb=None): '''Reorder the CI coefficients, to adapt the reordered orbitals (The relation of the reordered orbitals and original orbitals is new = old[idx]). Eg. The orbital ordering indices ``orbidx = [2,0,1]`` indicates the map old orbital a b c -> new orbital c a b. The strings are reordered as old-strings 0b011, 0b101, 0b110 == (1,2), (1,3), (2,3) <= apply orbidx to get orb-strings orb-strings (3,1), (3,2), (1,2) == 0B101, 0B110, 0B011 <= by gen_strings4orblist then argsort to translate the string representation to the address [2(=0B011), 0(=0B101), 1(=0B110)] ''' neleca, nelecb = _unpack(nelec) if orbidxb is None: orbidxb = orbidxa guide_stringsa = cistring.gen_strings4orblist(orbidxa, neleca) guide_stringsb = cistring.gen_strings4orblist(orbidxb, nelecb) old_det_idxa = numpy.argsort(guide_stringsa) old_det_idxb = numpy.argsort(guide_stringsb) return lib.take_2d(ci, old_det_idxa, old_det_idxb)
def test_des_linkstr(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_ci.gen_cre_linkstr(strs, norb, nelec) c_index1[:,:,1] = 0 self.assertTrue(numpy.all(c_index0 == c_index1))
def test_parity(self): strs = cistring.gen_strings4orblist(range(5), 3) links = cistring.gen_linkstr_index(range(5), 3) parity = [] for addr0, link in enumerate(links): parity.append([ cistring.parity(strs[addr0], strs[addr1]) for addr1 in link[:, 2] ]) self.assertEqual(parity, links[:, :, 3].tolist())
def test_des_linkstr(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_ci.gen_cre_linkstr(strs, norb, nelec) c_index1[:, :, 1] = 0 self.assertTrue(numpy.all(c_index0 == c_index1))
def test_strings4orblist(self): ref = [ '0b1010', '0b100010', '0b101000', '0b10000010', '0b10001000', '0b10100000' ] for i, x in enumerate(cistring.gen_strings4orblist([1, 3, 5, 7], 2)): self.assertEqual(bin(x), ref[i]) ref = [ '0b11', '0b101', '0b110', '0b1001', '0b1010', '0b1100', '0b10001', '0b10010', '0b10100', '0b11000' ] for i, x in enumerate(cistring.gen_strings4orblist(range(5), 2)): self.assertEqual(bin(x), ref[i]) strs = cistring.gen_strings4orblist(range(8), 4) occlst = cistring._gen_occslst(range(8), 4) self.assertAlmostEqual( abs(occlst - cistring._strs2occslst(strs, 8)).sum(), 0, 12) self.assertAlmostEqual( abs(strs - cistring._occslst2strs(occlst)).sum(), 0, 12)
def reorder(ci, nelec, orbidxa, orbidxb=None): '''reorder the CI coefficients wrt the reordering of orbitals (The relation of the reordered orbitals and original orbitals is new = old[idx]). Eg. orbidx = [2,0,1] to map old orbital a b c -> new orbital c a b old-strings 0b011, 0b101, 0b110 == (1,2), (1,3), (2,3) orb-strings (3,1), (3,2), (1,2) == 0B101, 0B110, 0B011 <= by gen_strings4orblist then argsort to translate the string representation to the address [2(=0B011), 0(=0B101), 1(=0B110)] ''' if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec // 2 else: neleca, nelecb = nelec if orbidxb is None: orbidxb = orbidxa guide_stringsa = cistring.gen_strings4orblist(orbidxa, neleca) guide_stringsb = cistring.gen_strings4orblist(orbidxb, nelecb) old_det_idxa = numpy.argsort(guide_stringsa) old_det_idxb = numpy.argsort(guide_stringsb) return ci.take(old_det_idxa, axis=0).take(old_det_idxb, axis=1)
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) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) return _guess_wfnsym(ci, strsa, strsb, orbsym)
def test_des_des_linkstr(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_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 = select_ci.des_des_linkstr_tril(strs, norb, nelec) dd_index1[:,:,1] = 0 self.assertTrue(numpy.all(dd_index0 == dd_index1))
def make_hdiag(h1e, g2e, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec occslista = [[i for i in range(neleca) if str0 & (1<<i)] for str0 in cistring.gen_strings4orblist(range(norb), neleca)] occslistb = [[i for i in range(nelecb) if str0 & (1<<i)] for str0 in cistring.gen_strings4orblist(range(norb), nelecb)] g2e = ao2mo.restore(1, g2e, norb) diagj = numpy.einsum('iijj->ij',g2e) diagk = numpy.einsum('ijji->ij',g2e) hdiag = [] for aocc in occslista: for bocc in occslistb: e1 = h1e[aocc,aocc].sum() + h1e[bocc,bocc].sum() e2 = diagj[aocc][:,aocc].sum() + diagj[aocc][:,bocc].sum() \ + diagj[bocc][:,aocc].sum() + diagj[bocc][:,bocc].sum() \ - diagk[aocc][:,aocc].sum() - diagk[bocc][:,bocc].sum() hdiag.append(e1 + e2*.5) return numpy.array(hdiag)
def make_hdiag(h1e, g2e, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec occslista = [[i for i in range(neleca) if str0 & (1 << i)] for str0 in cistring.gen_strings4orblist(range(norb), neleca)] occslistb = [[i for i in range(nelecb) if str0 & (1 << i)] for str0 in cistring.gen_strings4orblist(range(norb), nelecb)] g2e = ao2mo.restore(1, g2e, norb) diagj = numpy.einsum('iijj->ij', g2e) diagk = numpy.einsum('ijji->ij', g2e) hdiag = [] for aocc in occslista: for bocc in occslistb: e1 = h1e[aocc, aocc].sum() + h1e[bocc, bocc].sum() e2 = diagj[aocc][:,aocc].sum() + diagj[aocc][:,bocc].sum() \ + diagj[bocc][:,aocc].sum() + diagj[bocc][:,bocc].sum() \ - diagk[aocc][:,aocc].sum() - diagk[bocc][:,bocc].sum() hdiag.append(e1 + e2 * .5) return numpy.array(hdiag)
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 ''' if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) airreps = numpy.zeros(strsa.size, dtype=numpy.int32) birreps = numpy.zeros(strsb.size, dtype=numpy.int32) for i in range(norb): airreps[numpy.bitwise_and(strsa, 1<<i) > 0] ^= orbsym[i] birreps[numpy.bitwise_and(strsb, 1<<i) > 0] ^= orbsym[i] #print(airreps) #print(birreps) mask = (numpy.bitwise_xor(airreps.reshape(-1,1), birreps) == wfnsym) ci1 = numpy.zeros_like(ci) ci1[mask] = ci[mask] return ci1
def test_des_des_linkstr(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_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 = select_ci.des_des_linkstr_tril(strs, norb, nelec) dd_index1[:, :, 1] = 0 self.assertTrue(numpy.all(dd_index0 == dd_index1))
def test_spin_square(self): norb, nelec = 10, 4 strs = cistring.gen_strings4orblist(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 = select_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs) ci0 = select_ci.to_fci(ci_coeff, norb, (nelec,nelec)) ss0 = select_ci.spin_square(ci_coeff, norb, (nelec,nelec)) ss1 = spin_op.spin_square0(ci0, norb, (nelec,nelec)) self.assertAlmostEqual(ss0[0], ss1[0], 9)
def test_contract_2e_symm(self): norb, nelec = 7, (4,4) strs = cistring.gen_strings4orblist(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) civec_strs = select_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), ci_strs) orbsym = (numpy.random.random(norb) * 4).astype(int) nn = norb*(norb+1)//2 eri = (numpy.random.random(nn*(nn+1)//2)-.2)**3 ci0 = select_ci.to_fci(civec_strs, norb, nelec) e1 = numpy.dot(civec_strs.ravel(), select_ci_symm.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)