def from_fci(fcivec, ci_strs, norb, nelec): fcivec, nelec, ci_strs = _unpack(fcivec, nelec, ci_strs) addrsa = [cistring.str2addr(norb, nelec[0], x) for x in ci_strs[0]] addrsb = [cistring.str2addr(norb, nelec[1], x) for x in ci_strs[1]] na = cistring.num_strings(norb, nelec[0]) nb = cistring.num_strings(norb, nelec[1]) fcivec = fcivec.reshape(na, nb) civec = lib.take_2d(fcivec, addrsa, addrsb) return _as_SCIvector(civec, ci_strs)
def from_fci(fcivec, ci_strs, norb, nelec): fcivec, nelec, ci_strs = _unpack(fcivec, nelec, ci_strs) addrsa = [cistring.str2addr(norb, nelec[0], x) for x in ci_strs[0]] addrsb = [cistring.str2addr(norb, nelec[1], x) for x in ci_strs[1]] na = cistring.num_strings(norb, nelec[0]) nb = cistring.num_strings(norb, nelec[1]) fcivec = fcivec.reshape(na,nb) civec = lib.take_2d(fcivec, addrsa, addrsb) return _as_SCIvector(civec, ci_strs)
def to_fci(civec_strs, norb, nelec): ci_coeff, nelec, ci_strs = _unpack(civec_strs, nelec) addrsa = [cistring.str2addr(norb, nelec[0], x) for x in ci_strs[0]] addrsb = [cistring.str2addr(norb, nelec[1], x) for x in ci_strs[1]] na = cistring.num_strings(norb, nelec[0]) nb = cistring.num_strings(norb, nelec[1]) ci0 = numpy.zeros((na, nb)) lib.takebak_2d(ci0, ci_coeff, addrsa, addrsb) return ci0
def to_fci(civec_strs, norb, nelec): ci_coeff, nelec, ci_strs = _unpack(civec_strs, nelec) addrsa = [cistring.str2addr(norb, nelec[0], x) for x in ci_strs[0]] addrsb = [cistring.str2addr(norb, nelec[1], x) for x in ci_strs[1]] na = cistring.num_strings(norb, nelec[0]) nb = cistring.num_strings(norb, nelec[1]) ci0 = numpy.zeros((na,nb)) lib.takebak_2d(ci0, ci_coeff, addrsa, addrsb) return ci0
def to_fci(cisdvec, norb, nelec): if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec nocc = neleca nvir = norb - nocc c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, norb, nocc) t1addr, t1sign = t1strs(norb, nocc) na = cistring.num_strings(norb, nocc) fcivec = numpy.zeros((na, na)) fcivec[0, 0] = c0 c1 = c1[::-1].T.ravel() fcivec[0, t1addr] = fcivec[t1addr, 0] = c1 * t1sign c2ab = c2[::-1, ::-1].transpose(2, 0, 3, 1).reshape(nocc * nvir, -1) c2ab = numpy.einsum('i,j,ij->ij', t1sign, t1sign, c2ab) lib.takebak_2d(fcivec, c2ab, t1addr, t1addr) if nocc > 1 and nvir > 1: hf_str = int('1' * nocc, 2) for a in range(nocc, norb): for b in range(nocc, a): for i in reversed(range(1, nocc)): for j in reversed(range(i)): c2aa = c2[i, j, a - nocc, b - nocc] - c2[j, i, a - nocc, b - nocc] str1 = hf_str ^ (1 << j) | (1 << b) c2aa *= cistring.cre_des_sign(b, j, hf_str) c2aa *= cistring.cre_des_sign(a, i, str1) str1 ^= (1 << i) | (1 << a) addr = cistring.str2addr(norb, nocc, str1) fcivec[0, addr] = fcivec[addr, 0] = c2aa return fcivec
def search_open_shell_det(occ_lst): occ_mask = numpy.zeros(norb, dtype=bool) occ_mask[occ_lst] = True # First search Lz of the open-shell orbital for lz_open in all_lz: if numpy.count_nonzero(orb_lz == lz_open) % 2 == 1: break n_gx = numpy.count_nonzero(gx_mask & occ_mask & (orb_lz == lz_open)) n_gy = numpy.count_nonzero(gy_mask & occ_mask & (orb_lz == -lz_open)) n_ux = numpy.count_nonzero(ux_mask & occ_mask & (orb_lz == lz_open)) n_uy = numpy.count_nonzero(uy_mask & occ_mask & (orb_lz == -lz_open)) if n_gx > n_gy: idx = numpy.where(occ_mask & (orb_lz == lz_open) & gx_mask)[0][0] idy = numpy.where((~occ_mask) & (orb_lz == -lz_open) & gy_mask)[0][0] elif n_gx < n_gy: idx = numpy.where((~occ_mask) & (orb_lz == lz_open) & gx_mask)[0][0] idy = numpy.where(occ_mask & (orb_lz == -lz_open) & gy_mask)[0][0] elif n_ux > n_uy: idx = numpy.where(occ_mask & (orb_lz == lz_open) & ux_mask)[0][0] idy = numpy.where((~occ_mask) & (orb_lz == -lz_open) & uy_mask)[0][0] elif n_ux < n_uy: idx = numpy.where((~occ_mask) & (orb_lz == lz_open) & ux_mask)[0][0] idy = numpy.where(occ_mask & (orb_lz == -lz_open) & uy_mask)[0][0] else: raise RuntimeError nelec = len(occ_lst) det_x = occ_mask.copy() det_x[idx] = True det_x[idy] = False str_x = ''.join(['1' if i else '0' for i in det_x[::-1]]) addr_x = cistring.str2addr(norb, nelec, str_x) det_y = occ_mask.copy() det_y[idx] = False det_y[idy] = True str_y = ''.join(['1' if i else '0' for i in det_y[::-1]]) addr_y = cistring.str2addr(norb, nelec, str_y) return addr_x, addr_y
def initguess_triplet(norb, nelec, binstring): '''Generate a triplet initial guess for FCI solver ''' neleca, nelecb = _unpack(nelec) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) addr = cistring.str2addr(norb, neleca, int(binstring, 2)) ci0 = numpy.zeros((na, nb)) ci0[addr, 0] = numpy.sqrt(.5) ci0[0, addr] = -numpy.sqrt(.5) return ci0
def t1strs(norb, nelec): nocc = nelec hf_str = int('1'*nocc, 2) addrs = [] signs = [] for a in range(nocc, norb): for i in reversed(range(nocc)): str1 = hf_str ^ (1 << i) | (1 << a) addrs.append(cistring.str2addr(norb, nelec, str1)) signs.append(cistring.cre_des_sign(a, i, hf_str)) return numpy.asarray(addrs), numpy.asarray(signs)
def t1strs(norb, nelec): nocc = nelec hf_str = int('1' * nocc, 2) addrs = [] signs = [] for a in range(nocc, norb): for i in reversed(range(nocc)): str1 = hf_str ^ (1 << i) | (1 << a) addrs.append(cistring.str2addr(norb, nelec, str1)) signs.append(cistring.cre_des_sign(a, i, hf_str)) return numpy.asarray(addrs), numpy.asarray(signs)
def initguess_triplet(norb, nelec, binstring): '''Generate a triplet initial guess for FCI solver ''' neleca, nelecb = _unpack(nelec) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) addr = cistring.str2addr(norb, neleca, int(binstring,2)) ci0 = numpy.zeros((na,nb)) ci0[addr,0] = numpy.sqrt(.5) ci0[0,addr] =-numpy.sqrt(.5) return ci0
def initguess_triplet(norb, nelec, binstring): if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec//2 else: neleca, nelecb = nelec na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) addr = cistring.str2addr(norb, neleca, int(binstring,2)) ci0 = numpy.zeros((na,nb)) ci0[addr,0] = numpy.sqrt(.5) ci0[0,addr] =-numpy.sqrt(.5) return ci0
def t1strs(norb, nelec): '''FCI strings (address) for CIS single-excitation amplitues''' nocc = nelec hf_str = int('1' * nocc, 2) addrs = [] signs = [] for a in range(nocc, norb): for i in reversed(range(nocc)): str1 = hf_str ^ (1 << i) | (1 << a) addrs.append(cistring.str2addr(norb, nelec, str1)) signs.append(cistring.cre_des_sign(a, i, hf_str)) return numpy.asarray(addrs), numpy.asarray(signs)
def search_open_shell_det(occ_lst): occ_mask = numpy.zeros(norb, dtype=bool) occ_mask[occ_lst] = True # First search Lz of the open-shell orbital for lz_open in all_lz: if numpy.count_nonzero(orb_lz == lz_open) % 2 == 1: break n_gx = numpy.count_nonzero(gx_mask & occ_mask & (orb_lz == lz_open)) n_gy = numpy.count_nonzero(gy_mask & occ_mask & (orb_lz ==-lz_open)) n_ux = numpy.count_nonzero(ux_mask & occ_mask & (orb_lz == lz_open)) n_uy = numpy.count_nonzero(uy_mask & occ_mask & (orb_lz ==-lz_open)) if n_gx > n_gy: idx = numpy.where(occ_mask & (orb_lz == lz_open) & gx_mask)[0][0] idy = numpy.where((~occ_mask) & (orb_lz ==-lz_open) & gy_mask)[0][0] elif n_gx < n_gy: idx = numpy.where((~occ_mask) & (orb_lz == lz_open) & gx_mask)[0][0] idy = numpy.where(occ_mask & (orb_lz ==-lz_open) & gy_mask)[0][0] elif n_ux > n_uy: idx = numpy.where(occ_mask & (orb_lz == lz_open) & ux_mask)[0][0] idy = numpy.where((~occ_mask) & (orb_lz ==-lz_open) & uy_mask)[0][0] elif n_ux < n_uy: idx = numpy.where((~occ_mask) & (orb_lz == lz_open) & ux_mask)[0][0] idy = numpy.where(occ_mask & (orb_lz ==-lz_open) & uy_mask)[0][0] else: raise RuntimeError nelec = len(occ_lst) det_x = occ_mask.copy() det_x[idx] = True det_x[idy] = False str_x = ''.join(['1' if i else '0' for i in det_x[::-1]]) addr_x = cistring.str2addr(norb, nelec, str_x) det_y = occ_mask.copy() det_y[idx] = False det_y[idy] = True str_y = ''.join(['1' if i else '0' for i in det_y[::-1]]) addr_y = cistring.str2addr(norb, nelec, str_y) return addr_x, addr_y
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)))))
def t2strs(norb, nelec): nocc = nelec hf_str = int('1'*nocc, 2) addrs = [] signs = [] for a in range(nocc+1, norb): for b in range(nocc, a): for i in reversed(range(1,nocc)): for j in reversed(range(i)): str1 = hf_str ^ (1 << j) | (1 << b) sign = cistring.cre_des_sign(b, j, hf_str) sign*= cistring.cre_des_sign(a, i, str1) str1^= (1 << i) | (1 << a) addrs.append(cistring.str2addr(norb, nelec, str1)) signs.append(sign) return numpy.asarray(addrs), numpy.asarray(signs)
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)))))
def to_fci(cisdvec, norb, nelec): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec nocc = neleca nvir = norb - nocc c0 = cisdvec[0] c1 = cisdvec[1:nocc*nvir+1].reshape(nocc,nvir) c2 = cisdvec[nocc*nvir+1:].reshape(nocc,nocc,nvir,nvir) t1addr, t1sign = t1strs(norb, nocc) na = cistring.num_strings(norb, nocc) fcivec = numpy.zeros((na,na)) fcivec[0,0] = c0 c1 = c1[::-1].T.ravel() fcivec[0,t1addr] = fcivec[t1addr,0] = c1 * t1sign c2ab = c2[::-1,::-1].transpose(2,0,3,1).reshape(nocc*nvir,-1) c2ab = numpy.einsum('i,j,ij->ij', t1sign, t1sign, c2ab) lib.takebak_2d(fcivec, c2ab, t1addr, t1addr) if nocc > 1 and nvir > 1: hf_str = int('1'*nocc, 2) for a in range(nocc, norb): for b in range(nocc, a): for i in reversed(range(1, nocc)): for j in reversed(range(i)): c2aa = c2[i,j,a-nocc,b-nocc] - c2[j,i,a-nocc,b-nocc] str1 = hf_str ^ (1 << j) | (1 << b) c2aa*= cistring.cre_des_sign(b, j, hf_str) c2aa*= cistring.cre_des_sign(a, i, str1) str1^= (1 << i) | (1 << a) addr = cistring.str2addr(norb, nocc, str1) fcivec[0,addr] = fcivec[addr,0] = c2aa return fcivec
def find_addr_(stra, aonly, nelec): stra[orbleft[aonly]] = True return cistring.str2addr(norb, nelec, ('%i'*norb)%tuple(stra)[::-1])
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)
def find_addr_(stra, aonly, nelec): stra[orbleft[aonly]] = True return cistring.str2addr(norb, nelec, ('%i' * norb) % tuple(stra)[::-1])
def to_fcivec(cisdvec, norb, nelec, frozen=0): '''Convert CISD coefficients to FCI coefficients''' if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec assert (neleca == nelecb) frozen_mask = numpy.zeros(norb, dtype=bool) if isinstance(frozen, (int, numpy.integer)): nfroz = frozen frozen_mask[:frozen] = True else: nfroz = len(frozen) frozen_mask[frozen] = True nocc = numpy.count_nonzero(~frozen_mask[:neleca]) nmo = norb - nfroz nvir = nmo - nocc c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc) t1addr, t1sign = t1strs(nmo, nocc) na = cistring.num_strings(nmo, nocc) fcivec = numpy.zeros((na, na)) fcivec[0, 0] = c0 c1 = c1[::-1].T.ravel() fcivec[0, t1addr] = fcivec[t1addr, 0] = c1 * t1sign c2ab = c2[::-1, ::-1].transpose(2, 0, 3, 1).reshape(nocc * nvir, -1) c2ab = numpy.einsum('i,j,ij->ij', t1sign, t1sign, c2ab) lib.takebak_2d(fcivec, c2ab, t1addr, t1addr) if nocc > 1 and nvir > 1: hf_str = int('1' * nocc, 2) for a in range(nocc, nmo): for b in range(nocc, a): for i in reversed(range(1, nocc)): for j in reversed(range(i)): c2aa = c2[i, j, a - nocc, b - nocc] - c2[j, i, a - nocc, b - nocc] str1 = hf_str ^ (1 << j) | (1 << b) c2aa *= cistring.cre_des_sign(b, j, hf_str) c2aa *= cistring.cre_des_sign(a, i, str1) str1 ^= (1 << i) | (1 << a) addr = cistring.str2addr(nmo, nocc, str1) fcivec[0, addr] = fcivec[addr, 0] = c2aa if nfroz == 0: return fcivec assert (norb < 63) strs = cistring.gen_strings4orblist(range(norb), neleca) na = len(strs) count = numpy.zeros(na, dtype=int) parity = numpy.zeros(na, dtype=bool) core_mask = numpy.ones(na, dtype=bool) # During the loop, count saves the number of occupied orbitals that # lower (with small orbital ID) than the present orbital i. # Moving all the frozen orbitals to the beginning of the orbital list # (before the occupied orbitals) leads to parity odd (= True, with # negative sign) or even (= False, with positive sign). for i in range(norb): if frozen_mask[i]: if i < neleca: # frozen occupied orbital should be occupied core_mask &= (strs & (1 << i)) != 0 parity ^= (count & 1) == 1 else: # frozen virtual orbital should not be occupied. # parity is not needed since it's unoccupied core_mask &= (strs & (1 << i)) == 0 else: count += (strs & (1 << i)) != 0 sub_strs = strs[core_mask & (count == nocc)] addrs = cistring.strs2addr(norb, neleca, sub_strs) fcivec1 = numpy.zeros((na, na)) fcivec1[addrs[:, None], addrs] = fcivec fcivec1[parity, :] *= -1 fcivec1[:, parity] *= -1 return fcivec1