def from_fcivec(ci0, norb, nelec, frozen=0): '''Extract CISD coefficients from FCI coefficients''' if frozen is not 0: raise NotImplementedError if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec norba = norbb = norb nocc = nocca, noccb = neleca, nelecb nvira = norba - nocca nvirb = norbb - noccb t1addra, t1signa = cisd.tn_addrs_signs(norba, nocca, 1) t1addrb, t1signb = cisd.tn_addrs_signs(norbb, noccb, 1) na = cistring.num_strings(norba, nocca) nb = cistring.num_strings(norbb, noccb) ci0 = ci0.reshape(na,nb) c0 = ci0[0,0] c1a = (ci0[t1addra,0] * t1signa).reshape(nocca,nvira) c1b = (ci0[0,t1addrb] * t1signb).reshape(noccb,nvirb) c2ab = numpy.einsum('i,j,ij->ij', t1signa, t1signb, ci0[t1addra[:,None],t1addrb]) c2ab = c2ab.reshape(nocca,nvira,noccb,nvirb).transpose(0,2,1,3) t2addra, t2signa = cisd.tn_addrs_signs(norba, nocca, 2) t2addrb, t2signb = cisd.tn_addrs_signs(norbb, noccb, 2) c2aa = (ci0[t2addra,0] * t2signa).reshape(nocca*(nocca-1)//2, nvira*(nvira-1)//2) c2aa = _unpack_4fold(c2aa, nocca, nvira) c2bb = (ci0[0,t2addrb] * t2signb).reshape(noccb*(noccb-1)//2, nvirb*(nvirb-1)//2) c2bb = _unpack_4fold(c2bb, noccb, nvirb) return amplitudes_to_cisdvec(c0, (c1a,c1b), (c2aa,c2ab,c2bb))
def from_fcivec(ci0, norb, nelec, frozen=0): '''Extract CISD coefficients from FCI coefficients''' if frozen is not 0: raise NotImplementedError if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec norba = norbb = norb nocc = nocca, noccb = neleca, nelecb nvira = norba - nocca nvirb = norbb - noccb t1addra, t1signa = cisd.tn_addrs_signs(norba, nocca, 1) t1addrb, t1signb = cisd.tn_addrs_signs(norbb, noccb, 1) na = cistring.num_strings(norba, nocca) nb = cistring.num_strings(norbb, noccb) ci0 = ci0.reshape(na,nb) c0 = ci0[0,0] c1a = (ci0[t1addra,0] * t1signa).reshape(nocca,nvira) c1b = (ci0[0,t1addrb] * t1signb).reshape(noccb,nvirb) c2ab = numpy.einsum('i,j,ij->ij', t1signa, t1signb, ci0[t1addra[:,None],t1addrb]) c2ab = c2ab.reshape(nocca,nvira,noccb,nvirb).transpose(0,2,1,3) t2addra, t2signa = cisd.tn_addrs_signs(norba, nocca, 2) t2addrb, t2signb = cisd.tn_addrs_signs(norbb, noccb, 2) c2aa = (ci0[t2addra,0] * t2signa).reshape(nocca*(nocca-1)//2, nvira*(nvira-1)//2) c2aa = _unpack_4fold(c2aa, nocca, nvira) c2bb = (ci0[0,t2addrb] * t2signb).reshape(noccb*(noccb-1)//2, nvirb*(nvirb-1)//2) c2bb = _unpack_4fold(c2bb, noccb, nvirb) return amplitudes_to_cisdvec(c0, (c1a,c1b), (c2aa,c2ab,c2bb))
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 frozena_mask = numpy.zeros(norb, dtype=bool) frozenb_mask = numpy.zeros(norb, dtype=bool) if isinstance(frozen, (int, numpy.integer)): nfroza = nfrozb = frozen frozena_mask[:frozen] = True frozenb_mask[:frozen] = True else: nfroza = len(frozen[0]) nfrozb = len(frozen[1]) frozena_mask[frozen[0]] = True frozenb_mask[frozen[1]] = True # if nfroza != nfrozb: # raise NotImplementedError nocca = numpy.count_nonzero(~frozena_mask[:neleca]) noccb = numpy.count_nonzero(~frozenb_mask[:nelecb]) nmo = nmoa, nmob = norb - nfroza, norb - nfrozb nocc = nocca, noccb nvira, nvirb = nmoa - nocca, nmob - noccb c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc) c1a, c1b = c1 c2aa, c2ab, c2bb = c2 t1addra, t1signa = cisd.tn_addrs_signs(nmoa, nocca, 1) t1addrb, t1signb = cisd.tn_addrs_signs(nmob, noccb, 1) na = cistring.num_strings(nmoa, nocca) nb = cistring.num_strings(nmob, noccb) fcivec = numpy.zeros((na,nb)) fcivec[0,0] = c0 fcivec[t1addra,0] = c1a.ravel() * t1signa fcivec[0,t1addrb] = c1b.ravel() * t1signb c2ab = c2ab.transpose(0,2,1,3).reshape(nocca*nvira,-1) c2ab = numpy.einsum('i,j,ij->ij', t1signa, t1signb, c2ab) fcivec[t1addra[:,None],t1addrb] = c2ab if nocca > 1 and nvira > 1: ooidx = numpy.tril_indices(nocca, -1) vvidx = numpy.tril_indices(nvira, -1) c2aa = c2aa[ooidx][:,vvidx[0],vvidx[1]] t2addra, t2signa = cisd.tn_addrs_signs(nmoa, nocca, 2) fcivec[t2addra,0] = c2aa.ravel() * t2signa if noccb > 1 and nvirb > 1: ooidx = numpy.tril_indices(noccb, -1) vvidx = numpy.tril_indices(nvirb, -1) c2bb = c2bb[ooidx][:,vvidx[0],vvidx[1]] t2addrb, t2signb = cisd.tn_addrs_signs(nmob, noccb, 2) fcivec[0,t2addrb] = c2bb.ravel() * t2signb if nfroza == nfrozb == 0: return fcivec assert(norb < 63) strsa = cistring.gen_strings4orblist(range(norb), neleca) strsb = cistring.gen_strings4orblist(range(norb), nelecb) na = len(strsa) nb = len(strsb) count_a = numpy.zeros(na, dtype=int) count_b = numpy.zeros(nb, dtype=int) parity_a = numpy.zeros(na, dtype=bool) parity_b = numpy.zeros(nb, dtype=bool) core_a_mask = numpy.ones(na, dtype=bool) core_b_mask = numpy.ones(nb, dtype=bool) for i in range(norb): if frozena_mask[i]: if i < neleca: core_a_mask &= (strsa & (1<<i)) != 0 parity_a ^= (count_a & 1) == 1 else: core_a_mask &= (strsa & (1<<i)) == 0 else: count_a += (strsa & (1<<i)) != 0 if frozenb_mask[i]: if i < nelecb: core_b_mask &= (strsb & (1<<i)) != 0 parity_b ^= (count_b & 1) == 1 else: core_b_mask &= (strsb & (1<<i)) == 0 else: count_b += (strsb & (1<<i)) != 0 sub_strsa = strsa[core_a_mask & (count_a == nocca)] sub_strsb = strsb[core_b_mask & (count_b == noccb)] addrsa = cistring.strs2addr(norb, neleca, sub_strsa) addrsb = cistring.strs2addr(norb, nelecb, sub_strsb) fcivec1 = numpy.zeros((na,nb)) fcivec1[addrsa[:,None],addrsb] = fcivec fcivec1[parity_a,:] *= -1 fcivec1[:,parity_b] *= -1 return fcivec1
from pyscf.ci.cisd import tn_addrs_signs mol = gto.Mole() mol.atom = [ ['O', ( 0., 0. , 0. )], ['H', ( 0., -0.857, 0.587)], ['H', ( 0., 0.757 , 0.687)],] mol.basis = '321g' mol.build() mf = scf.RHF(mol).run() e, fcivec = fci.FCI(mf).kernel(verbose=5) nmo = mol.nao nocc = mol.nelectron // 2 t1addrs, t1signs = tn_addrs_signs(nmo, nocc, 1) t2addrs, t2signs = tn_addrs_signs(nmo, nocc, 2) t3addrs, t3signs = tn_addrs_signs(nmo, nocc, 3) t4addrs, t4signs = tn_addrs_signs(nmo, nocc, 4) # CIS includes two types of amplitudes: alpha -> alpha and beta -> beta cis_a = fcivec[t1addrs, 0] * t1signs cis_b = fcivec[0, t1addrs] * t1signs # CID has: # alpha,alpha -> alpha,alpha # alpha,beta -> alpha,beta # beta ,beta -> beta ,beta # For alpha,alpha -> alpha,alpha excitations, the redundant coefficients are # excluded. The number of coefficients is nocc*(nocc-1)//2 * nvir*(nvir-1)//2, # which corresponds to C2_{ijab}, i > j and a > b.
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 frozena_mask = numpy.zeros(norb, dtype=bool) frozenb_mask = numpy.zeros(norb, dtype=bool) if isinstance(frozen, (int, numpy.integer)): nfroza = nfrozb = frozen frozena_mask[:frozen] = True frozenb_mask[:frozen] = True else: nfroza = len(frozen[0]) nfrozb = len(frozen[1]) frozena_mask[frozen[0]] = True frozenb_mask[frozen[1]] = True # if nfroza != nfrozb: # raise NotImplementedError nocca = numpy.count_nonzero(~frozena_mask[:neleca]) noccb = numpy.count_nonzero(~frozenb_mask[:nelecb]) nmo = nmoa, nmob = norb - nfroza, norb - nfrozb nocc = nocca, noccb nvira, nvirb = nmoa - nocca, nmob - noccb c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc) c1a, c1b = c1 c2aa, c2ab, c2bb = c2 t1addra, t1signa = cisd.tn_addrs_signs(nmoa, nocca, 1) t1addrb, t1signb = cisd.tn_addrs_signs(nmob, noccb, 1) na = cistring.num_strings(nmoa, nocca) nb = cistring.num_strings(nmob, noccb) fcivec = numpy.zeros((na,nb)) fcivec[0,0] = c0 fcivec[t1addra,0] = c1a.ravel() * t1signa fcivec[0,t1addrb] = c1b.ravel() * t1signb c2ab = c2ab.transpose(0,2,1,3).reshape(nocca*nvira,-1) c2ab = numpy.einsum('i,j,ij->ij', t1signa, t1signb, c2ab) fcivec[t1addra[:,None],t1addrb] = c2ab if nocca > 1 and nvira > 1: ooidx = numpy.tril_indices(nocca, -1) vvidx = numpy.tril_indices(nvira, -1) c2aa = c2aa[ooidx][:,vvidx[0],vvidx[1]] t2addra, t2signa = cisd.tn_addrs_signs(nmoa, nocca, 2) fcivec[t2addra,0] = c2aa.ravel() * t2signa if noccb > 1 and nvirb > 1: ooidx = numpy.tril_indices(noccb, -1) vvidx = numpy.tril_indices(nvirb, -1) c2bb = c2bb[ooidx][:,vvidx[0],vvidx[1]] t2addrb, t2signb = cisd.tn_addrs_signs(nmob, noccb, 2) fcivec[0,t2addrb] = c2bb.ravel() * t2signb if nfroza == nfrozb == 0: return fcivec assert(norb < 63) strsa = cistring.gen_strings4orblist(range(norb), neleca) strsb = cistring.gen_strings4orblist(range(norb), nelecb) na = len(strsa) nb = len(strsb) count_a = numpy.zeros(na, dtype=int) count_b = numpy.zeros(nb, dtype=int) parity_a = numpy.zeros(na, dtype=bool) parity_b = numpy.zeros(nb, dtype=bool) core_a_mask = numpy.ones(na, dtype=bool) core_b_mask = numpy.ones(nb, dtype=bool) for i in range(norb): if frozena_mask[i]: if i < neleca: core_a_mask &= (strsa & (1<<i)) != 0 parity_a ^= (count_a & 1) == 1 else: core_a_mask &= (strsa & (1<<i)) == 0 else: count_a += (strsa & (1<<i)) != 0 if frozenb_mask[i]: if i < nelecb: core_b_mask &= (strsb & (1<<i)) != 0 parity_b ^= (count_b & 1) == 1 else: core_b_mask &= (strsb & (1<<i)) == 0 else: count_b += (strsb & (1<<i)) != 0 sub_strsa = strsa[core_a_mask & (count_a == nocca)] sub_strsb = strsb[core_b_mask & (count_b == noccb)] addrsa = cistring.strs2addr(norb, neleca, sub_strsa) addrsb = cistring.strs2addr(norb, nelecb, sub_strsb) fcivec1 = numpy.zeros((na,nb)) fcivec1[addrsa[:,None],addrsb] = fcivec fcivec1[parity_a,:] *= -1 fcivec1[:,parity_b] *= -1 return fcivec1