def make_hdiag(h1e, eri, norb, nelec): '''Diagonal Hamiltonian for Davidson preconditioner ''' if h1e.dtype == numpy.complex or eri.dtype == numpy.complex: raise NotImplementedError('Complex Hamiltonian') neleca, nelecb = _unpack_nelec(nelec) h1e = numpy.asarray(h1e, order='C') eri = ao2mo.restore(1, eri, norb) occslsta = occslstb = cistring._gen_occslst(range(norb), neleca) if neleca != nelecb: occslstb = cistring._gen_occslst(range(norb), nelecb) na = len(occslsta) nb = len(occslstb) 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), occslsta.ctypes.data_as(ctypes.c_void_p), occslstb.ctypes.data_as(ctypes.c_void_p)) return hdiag
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) occslsta = occslstb = cistring._gen_occslst(range(norb), neleca) if neleca != nelecb: occslstb = cistring._gen_occslst(range(norb), nelecb) na = len(occslsta) nb = len(occslstb) 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), occslsta.ctypes.data_as(ctypes.c_void_p), occslstb.ctypes.data_as(ctypes.c_void_p)) return numpy.asarray(hdiag)
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) occslsta = occslstb = cistring._gen_occslst(range(norb), neleca) if neleca != nelecb: occslstb = cistring._gen_occslst(range(norb), nelecb) na = len(occslsta) nb = len(occslstb) 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), occslsta.ctypes.data_as(ctypes.c_void_p), occslstb.ctypes.data_as(ctypes.c_void_p)) return 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 = cistring._gen_occslst(range(norb), neleca) occslistb = cistring._gen_occslst(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, eri, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec occslista = cistring._gen_occslst(range(norb), neleca) occslistb = cistring._gen_occslst(range(norb), nelecb) eri = ao2mo.restore(1, eri, norb) diagj = numpy.einsum('iijj->ij', eri) diagk = numpy.einsum('ijji->ij', eri) 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 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_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 cylindrical_init_guess(mol, norb, nelec, orbsym, wfnsym=0, singlet=True, nroots=1): ''' FCI initial guess for system of cylindrical symmetry. (In testing) Examples: >>> mol = gto.M(atom='O; O 1 1.2', spin=2, symmetry=True) >>> orbsym = [6,7,2,3] >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10)[0] >>> print(ci0.reshape(4,4)) >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10, singlet=False)[0] >>> print(ci0.reshape(4,4)) ''' neleca, nelecb = _unpack_nelec(nelec) if isinstance(orbsym[0], str): orbsym = [symm.irrep_name2id(mol.groupname, x) for x in orbsym] orbsym = numpy.asarray(orbsym) if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) if mol.groupname in ('Dooh', 'Coov'): def irrep_id2lz(irrep_id): # See also symm.basis.DOOH_IRREP_ID_TABLE level = irrep_id // 10 d2h_id = irrep_id % 10 # irrep_id 0,1,4,5 corresponds to lz = 0,2,4,... # irrep_id 2,3,6,7 corresponds to lz = 1,3,5,... lz = level * 2 + ((d2h_id == 2) | (d2h_id == 3) | (d2h_id == 6) | (d2h_id == 7)) if isinstance(irrep_id, (int, numpy.number)): # irrep_id 1,3,4,6 corresponds to E_y (E_{(-)}) # irrep_id 0,2,5,7 corresponds to E_x (E_{(+)}) if (d2h_id == 1) | (d2h_id == 3) | (d2h_id == 4) | (d2h_id == 6): lz = -lz else: lz[(d2h_id == 1) | (d2h_id == 3) | (d2h_id == 4) | (d2h_id == 6)] *= -1 return lz orb_lz = irrep_id2lz(orbsym) wfn_lz = irrep_id2lz(wfnsym) d2h_wfnsym_id = wfnsym % 10 else: raise NotImplementedError orb_lz = wfn_lz = d2h_wfnsym_id = None occslsta = occslstb = cistring._gen_occslst(range(norb), neleca) if neleca != nelecb: occslstb = cistring._gen_occslst(range(norb), nelecb) na = len(occslsta) nb = len(occslsta) gx_mask = orbsym == 2 gy_mask = orbsym == 3 ux_mask = orbsym == 7 uy_mask = orbsym == 6 all_lz = set(abs(orb_lz)) 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 ci0 = [] iroot = 0 for addr in range(na * nb): ci_1 = numpy.zeros((na, nb)) addra = addr // nb addrb = addr % nb occa = occslsta[addra] occb = occslstb[addrb] tot_sym = 0 for i in occa: tot_sym ^= orbsym[i] for i in occb: tot_sym ^= orbsym[i] if tot_sym == d2h_wfnsym_id: n_Ex_a = (gx_mask[occa]).sum() + (ux_mask[occa]).sum() n_Ey_a = (gy_mask[occa]).sum() + (uy_mask[occa]).sum() n_Ex_b = (gx_mask[occb]).sum() + (ux_mask[occb]).sum() n_Ey_b = (gy_mask[occb]).sum() + (uy_mask[occb]).sum() if abs(n_Ex_a - n_Ey_a) == 1 and abs(n_Ex_b - n_Ey_b) == 1: # open-shell for both alpha det and beta det e.g. the # valence part of O2 molecule addr_x_a, addr_y_a = search_open_shell_det(occa) addr_x_b, addr_y_b = search_open_shell_det(occb) if singlet: if wfn_lz == 0: ci_1[addr_x_a,addr_x_b] = \ ci_1[addr_y_a,addr_y_b] = numpy.sqrt(.5) else: ci_1[addr_x_a, addr_x_b] = numpy.sqrt(.5) ci_1[addr_y_a, addr_y_b] = -numpy.sqrt(.5) else: ci_1[addr_x_a, addr_y_b] = numpy.sqrt(.5) ci_1[addr_y_a, addr_x_b] = -numpy.sqrt(.5) else: # TODO: Other direct-product to direct-sum transofromation # which involves CG coefficients. ci_1[addra, addrb] = 1 ci0.append(ci_1.ravel()) iroot += 1 if iroot >= nroots: break return ci0
def cylindrical_init_guess(mol, norb, nelec, orbsym, wfnsym=0, singlet=True, nroots=1): ''' FCI initial guess for system of cylindrical symmetry. (In testing) Examples: >>> mol = gto.M(atom='O; O 1 1.2', spin=2, symmetry=True) >>> orbsym = [6,7,2,3] >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10)[0] >>> print(ci0.reshape(4,4)) >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10, singlet=False)[0] >>> print(ci0.reshape(4,4)) ''' neleca, nelecb = _unpack_nelec(nelec) if isinstance(orbsym[0], str): orbsym = [symm.irrep_name2id(mol.groupname, x) for x in orbsym] orbsym = numpy.asarray(orbsym) if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) if mol.groupname in ('Dooh', 'Coov'): def irrep_id2lz(irrep_id): # See also symm.basis.DOOH_IRREP_ID_TABLE level = irrep_id // 10 d2h_id = irrep_id % 10 # irrep_id 0,1,4,5 corresponds to lz = 0,2,4,... # irrep_id 2,3,6,7 corresponds to lz = 1,3,5,... lz = level * 2 + ((d2h_id==2) | (d2h_id==3) | (d2h_id==6) | (d2h_id==7)) if isinstance(irrep_id, (int, numpy.number)): # irrep_id 1,3,4,6 corresponds to E_y (E_{(-)}) # irrep_id 0,2,5,7 corresponds to E_x (E_{(+)}) if (d2h_id==1) | (d2h_id==3) | (d2h_id==4) | (d2h_id==6): lz = -lz else: lz[(d2h_id==1) | (d2h_id==3) | (d2h_id==4) | (d2h_id==6)] *= -1 return lz orb_lz = irrep_id2lz(orbsym) wfn_lz = irrep_id2lz(wfnsym) d2h_wfnsym_id = wfnsym % 10 else: raise NotImplementedError orb_lz = wfn_lz = d2h_wfnsym_id = None occslsta = occslstb = cistring._gen_occslst(range(norb), neleca) if neleca != nelecb: occslstb = cistring._gen_occslst(range(norb), nelecb) na = len(occslsta) nb = len(occslsta) gx_mask = orbsym == 2 gy_mask = orbsym == 3 ux_mask = orbsym == 7 uy_mask = orbsym == 6 all_lz = set(abs(orb_lz)) 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 ci0 = [] iroot = 0 for addr in range(na*nb): ci_1 = numpy.zeros((na,nb)) addra = addr // nb addrb = addr % nb occa = occslsta[addra] occb = occslstb[addrb] tot_sym = 0 for i in occa: tot_sym ^= orbsym[i] for i in occb: tot_sym ^= orbsym[i] if tot_sym == d2h_wfnsym_id: n_Ex_a = (gx_mask[occa]).sum() + (ux_mask[occa]).sum() n_Ey_a = (gy_mask[occa]).sum() + (uy_mask[occa]).sum() n_Ex_b = (gx_mask[occb]).sum() + (ux_mask[occb]).sum() n_Ey_b = (gy_mask[occb]).sum() + (uy_mask[occb]).sum() if abs(n_Ex_a - n_Ey_a) == 1 and abs(n_Ex_b - n_Ey_b) == 1: # open-shell for both alpha det and beta det e.g. the # valence part of O2 molecule addr_x_a, addr_y_a = search_open_shell_det(occa) addr_x_b, addr_y_b = search_open_shell_det(occb) if singlet: if wfn_lz == 0: ci_1[addr_x_a,addr_x_b] = \ ci_1[addr_y_a,addr_y_b] = numpy.sqrt(.5) else: ci_1[addr_x_a,addr_x_b] = numpy.sqrt(.5) ci_1[addr_y_a,addr_y_b] =-numpy.sqrt(.5) else: ci_1[addr_x_a,addr_y_b] = numpy.sqrt(.5) ci_1[addr_y_a,addr_x_b] =-numpy.sqrt(.5) else: # TODO: Other direct-product to direct-sum transofromation # which involves CG coefficients. ci_1[addra,addrb] = 1 ci0.append(ci_1.ravel()) iroot += 1 if iroot >= nroots: break return ci0