def get_irrep_nelec(mol, mo_coeff, mo_occ, s=None): '''Alpha/beta electron numbers for each irreducible representation. Args: mol : an instance of :class:`Mole` To provide irrep_id, and spin-adapted basis mo_occ : a list of 1D ndarray Regular occupancy, without grouping for irreps mo_coeff : a list of 2D ndarray Regular orbital coefficients, without grouping for irreps Returns: irrep_nelec : dict The number of alpha/beta electrons for each irrep {'ir_name':(int,int), ...}. Examples: >>> mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='ccpvdz', symmetry=True, charge=1, spin=1, verbose=0) >>> mf = scf.UHF(mol) >>> mf.scf() -75.623975516256721 >>> scf.uhf_symm.get_irrep_nelec(mol, mf.mo_coeff, mf.mo_occ) {'A1': (3, 3), 'A2': (0, 0), 'B1': (1, 1), 'B2': (1, 0)} ''' orbsyma = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff[0], s) orbsymb = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff[1], s) orbsyma = numpy.array(orbsyma) orbsymb = numpy.array(orbsymb) irrep_nelec = dict([(mol.irrep_name[k], (int(sum(mo_occ[0][orbsyma==ir])), int(sum(mo_occ[1][orbsymb==ir])))) for k, ir in enumerate(mol.irrep_id)]) return irrep_nelec
def get_grad(self, mo_coeff, mo_occ, fock=None): mol = self.mol if not mol.symmetry: return uhf.UHF.get_grad(self, mo_coeff, mo_occ, fock) if fock is None: dm1 = self.make_rdm1(mo_coeff, mo_occ) fock = self.get_hcore(mol) + self.get_veff(self.mol, dm1) ovlp_ao = self.get_ovlp() orbsyma = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff[0], ovlp_ao, False) orbsymb = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff[1], ovlp_ao, False) orbsyma = numpy.asarray(orbsyma) orbsymb = numpy.asarray(orbsymb) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb ga = reduce(numpy.dot, (mo_coeff[0][:,viridxa].T.conj(), fock[0], mo_coeff[0][:,occidxa])) ga[orbsyma[viridxa].reshape(-1,1)!=orbsyma[occidxa]] = 0 gb = reduce(numpy.dot, (mo_coeff[1][:,viridxb].T.conj(), fock[1], mo_coeff[1][:,occidxb])) gb[orbsymb[viridxb].reshape(-1,1)!=orbsymb[occidxb]] = 0 return numpy.hstack((ga.ravel(), gb.ravel()))
def gen_g_hop(self, mo_coeff, mo_occ, fock_ao=None, h1e=None): mol = self._scf.mol if mol.symmetry: ovlp_ao = self._scf.get_ovlp() self._orbsym =(symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff[0], s=ovlp_ao), symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff[1], s=ovlp_ao)) return gen_g_hop_uhf(self, mo_coeff, mo_occ, fock_ao, h1e)
def kernel(self, mo_coeff=None, ci0=None, macro=None, micro=None, callback=None, _kern=None): if mo_coeff is None: mo_coeff = self.mo_coeff else: self.mo_coeff = mo_coeff if macro is None: macro = self.max_cycle_macro if micro is None: micro = self.max_cycle_micro if callback is None: callback = self.callback if _kern is None: _kern = mc1step.kernel if self.verbose > logger.QUIET: pyscf.gto.mole.check_sanity(self, self._keys, self.stdout) self.mol.check_sanity(self) self.dump_flags() # irrep_name = self.mol.irrep_name irrep_name = self.mol.irrep_id try: self.orbsym = symm.label_orb_symm(self.mol, irrep_name, self.mol.symm_orb, mo_coeff, s=self._scf.get_ovlp()) except ValueError: logger.warn(self, "mc1step_symm symmetrizes input orbitals") s = self._scf.get_ovlp() mo_coeff = symm.symmetrize_orb(self.mol, mo_coeff, s=s) diag = numpy.einsum("ki,ki->i", mo_coeff, numpy.dot(s, mo_coeff)) mo_coeff = numpy.einsum("ki,i->ki", mo_coeff, 1 / numpy.sqrt(diag)) self.orbsym = symm.label_orb_symm(self.mol, irrep_name, self.mol.symm_orb, mo_coeff, s=s) if not hasattr(self.fcisolver, "orbsym") or not self.fcisolver.orbsym: ncore = self.ncore nocc = self.ncore + self.ncas self.fcisolver.orbsym = self.orbsym[ncore:nocc] logger.debug(self, "Active space irreps %s", str(self.fcisolver.orbsym)) self.converged, self.e_tot, e_cas, self.ci, self.mo_coeff = _kern( self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, macro=macro, micro=micro, ci0=ci0, callback=callback, verbose=self.verbose, ) logger.note(self, "CASSCF energy = %.15g", self.e_tot) return self.e_tot, e_cas, self.ci, self.mo_coeff
def test_kernel_symm(self): mol = gto.Mole() mol.verbose = 0 mol.output = None mol.atom = [ ['O', ( 0., 0. , 0. )], ['H', ( 0., -0.757, 0.587)], ['H', ( 0., 0.757 , 0.587)],] mol.basis = 'sto-3g' mol.symmetry = 1 mol.build() m = scf.RHF(mol).run() norb = m.mo_coeff.shape[1] nelec = mol.nelectron - 2 h1e = reduce(numpy.dot, (m.mo_coeff.T, scf.hf.get_hcore(mol), m.mo_coeff)) eri = ao2mo.incore.full(m._eri, m.mo_coeff) orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, m.mo_coeff) myci = selected_ci_symm.SCI().set(orbsym=orbsym, select_cutoff=.5e-3) e1, c1 = myci.kernel(h1e, eri, norb, nelec) myci = direct_spin1_symm.FCISolver().set(orbsym=orbsym) e2, c2 = myci.kernel(h1e, eri, norb, nelec) self.assertAlmostEqual(e1, e2, 6) c2_cut = selected_ci.from_fci(c2, c1._strs, norb, nelec) self.assertAlmostEqual(abs(numpy.dot(c1.ravel(), c2_cut.ravel())), 1, 6) myci = selected_ci_symm.SCI().set(orbsym=orbsym, select_cutoff=1e-5) e1, c1 = myci.kernel(h1e, eri, norb, nelec, ci0=c2_cut, wfnsym=0) self.assertAlmostEqual(e1, e2, 9) c2_cut = selected_ci.from_fci(c2, c1._strs, norb, nelec) self.assertAlmostEqual(abs(numpy.dot(c1.ravel(), c2_cut.ravel())), 1, 9)
def get_occ(self, mo_energy, mo_coeff=None): ''' We cannot assume default mo_energy value, because the orbital energies are sorted after doing SCF. But in this function, we need the orbital energies are grouped by symmetry irreps ''' mol = self.mol nirrep = len(mol.symm_orb) if mo_coeff is not None: orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) else: orbsym = [numpy.repeat(ir, mol.symm_orb[i].shape[1]) for i, ir in enumerate(mol.irrep_id)] orbsym = numpy.hstack(orbsym) mo_occ = numpy.zeros_like(mo_energy) mo_e_left = [] idx_e_left = [] nelec_fix = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = numpy.where(orbsym == ir)[0] if irname in self.irrep_nelec: n = self.irrep_nelec[irname] e_idx = numpy.argsort(mo_energy[ir_idx]) mo_occ[ir_idx[e_idx[:n//2]]] = 2 nelec_fix += n else: idx_e_left.append(ir_idx) nelec_float = mol.nelectron - nelec_fix assert(nelec_float >= 0) if nelec_float > 0: idx_e_left = numpy.hstack(idx_e_left) mo_e_left = mo_energy[idx_e_left] mo_e_sort = numpy.argsort(mo_e_left) occ_idx = idx_e_left[mo_e_sort[:(nelec_float//2)]] mo_occ[occ_idx] = 2 viridx = (mo_occ==0) if self.verbose < logger.INFO or viridx.sum() == 0: return mo_occ ehomo = max(mo_energy[mo_occ>0 ]) elumo = min(mo_energy[mo_occ==0]) noccs = [] for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = (orbsym == ir) noccs.append(int(mo_occ[ir_idx].sum())) if ehomo in mo_energy[ir_idx]: irhomo = irname if elumo in mo_energy[ir_idx]: irlumo = irname logger.info(self, 'H**O (%s) = %.15g LUMO (%s) = %.15g', irhomo, ehomo, irlumo, elumo) if self.verbose >= logger.DEBUG: logger.debug(self, 'irrep_nelec = %s', noccs) _dump_mo_energy(mol, mo_energy, mo_occ, ehomo, elumo, orbsym) return mo_occ
def get_irrep_nelec(mol, mo_coeff, mo_occ, s=None): '''Electron numbers for each irreducible representation. Args: mol : an instance of :class:`Mole` To provide irrep_id, and spin-adapted basis mo_coeff : 2D ndarray Regular orbital coefficients, without grouping for irreps mo_occ : 1D ndarray Regular occupancy, without grouping for irreps Returns: irrep_nelec : dict The number of electrons for each irrep {'ir_name':int,...}. Examples: >>> mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='ccpvdz', symmetry=True, verbose=0) >>> mf = scf.RHF(mol) >>> mf.scf() -76.016789472074251 >>> scf.hf_symm.get_irrep_nelec(mol, mf.mo_coeff, mf.mo_occ) {'A1': 6, 'A2': 0, 'B1': 2, 'B2': 2} ''' orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s) orbsym = numpy.array(orbsym) irrep_nelec = dict([(mol.irrep_name[k], int(sum(mo_occ[orbsym==ir]))) for k, ir in enumerate(mol.irrep_id)]) return irrep_nelec
def get_grad(self, mo_coeff, mo_occ, fock=None): mol = self.mol if not self.mol.symmetry: return rohf.ROHF.get_grad(self, mo_coeff, mo_occ, fock) if fock is None: dm1 = self.make_rdm1(mo_coeff, mo_occ) fock = self.get_hcore(mol) + self.get_veff(self.mol, dm1) orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) sym_allow = orbsym.reshape(-1,1) == orbsym occidxa = mo_occ > 0 occidxb = mo_occ == 2 viridxa = ~occidxa viridxb = ~occidxb focka = reduce(numpy.dot, (mo_coeff.T, fock[0], mo_coeff)) fockb = reduce(numpy.dot, (mo_coeff.T, fock[1], mo_coeff)) uniq_var_a = viridxa.reshape(-1,1) & occidxa uniq_var_b = viridxb.reshape(-1,1) & occidxb g = numpy.zeros_like(focka) g[uniq_var_a] = focka[uniq_var_a] g[uniq_var_b] += fockb[uniq_var_b] g[~sym_allow] = 0 return g[uniq_var_a | uniq_var_b].ravel()
def from_chkfile(filename, chkfile, tol=TOL, float_format=DEFAULT_FLOAT_FORMAT): '''Read SCF results from PySCF chkfile and transform 1-electron, 2-electron integrals using the SCF orbitals. The transformed integrals is written to FCIDUMP''' from pyscf import scf, symm with open(filename, 'w') as fout: mol, scf_rec = scf.chkfile.load_scf(chkfile) mo_coeff = numpy.array(scf_rec['mo_coeff']) nmo = mo_coeff.shape[1] if mol.symmetry: orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, check=False) write_head(fout, nmo, mol.nelectron, mol.spin, orbsym) else: write_head(fout, nmo, mol.nelectron, mol.spin) eri = ao2mo.full(mol, mo_coeff, verbose=0) write_eri(fout, ao2mo.restore(8, eri, nmo), nmo, tol, float_format) t = mol.intor_symmetric('int1e_kin') v = mol.intor_symmetric('int1e_nuc') h = reduce(numpy.dot, (mo_coeff.T, t+v, mo_coeff)) write_hcore(fout, h, nmo, tol, float_format) output_format = ' ' + float_format + ' 0 0 0 0\n' fout.write(output_format % mol.energy_nuc())
def orbital_coeff(mol, fout, mo_coeff, spin='Alpha', symm=None, ene=None, occ=None, ignore_h=False): from pyscf.symm import label_orb_symm if ignore_h: mol, mo_coeff = remove_high_l(mol, mo_coeff) aoidx = order_ao_index(mol) nmo = mo_coeff.shape[1] if symm is None: symm = ['A']*nmo if mol.symmetry: try: symm = label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo_coeff, tol=1e-5) except ValueError as e: logger.warn(mol, str(e)) if ene is None: ene = numpy.arange(nmo) assert(spin == 'Alpha' or spin == 'Beta') if occ is None: occ = numpy.zeros(nmo) neleca, nelecb = mol.nelec if spin == 'Alpha': occ[:neleca] = 1 else: occ[:nelecb] = 1 fout.write('[MO]\n') for imo in range(nmo): fout.write(' Sym= %s\n' % symm[imo]) fout.write(' Ene= %15.10g\n' % ene[imo]) fout.write(' Spin= %s\n' % spin) fout.write(' Occup= %10.5f\n' % occ[imo]) for i,j in enumerate(aoidx): fout.write(' %3d %18.14g\n' % (i+1, mo_coeff[j,imo]))
def gen_g_hop(self, mo_coeff, mo_occ, fock_ao=None, h1e=None): mol = self._scf.mol if mol.symmetry: # label the symmetry every time calling gen_g_hop because kernel function may # change mo_coeff ordering after calling self.eig self._orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s=self._scf.get_ovlp()) return gen_g_hop_rohf(self, mo_coeff, mo_occ, fock_ao, h1e)
def test_symmetrize_space(self): from pyscf import gto, symm, scf mol = gto.M(atom = 'C 0 0 0; H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1', basis = 'sto3g', verbose=0) mf = scf.RHF(mol).run() mol.build(0, 0, symmetry='D2') mo = symm.symmetrize_space(mol, mf.mo_coeff) irreps = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo) self.assertEqual(irreps, ['A','A','A','B1','B1','B2','B2','B3','B3'])
def analyze(self, verbose=logger.DEBUG): from pyscf.tools import dump_mat mo_energy = self.mo_energy mo_occ = self.mo_occ mo_coeff = self.mo_coeff log = logger.Logger(self.stdout, verbose) mol = self.mol nirrep = len(mol.irrep_id) ovlp_ao = self.get_ovlp() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s=ovlp_ao) orbsym = numpy.array(orbsym) wfnsym = 0 ndoccs = [] nsoccs = [] for k,ir in enumerate(mol.irrep_id): ndoccs.append(sum(orbsym[mo_occ==2] == ir)) nsoccs.append(sum(orbsym[mo_occ==1] == ir)) if nsoccs[k] % 2: wfnsym ^= ir if mol.groupname in ('Dooh', 'Coov'): log.info('TODO: total symmetry for %s', mol.groupname) else: log.info('total symmetry = %s', symm.irrep_id2name(mol.groupname, wfnsym)) log.info('occupancy for each irrep: ' + (' %4s'*nirrep), *mol.irrep_name) log.info('double occ ' + (' %4d'*nirrep), *ndoccs) log.info('single occ ' + (' %4d'*nirrep), *nsoccs) log.info('**** MO energy ****') irname_full = {} for k,ir in enumerate(mol.irrep_id): irname_full[ir] = mol.irrep_name[k] irorbcnt = {} for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.info('MO #%d (%s #%d), energy= %.15g occ= %g', k+1, irname_full[j], irorbcnt[j], mo_energy[k], mo_occ[k]) if verbose >= logger.DEBUG: label = mol.spheric_labels(True) molabel = [] irorbcnt = {} for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 molabel.append('#%-d(%s #%d)' % (k+1, irname_full[j], irorbcnt[j])) log.debug(' ** MO coefficients **') dump_mat.dump_rec(mol.stdout, mo_coeff, label, molabel, start=1) dm = self.make_rdm1(mo_coeff, mo_occ) return self.mulliken_meta(mol, dm, s=ovlp_ao, verbose=verbose)
def __init__(self): self.__dict__.update(cis.__dict__) self.h1e = reduce(numpy.dot, (mo.T, scf.hf.get_hcore(mol), mo)) self.eri = ao2mo.outcore.full_iofree(mol, mo) self.eci = None self.ci = None if mol.symmetry: self.orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo) self._keys = set(self.__dict__.keys())
def analyze(mf, verbose=logger.DEBUG, **kwargs): '''Analyze the given SCF object: print orbital energies, occupancies; print orbital coefficients; Occupancy for each irreps; Mulliken population analysis ''' from pyscf.lo import orth from pyscf.tools import dump_mat mol = mf.mol if not mol.symmetry: return hf.analyze(mf, verbose, **kwargs) mo_energy = mf.mo_energy mo_occ = mf.mo_occ mo_coeff = mf.mo_coeff log = logger.Logger(mf.stdout, verbose) nirrep = len(mol.irrep_id) ovlp_ao = mf.get_ovlp() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s=ovlp_ao, check=False) orbsym = numpy.array(orbsym) wfnsym = 0 noccs = [sum(orbsym[mo_occ>0]==ir) for ir in mol.irrep_id] log.note('total symmetry = %s', symm.irrep_id2name(mol.groupname, wfnsym)) log.note('occupancy for each irrep: ' + (' %4s'*nirrep), *mol.irrep_name) log.note('double occ ' + (' %4d'*nirrep), *noccs) log.note('**** MO energy ****') irname_full = {} for k,ir in enumerate(mol.irrep_id): irname_full[ir] = mol.irrep_name[k] irorbcnt = {} for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note('MO #%d (%s #%d), energy= %.15g occ= %g', k+1, irname_full[j], irorbcnt[j], mo_energy[k], mo_occ[k]) if verbose >= logger.DEBUG: label = mol.spheric_labels(True) molabel = [] irorbcnt = {} for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 molabel.append('#%-d(%s #%d)' % (k+1, irname_full[j], irorbcnt[j])) log.debug(' ** MO coefficients (expansion on meta-Lowdin AOs) **') orth_coeff = orth.orth_ao(mol, 'meta_lowdin', s=ovlp_ao) c = reduce(numpy.dot, (orth_coeff.T, ovlp_ao, mo_coeff)) dump_mat.dump_rec(mf.stdout, c, label, molabel, start=1, **kwargs) dm = mf.make_rdm1(mo_coeff, mo_occ) return mf.mulliken_meta(mol, dm, s=ovlp_ao, verbose=log)
def label_symmetry_(mc, mo_coeff): #irrep_name = mc.mol.irrep_name irrep_name = mc.mol.irrep_id s = mc._scf.get_ovlp() try: mc.orbsym = symm.label_orb_symm(mc.mol, irrep_name, mc.mol.symm_orb, mo_coeff, s=s) except ValueError: logger.warn(mc, 'mc1step_symm symmetrizes input orbitals') ncore = mc.ncore nocc = mc.ncore + mc.ncas mo_cor = symm.symmetrize_space(mc.mol, mo_coeff[:, :ncore], s=s) mo_act = symm.symmetrize_space(mc.mol, mo_coeff[:,ncore:nocc], s=s) mo_vir = symm.symmetrize_space(mc.mol, mo_coeff[:,nocc: ], s=s) mo_coeff = numpy.hstack((mo_cor,mo_act,mo_vir)) mc.orbsym = symm.label_orb_symm(mc.mol, irrep_name, mc.mol.symm_orb, mo_coeff, s=s) if not hasattr(mc.fcisolver, 'orbsym') or not mc.fcisolver.orbsym: ncore = mc.ncore nocc = mc.ncore + mc.ncas mc.fcisolver.orbsym = mc.orbsym[ncore:nocc] logger.debug(mc, 'Active space irreps %s', str(mc.fcisolver.orbsym))
def get_grad(self, mo_coeff, mo_occ, fock=None): mol = self.mol if fock is None: dm1 = self.make_rdm1(mo_coeff, mo_occ) fock = self.get_hcore(mol) + self.get_veff(self.mol, dm1) orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) occidx = mo_occ > 0 viridx = ~occidx g = reduce(numpy.dot, (mo_coeff[:,viridx].T.conj(), fock, mo_coeff[:,occidx])) * 2 sym_allow = orbsym[viridx].reshape(-1,1) == orbsym[occidx] g[~sym_allow] = 0 return g.ravel()
def write_integrals(xci, orb): mol = xci.mol orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, orb) h1e = reduce(numpy.dot, (orb.T, xci.get_hcore(), orb)) norb = orb.shape[1] if xci._eri is not None: h2e = ao2mo.restore(1, ao2mo.full(xci._eri, orb), norb) else: h2e = ao2mo.restore(1, ao2mo.full(mol, orb), norb) with h5py.File(xci.integralfile, 'w') as f: f['h1e'] = h1e f['h2e'] = h2e f['norb' ] = numpy.array(norb, dtype=numpy.int32) f['group' ] = mol.groupname f['orbsym'] = numpy.asarray(orbsym, dtype=numpy.int32) f['ecore' ] = mol.energy_nuc()
def get_orbsym(mol, mo_coeff, s=None, check=False): if mo_coeff is None: orbsym = numpy.hstack([[ir] * mol.symm_orb[i].shape[1] for i, ir in enumerate(mol.irrep_id)]) elif getattr(mo_coeff, 'orbsym', None) is not None: orbsym = mo_coeff.orbsym else: nao = mo_coeff.shape[0] // 2 if isinstance(s, numpy.ndarray): assert(s.size == nao**2 or numpy.allclose(s[:nao,:nao], s[nao:,nao:])) s = s[:nao,:nao] mo_a = mo_coeff[:nao].copy() mo_b = mo_coeff[nao:] zero_alpha_idx = numpy.linalg.norm(mo_a, axis=0) < 1e-7 mo_a[:,zero_alpha_idx] = mo_b[:,zero_alpha_idx] orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_a, s, check) return numpy.asarray(orbsym)
def generate_hamiltonian(): ### PYSCF INPUT r0 = 1.50 molecule = ''' Cr Cr 1 {} '''.format(r0) charge = 0 spin = 0 basis_set = 'def2-svp' ### TPSCI BASIS INPUT orb_basis = 'scf' cas = True cas_nstart = 12 cas_nstop = 42 loc_start = 1 loc_stop = 6 cas_nel = 24 def ordering_diatomics_cr(mol,C): # {{{ ##DZ basis diatomics reordering with frozen 1s orb_type = ['s','pz','dz','px','dxz','py','dyz','dx2-y2','dxy'] ref = np.zeros(C.shape[1]) ## Find dimension of each space dim_orb = [] for orb in orb_type: print("Orb type",orb) idx = 0 for label in mol.ao_labels(): if orb in label: #print(label) idx += 1 ##frozen 1s orbitals if orb == 's': idx -= 6 elif orb == 'px': idx -=2 elif orb == 'py': idx -=2 elif orb == 'pz': idx -=2 dim_orb.append(idx) print(idx) new_idx = [] ## Find orbitals corresponding to each orb space for i,orb in enumerate(orb_type): print("Orbital type:",orb) from pyscf import mo_mapping s_pop = mo_mapping.mo_comps(orb, mol, C) print(s_pop) ref += s_pop cas_list = s_pop.argsort()[-dim_orb[i]:] print('cas_list', np.array(cas_list)) new_idx.extend(cas_list) #print(orb,' population for active space orbitals', s_pop[cas_list]) ao_labels = mol.ao_labels() #idx = mol.search_ao_label(['N.*s']) #for i in idx: # print(i, ao_labels[i]) print(ref) print(new_idx) for label in mol.ao_labels(): print(label) return new_idx # }}} # basis is SVP read comments by alex thom paper DOI:10.1021/acs.jctc.9b01023 from pyscf import gto basis_set={'Cr': gto.parse(''' BASIS "ao basis" PRINT #BASIS SET: (14s,8p,5d) -> [5s,2p,2d] Cr S 51528.086349 0.14405823106E-02 7737.2103487 0.11036202287E-01 1760.3748470 0.54676651806E-01 496.87706544 0.18965038103 161.46520598 0.38295412850 55.466352268 0.29090050668 Cr S 107.54732999 -0.10932281100 12.408671897 0.64472599471 5.0423628826 0.46262712560 Cr S 8.5461640165 -0.22711013286 1.3900441221 0.73301527591 0.56066602876 0.44225565433 Cr S 0.71483705972E-01 1.0000000000 Cr S 0.28250687604E-01 1.0000000000 Cr P 640.48536096 0.96126715203E-02 150.69711194 0.70889834655E-01 47.503755296 0.27065258990 16.934120165 0.52437343414 6.2409680590 0.34107994714 Cr P 3.0885463206 0.33973986903 1.1791047769 0.57272062927 0.43369774432 0.24582728206 Cr D 27.559479426 0.30612488044E-01 7.4687020327 0.15593270944 2.4345903574 0.36984421276 0.78244754808 0.47071118077 Cr D 0.21995774311 0.33941649889 END''')} ### TPSCI CLUSTER INPUT init_fspace = ((1, 1),(3, 3),(3, 3),(3, 3), (1, 1), (1, 1)) blocks = [range(0,4),range(4,10),range(10,16),range(16,22),range(22,26),range(26,30)] # Integrals from pyscf #Integrals from pyscf pmol = PyscfHelper() pmol.init(molecule,charge,spin,basis_set,orb_basis, cas_nstart=cas_nstart,cas_nstop=cas_nstop,cas_nel=cas_nel,cas=True, loc_nstart=loc_start,loc_nstop = loc_stop) h = pmol.h g = pmol.g ecore = pmol.ecore print("Ecore:%16.8f"%ecore) C = pmol.C K = pmol.K mol = pmol.mol mo_energy = pmol.mf.mo_energy dm_aa = pmol.dm_aa dm_bb = pmol.dm_bb do_fci = 0 do_hci = 0 do_tci = 1 if do_fci: efci, fci_dim = run_fci_pyscf(h,g,nelec,ecore=ecore) if do_hci: ehci, hci_dim = run_hci_pyscf(h,g,nelec,ecore=ecore,select_cutoff=5e-4,ci_cutoff=5e-4) #cluster using hcore idx = ordering_diatomics_cr(mol,C) h,g = reorder_integrals(idx,h,g) C = C[:,idx] mo_energy = mo_energy[idx] dm_aa = dm_aa[:,idx] dm_aa = dm_aa[idx,:] dm_bb = dm_bb[:,idx] dm_bb = dm_bb[idx,:] print(dm_aa) from pyscf import molden molden.from_mo(pmol.mol, 'h8.molden', C) print(h) mol = pmol.mol if mol.symmetry == True: from pyscf import symm mo = symm.symmetrize_orb(mol, C) osym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo) #symm.addons.symmetrize_space(mol, mo, s=None, check=True, tol=1e-07) for i in range(len(osym)): print("%4d %8s %16.8f"%(i+1,osym[i],mo_energy[i])) clusters = [] for ci,c in enumerate(blocks): clusters.append(Cluster(ci,c)) print(" Clusters:") [print(ci) for ci in clusters] clustered_ham = ClusteredOperator(clusters, core_energy=ecore) print(" Add 1-body terms") clustered_ham.add_local_terms() clustered_ham.add_1b_terms(h) print(" Add 2-body terms") clustered_ham.add_2b_terms(g) # intial state ci_vector = ClusteredState(clusters) ci_vector.init(init_fspace) ci_vector.print() # do cmf do_cmf = 1 if do_cmf: # Get CMF reference e_cmf, cmf_conv, rdm_a, rdm_b = cmf(clustered_ham, ci_vector, h, g, max_iter=10, dm_guess=(dm_aa, dm_bb), diis=True) print(" Final CMF Total Energy %12.8f" %(e_cmf + ecore)) # build cluster basis and operator matrices using CMF optimized density matrices for ci_idx, ci in enumerate(clusters): print(ci) fspaces_i = init_fspace[ci_idx] delta_e = 2 fspaces_i = ci.possible_fockspaces( delta_elec=(fspaces_i[0], fspaces_i[1], delta_e) ) print() print(" Form basis by diagonalizing local Hamiltonian for cluster: ",ci_idx) ci.form_fockspace_eigbasis(h, g, fspaces_i, max_roots=100, rdm1_a=rdm_a, rdm1_b=rdm_b) print(" Build mats for cluster ",ci.idx) ci.build_op_matrices() ci.build_local_terms(h,g) hamiltonian_file = open('hamiltonian_file', 'wb') pickle.dump(clustered_ham, hamiltonian_file) print(" Done.")
def get_occ(self, mo_energy=None, mo_coeff=None, orbsym=None): if mo_energy is None: mo_energy = self.mo_energy mol = self.mol if not self.mol.symmetry: return rohf.ROHF.get_occ(self, mo_energy, mo_coeff) if mo_coeff is None or self._focka_ao is None: mo_ea = mo_eb = mo_energy else: mo_ea = numpy.einsum('ik,ik->k', mo_coeff, self._focka_ao.dot(mo_coeff)) mo_eb = numpy.einsum('ik,ik->k', mo_coeff, self._fockb_ao.dot(mo_coeff)) nmo = mo_ea.size mo_occ = numpy.zeros(nmo) if orbsym is None: if mo_coeff is not None: orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) else: orbsym = [ numpy.repeat(ir, mol.symm_orb[i].shape[1]) for i, ir in enumerate(mol.irrep_id) ] orbsym = numpy.hstack(orbsym) else: orbsym = numpy.asarray(orbsym) assert (mo_energy.size == orbsym.size) float_idx = [] neleca_fix = 0 nelecb_fix = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = numpy.where(orbsym == ir)[0] if irname in self.irrep_nelec: if isinstance(self.irrep_nelec[irname], (int, numpy.integer)): nelecb = self.irrep_nelec[irname] // 2 neleca = self.irrep_nelec[irname] - nelecb else: neleca, nelecb = self.irrep_nelec[irname] mo_occ[ir_idx] = rohf._fill_rohf_occ(mo_energy[ir_idx], mo_ea[ir_idx], mo_eb[ir_idx], nelecb, neleca - nelecb) neleca_fix += neleca nelecb_fix += nelecb else: float_idx.append(ir_idx) nelec_float = mol.nelectron - neleca_fix - nelecb_fix assert (nelec_float >= 0) if len(float_idx) > 0: float_idx = numpy.hstack(float_idx) nopen = mol.spin - (neleca_fix - nelecb_fix) ncore = (nelec_float - nopen) // 2 mo_occ[float_idx] = rohf._fill_rohf_occ(mo_energy[float_idx], mo_ea[float_idx], mo_eb[float_idx], ncore, nopen) ncore = self.nelec[1] nocc = self.nelec[0] nopen = nocc - ncore vir_idx = (mo_occ == 0) if self.verbose >= logger.INFO and nocc < nmo and ncore > 0: ehomo = max(mo_energy[mo_occ > 0]) elumo = min(mo_energy[mo_occ == 0]) ndoccs = [] nsoccs = [] for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = (orbsym == ir) ndoccs.append(numpy.count_nonzero(mo_occ[ir_idx] == 2)) nsoccs.append(numpy.count_nonzero(mo_occ[ir_idx] == 1)) if ehomo in mo_energy[ir_idx]: irhomo = irname if elumo in mo_energy[ir_idx]: irlumo = irname # to help self.eigh compute orbital energy self._irrep_doccs = ndoccs self._irrep_soccs = nsoccs logger.info(self, 'H**O (%s) = %.15g LUMO (%s) = %.15g', irhomo, ehomo, irlumo, elumo) logger.debug(self, 'double occ irrep_nelec = %s', ndoccs) logger.debug(self, 'single occ irrep_nelec = %s', nsoccs) #_dump_mo_energy(mol, mo_energy, mo_occ, ehomo, elumo, orbsym, # verbose=self.verbose) if nopen > 0: core_idx = mo_occ == 2 open_idx = mo_occ == 1 vir_idx = mo_occ == 0 logger.debug( self, ' Roothaan | alpha | beta' ) logger.debug(self, ' Highest 2-occ = %18.15g | %18.15g | %18.15g', max(mo_energy[core_idx]), max(mo_ea[core_idx]), max(mo_eb[core_idx])) logger.debug(self, ' Lowest 0-occ = %18.15g | %18.15g | %18.15g', min(mo_energy[vir_idx]), min(mo_ea[vir_idx]), min(mo_eb[vir_idx])) for i in numpy.where(open_idx)[0]: logger.debug( self, ' 1-occ = %18.15g | %18.15g | %18.15g', mo_energy[i], mo_ea[i], mo_eb[i]) numpy.set_printoptions(threshold=nmo) logger.debug(self, ' Roothaan mo_energy =\n%s', mo_energy) logger.debug1(self, ' alpha mo_energy =\n%s', mo_ea) logger.debug1(self, ' beta mo_energy =\n%s', mo_eb) numpy.set_printoptions(threshold=1000) return mo_occ
def writeNevpt2Integrals(mc, dm1, dm2, dm1eff, aaavsplit, frozen): eris = _ERIS(mc, mc.mo_coeff) nocc = mc.ncore + mc.ncas ncore = mc.ncore nact = mc.ncas norbs = eris['ppaa'].shape[0] nvirt = norbs - ncore - nact eris_sp = {} #eris_sp['cvcv']= numpy.zeros(shape=(1,1)) #numpy.zeros(shape=(mc.ncore, norbs-mc.ncore-mc.ncas, mc.ncore, norbs-mc.ncas-mc.ncore)) eris_sp['h1eff'] = 1. * eris['h1eff'] #numpy.zeros(shape=(norbs, norbs)) int1 = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_hcore(), mc.mo_coeff)) #eris_sp['h1eff'] = makeheff(int1, eris['papa'], eris['ppaa'], dm1, ncore, nvirt) eris_sp['h1eff'][:mc.ncore, :mc.ncore] += numpy.einsum( 'abcd,cd', eris['ppaa'][:mc.ncore, :mc.ncore, :, :], dm1eff) eris_sp['h1eff'][:mc.ncore, :mc.ncore] -= numpy.einsum( 'abcd,bd', eris['papa'][:mc.ncore, :, :mc.ncore, :], dm1eff) * 0.5 eris_sp['h1eff'][mc.ncas + mc.ncore:, mc.ncas + mc.ncore:] += numpy.einsum( 'abcd,cd', eris['ppaa'][mc.ncas + mc.ncore:, mc.ncas + mc.ncore:, :, :], dm1eff) eris_sp['h1eff'][mc.ncas + mc.ncore:, mc.ncas + mc.ncore:] -= numpy.einsum( 'abcd,bd', eris['papa'][mc.ncas + mc.ncore:, :, mc.ncas + mc.ncore:, :], dm1eff) * 0.5 offdiagonal = 0.0 #zero out off diagonal core for k in range(mc.ncore): for l in range(mc.ncore): if (k != l): offdiagonal = max(abs(offdiagonal), abs(eris_sp['h1eff'][k, l])) #zero out off diagonal virtuals for k in range(mc.ncore + mc.ncas, norbs): for l in range(mc.ncore + mc.ncas, norbs): if (k != l): offdiagonal = max(abs(offdiagonal), abs(eris_sp['h1eff'][k, l])) if (abs(offdiagonal) > 1e-6): print "WARNING ***** Have to use natorual orbitals from casscf ****" print "offdiagonal elements ", offdiagonal eriscvcv = eris['cvcv'] if (not isinstance(eris['cvcv'], type(eris_sp['h1eff']))): #eriscvcv = h5py.File(eris['cvcv'].name,'r')["eri_mo"] eriscvcv = lib.chkfile.load( eris['cvcv'].name, "eri_mo") #h5py.File(eris['cvcv'].name,'r')["eri_mo"] eris_sp['cvcv'] = eriscvcv.reshape(mc.ncore, norbs - mc.ncore - mc.ncas, mc.ncore, norbs - mc.ncore - mc.ncas) import os os.system("mkdir int") numpy.save( "int/W:caac", numpy.asfortranarray(eris['papa'][frozen:mc.ncore, :, frozen:mc.ncore, :].transpose( 0, 3, 1, 2))) numpy.save( "int/W:aeca", numpy.asfortranarray(eris['papa'][frozen:mc.ncore, :, mc.ncore + mc.ncas:, :].transpose( 1, 2, 0, 3))) numpy.save( "int/W:ccaa", numpy.asfortranarray(eris['papa'][frozen:mc.ncore, :, frozen:mc.ncore, :].transpose( 0, 2, 1, 3))) numpy.save( "int/W:eeaa", numpy.asfortranarray(eris['papa'][mc.ncore + mc.ncas:, :, mc.ncore + mc.ncas:, :].transpose( 0, 2, 1, 3))) numpy.save( "int/W:caca", numpy.asfortranarray(eris['ppaa'][frozen:mc.ncore, frozen:mc.ncore, :, :].transpose( 0, 2, 1, 3))) numpy.save( "int/W:eaca", numpy.asfortranarray(eris['ppaa'][mc.ncore + mc.ncas:, frozen:mc.ncore, :, :].transpose( 0, 2, 1, 3))) numpy.save( "int/W:eecc", numpy.asfortranarray(eris_sp['cvcv'][frozen:, :, frozen:, :].transpose(1, 3, 0, 2))) numpy.save( "int/W:ccae", numpy.asfortranarray(eris['pacv'][frozen:mc.ncore, :, frozen:, :].transpose(0, 2, 1, 3))) numpy.save( "int/W:aaaa", numpy.asfortranarray(eris['ppaa'][mc.ncore:mc.ncore + mc.ncas, mc.ncore:mc.ncore + mc.ncas, :, :].transpose(0, 2, 1, 3))) numpy.save( "int/W:eeca", numpy.asfortranarray(eris['pacv'][mc.ncore + mc.ncas:, :, frozen:, :].transpose(3, 0, 2, 1))) numpy.save("int/int1eff", numpy.asfortranarray(eris_sp['h1eff'][frozen:, frozen:])) numpy.save("int/E1.npy", numpy.asfortranarray(dm1)) numpy.save("int/E2.npy", numpy.asfortranarray(dm2)) #numpy.save("int/E3",dm3) #numpy.save("int/E3B.npy", dm3.transpose(0,3,1,4,2,5)) #numpy.save("int/E3C.npy", dm3.transpose(5,0,2,4,1,3)) nc = mc.ncore + mc.ncas energyE0 = 1.0 * numpy.einsum('ij,ij', eris_sp['h1eff'][ncore:nc, ncore:nc], dm1) energyE0 += 0.5 * numpy.einsum( 'ijkl,ijkl', eris['ppaa'][mc.ncore:mc.ncore + mc.ncas, mc.ncore:mc.ncore + mc.ncas, :, :].transpose( 0, 2, 1, 3), dm2) mo = mc.mo_coeff dmcore = numpy.dot(mo[:, :ncore], mo[:, :ncore].T) * 2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj - vk * 0.5, mo)) energyE0 += numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 energyE0 += mc.mol.energy_nuc() print "Energy = ", energyE0 from pyscf import symm mol = mc.mol orbsymout = [] orbsym = [] if (mol.symmetry): orbsym = symm.label_orb_symm(mc.mol, mc.mol.irrep_id, mc.mol.symm_orb, mc.mo_coeff, s=mc._scf.get_ovlp()) if mol.symmetry and orbsym: if mol.groupname.lower() == 'dooh': orbsymout = [dmrg_sym.IRREP_MAP['D2h'][i % 10] for i in orbsym] elif mol.groupname.lower() == 'coov': orbsymout = [dmrg_sym.IRREP_MAP['C2v'][i % 10] for i in orbsym] else: orbsymout = [dmrg_sym.IRREP_MAP[mol.groupname][i] for i in orbsym] else: orbsymout = [] ncore = mc.ncore mo = mc.mo_coeff dmcore = numpy.dot(mo[:, :ncore], mo[:, :ncore].T) * 2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj - vk * 0.5, mo)) energy_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 print energy_core virtOrbs = range(ncore + mc.ncas, eris_sp['h1eff'].shape[0]) chunks = len(virtOrbs) / aaavsplit virtRange = [ virtOrbs[i:i + chunks] for i in xrange(0, len(virtOrbs), chunks) ] for K in range(aaavsplit): currentOrbs = range(ncore, mc.ncas + ncore) + virtRange[K] fout = open('FCIDUMP_aaav%d' % (K), 'w') #tools.fcidump.write_head(fout, eris_sp['h1eff'].shape[0]-ncore, mol.nelectron-2*ncore, orbsym= orbsymout[ncore:]) tools.fcidump.write_head( fout, mc.ncas + len(virtRange[K]), mol.nelectron - 2 * ncore, orbsym=(orbsymout[ncore:ncore + mc.ncas] + orbsymout[virtRange[K][0]:virtRange[K][-1] + 1])) ij = ncore * (ncore + 1) / 2 for i in range(len(currentOrbs)): for j in range(ncore, mc.ncas + ncore): for k in range(mc.ncas): for l in range(k + 1): I = currentOrbs[i] if abs(eris['ppaa'][I, j, k, l]) > 1.e-8: fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (eris['ppaa'][I,j,k,l], i+1, j+1-ncore, k+1, l+1)) h1eff = numpy.zeros(shape=(mc.ncas + len(virtRange[K]), mc.ncas + len(virtRange[K]))) h1eff[:mc.ncas, :mc.ncas] = eris_sp['h1eff'][ncore:ncore + mc.ncas, ncore:ncore + mc.ncas] h1eff[mc.ncas:, mc.ncas:] = eris_sp['h1eff'][virtRange[K][0]:virtRange[K][-1] + 1, virtRange[K][0]:virtRange[K][-1] + 1] h1eff[:mc.ncas, mc.ncas:] = eris_sp['h1eff'][ncore:ncore + mc.ncas, virtRange[K][0]:virtRange[K][-1] + 1] h1eff[mc.ncas:, :mc.ncas] = eris_sp['h1eff'][ virtRange[K][0]:virtRange[K][-1] + 1, ncore:ncore + mc.ncas] tools.fcidump.write_hcore(fout, h1eff, mc.ncas + len(virtRange[K]), tol=1e-8) #tools.fcidump.write_hcore(fout, eris_sp['h1eff'][virtRange[K][0]:virtRange[K][-1]+1, virtRange[K][0]:virtRange[K][-1]+1], len(virtRange[K]), tol=1e-8) fout.write(' %17.9e 0 0 0 0\n' % (mol.energy_nuc() + energy_core - energyE0)) fout.close() nc = ncore + mc.ncas fout = open('FCIDUMP_aaac', 'w') tools.fcidump.write_head(fout, nc - frozen, mol.nelectron - 2 * frozen, orbsym=orbsymout[frozen:nc]) for i in range(frozen, nc): for j in range(ncore, nc): for k in range(ncore, nc): for l in range(ncore, k + 1): if abs(eris['ppaa'][i, j, k - ncore, l - ncore]) > 1.e-8: fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (eris['ppaa'][i,j,k-ncore,l-ncore], i+1-frozen, j+1-frozen, k+1-frozen, l+1-frozen)) dmrge = energyE0 - mol.energy_nuc() - energy_core ecore_aaac = 0.0 for i in range(frozen, ncore): ecore_aaac += 2.0 * eris_sp['h1eff'][i, i] tools.fcidump.write_hcore(fout, eris_sp['h1eff'][frozen:nc, frozen:nc], nc - frozen, tol=1e-8) fout.write(' %17.9e 0 0 0 0\n' % (-dmrge - ecore_aaac)) fout.close() return norbs, energyE0
def hchain(n_sites, r=1.8, pg_reorder=True, **kwargs): """ 1D Hydrogen chain model. r in bohr. """ if 'scratch' in kwargs: import os if not os.path.isdir(kwargs['scratch']): os.mkdir(kwargs['scratch']) os.environ['TMPDIR'] = kwargs['scratch'] from pyscf import gto, scf, symm, ao2mo BOHR = 0.52917721092 # Angstroms r = r * BOHR mol = gto.M(atom=[['H', (i * r, 0, 0)] for i in range(n_sites)], basis='sto6g', verbose=0, symmetry='d2h') pg = mol.symmetry.lower() # Reorder if pg == 'd2h': fcidump_sym = [ "Ag", "B3u", "B2u", "B1g", "B1u", "B2g", "B3g", "Au" ] optimal_reorder = [ "Ag", "B1u", "B3u", "B2g", "B2u", "B3g", "B1g", "Au" ] elif pg == 'c1': fcidump_sym = ["A"] optimal_reorder = ["A"] else: assert False # SCF m = scf.RHF(mol) m.kernel() mo_coeff = m.mo_coeff n_ao = mo_coeff.shape[0] n_mo = mo_coeff.shape[1] orb_sym_str = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo_coeff) orb_sym = np.array([fcidump_sym.index(i) + 1 for i in orb_sym_str]) # Sort the orbitals by symmetry for more efficient DMRG if pg_reorder: idx = np.argsort([optimal_reorder.index(i) for i in orb_sym_str]) orb_sym = orb_sym[idx] mo_coeff = mo_coeff[:, idx] ridx = np.argsort(idx) else: ridx = np.array(list(range(n_mo)), dtype=int) h1e = mo_coeff.T @ m.get_hcore() @ mo_coeff g2e = ao2mo.restore(8, ao2mo.kernel(mol, mo_coeff), n_mo) ecore = mol.energy_nuc() del m, mol with HamilTools._init(**kwargs) as (): fcidump = FCIDUMP() n_elec = n_sites tol = 1E-13 mh1e = np.zeros((n_sites * (n_sites + 1) // 2)) k = 0 for i in range(0, n_sites): for j in range(0, i + 1): assert abs(h1e[i, j] - h1e[j, i]) < tol mh1e[k] = h1e[i, j] k += 1 mg2e = g2e.flatten().copy() mh1e[np.abs(mh1e) < tol] = 0.0 mg2e[np.abs(mg2e) < tol] = 0.0 fcidump.initialize_su2(n_sites, n_elec, 0, 1, ecore, mh1e, mg2e) fcidump.orb_sym = VectorUInt8(orb_sym) with HamilTools._from_fcidump(fcidump, pg=pg) as hamil: yield hamil
mol = gto.M(atom='C 0 0 0; C 0 0 1.24253', basis='cc-pvdz', symmetry=1, symmetry_subgroup='D2h') # run HF and store HF results in mf mf = scf.RHF(mol).run() # run MP2 and store MP2 results in mp2 mp2 = mp.MP2(mf).run() rdm1 = numpy.diag(mf.mo_occ) # The HF 1-particle density matrix in MO representation rdm1 += mp2.make_rdm1() # Add the correlation part natocc, natorb = numpy.linalg.eigh(rdm1) # Note natorb is in MO basis representation natorb = numpy.dot(mf.mo_coeff, natorb) try: natorb_sym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, natorb) print(natorb_sym) except ValueError: print('The diagonalization for rdm1 breaks the symmetry of the degenerated natural orbitals.') print('\nIn eigenvalue sovler symm.eigh, we diagonalize the density matrix with the MO symmetry ' 'information. The eigenvectors are all symmetry adapted.') orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mf.mo_coeff) natocc, natorb = symm.eigh(rdm1, orbsym) natorb = numpy.dot(mf.mo_coeff, natorb) natorb_sym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, natorb) print(natorb_sym)
def canonicalize(mc, mo_coeff=None, ci=None, eris=None, sort=False, cas_natorb=False, casdm1=None, verbose=logger.NOTE): '''Canonicalized CASCI/CASSCF orbitals of effecitve Fock matrix. Effective Fock matrix is built with one-particle density matrix (see also :func:`mcscf.casci.get_fock`) Args: mc : a CASSCF/CASCI object or RHF object Returns: A tuple, (natural orbitals, CI coefficients, orbital energies) The orbital energies are the diagonal terms of general Fock matrix. ''' from pyscf.lo import orth from pyscf.tools import dump_mat log = logger.new_logger(mc, verbose) if mo_coeff is None: mo_coeff = mc.mo_coeff if ci is None: ci = mc.ci if casdm1 is None: casdm1 = mc.fcisolver.make_rdm1(ci, mc.ncas, mc.nelecas) ncore = mc.ncore nocc = ncore + mc.ncas nmo = mo_coeff.shape[1] fock_ao = mc.get_fock(mo_coeff, ci, eris, casdm1, verbose) fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff)) mo_energy = fock.diagonal().copy() if cas_natorb: mo_coeff1, ci, occ = mc.cas_natorb(mo_coeff, ci, eris, sort, casdm1, verbose) ma = mo_coeff1[:,ncore:nocc] mo_energy[ncore:nocc] = numpy.einsum('ji,ji->i', ma, fock_ao.dot(ma)) else: # Keep the active space unchanged by default. The rotation in active space # may cause problem for external CI solver eg DMRG. mo_coeff1 = numpy.empty_like(mo_coeff) mo_coeff1[:,ncore:nocc] = mo_coeff[:,ncore:nocc] if ncore > 0: # note the last two args of ._eig for mc1step_symm # mc._eig function is called to handle symmetry adapated fock w, c1 = mc._eig(fock[:ncore,:ncore], 0, ncore) if sort: idx = numpy.argsort(w.round(9), kind='mergesort') w = w[idx] c1 = c1[:,idx] mo_coeff1[:,:ncore] = numpy.dot(mo_coeff[:,:ncore], c1) mo_energy[:ncore] = w if nmo-nocc > 0: w, c1 = mc._eig(fock[nocc:,nocc:], nocc, nmo) if sort: idx = numpy.argsort(w.round(9), kind='mergesort') w = w[idx] c1 = c1[:,idx] mo_coeff1[:,nocc:] = numpy.dot(mo_coeff[:,nocc:], c1) mo_energy[nocc:] = w if hasattr(mo_coeff, 'orbsym'): if sort: orbsym = symm.label_orb_symm(mc.mol, mc.mol.irrep_id, mc.mol.symm_orb, mo_coeff1) else: orbsym = mo_coeff.orbsym mo_coeff1 = lib.tag_array(mo_coeff1, orbsym=orbsym) if log.verbose >= logger.DEBUG: for i in range(nmo): log.debug('i = %d <i|F|i> = %12.8f', i+1, mo_energy[i]) # still return ci coefficients, in case the canonicalization funciton changed # cas orbitals, the ci coefficients should also be updated. return mo_coeff1, ci, mo_energy
def get_mo_from_h5(mol, h5fname, symmetry=None): ''' Get MO vectors for a pyscf molecule from an h5 file written by OpenMolcas Args: mol : instance gto.mole Must be in the same point group as the OpenMolcas calculation, or set the symmetry argument h5fname : str Path to an h5 file generated by OpenMolcas containing (at least) groups 'BASIS_FUNCTION_IDS', 'MO_OCCUPATIONS', 'MO_VECTORS', and 'MO_ENERGIES' and additionally 'DESYM_MATRIX' and 'DESYM_BASIS_FUNCTION_IDS' if symmetry is used. Kwargs: symmetry : str Point group of the calculation in OpenMolcas. If not provided, mol.groupname is used instead Returns: mo_coeff : ndarray of shape (nao_nr, nao_nr) ''' if symmetry is not None: mol = mol.copy() mol.build(symmetry=symmetry) nao = mol.nao_nr() with h5py.File(h5fname, 'r') as f: try: molcas_basids = f['DESYM_BASIS_FUNCTION_IDS'][()] molcas_usymm = f['DESYM_MATRIX'][()].reshape(nao, nao) except KeyError: assert (not mol.symmetry ), "Can't find desym_ data; mol.symmetry = {}".format( mol.symmetry) molcas_basids = f['BASIS_FUNCTION_IDS'][()] molcas_coeff = f['MO_VECTORS'][()] mo_energy = f['MO_ENERGIES'][()] mo_occ = f['MO_OCCUPATIONS'][()] idx_ao = [] for (c, n, l, m) in molcas_basids: # 0-index atom list in PySCF, 1-index atom list in Molcas c -= 1 # Actual principal quantum number in PySCF, 1-indexed list in Molcas n += l # l=1, ml=(-1,0,1) is (x,y,z) in PySCF, (y,z,x) in Molcas if l == 1: m = m - 2 if m > 0 else m + 1 idx_ao.append(mol.search_ao_nr(c, l, m, n)) idx_ao = np.argsort(np.asarray(idx_ao)) if mol.symmetry: # I have to figure out what order the Molcas irreps are in on the fly # because it seems to change depending on the xyz molcas_usymm = molcas_usymm[:, idx_ao] proj = np.stack([(np.dot(molcas_usymm, ir_coeff)**2).sum(1) for ir_coeff in mol.symm_orb], axis=0) errstr = ("Can't interpret h5 symmetry information; wrong mol? " " <mol.symm_orb|desym_matrix> =\n{}").format(proj) assert (np.allclose(np.amax(proj), 1)), errstr ix_irrep = np.argmax(proj, axis=0) uniq_idx = np.sort(np.unique(ix_irrep, return_index=True)[1]) uniq_idx = np.append(uniq_idx, len(ix_irrep)) nmo_irrep = [] for ix, i in enumerate(uniq_idx[:-1]): j = uniq_idx[ix + 1] assert (len(np.unique(ix_irrep[i:j])) == 1), errstr nmo_irrep.append(j - i) nmo_irrep = np.asarray(nmo_irrep) usymm_irrep_offset = np.cumsum(nmo_irrep) - nmo_irrep coeff_irrep_offset = np.cumsum(nmo_irrep**2) - nmo_irrep**2 mo_coeff = np.zeros((nao, nao), dtype=np.float_) for m_ir, usymm_off, coeff_off in zip(nmo_irrep, usymm_irrep_offset, coeff_irrep_offset): i, j = usymm_off, usymm_off + m_ir u, v = coeff_off, coeff_off + (m_ir**2) usymm = molcas_usymm[i:j, :].T coeff = molcas_coeff[u:v].reshape(m_ir, m_ir).T mo_coeff[:, i:j] = np.dot(usymm, coeff) else: assert (molcas_coeff.shape == ( nao**2, )), 'mo_vectors.shape = {} but {} AOs'.format( molcas_coeff.shape, nao) mo_coeff = molcas_coeff.reshape(nao, nao)[:, idx_ao].T # 'mergesort' keeps degenerate or active-space orbitals in the provided order! # idx_ene = np.argsort (mo_energy, kind='mergesort') # modified by Dayou: sort by mo_occ first, then mo_energy sort_key = np.min(mo_energy) * 100000 * mo_occ + mo_energy idx_ene = np.argsort(sort_key, kind='mergesort') mo_coeff = mo_coeff[:, idx_ene] mo_occ = mo_occ[idx_ene] mo_energy = mo_energy[idx_ene] if mol.verbose > logger.INFO: fname = str(mol.output)[:-4] + "_h5debug.molden" molden.from_mo(mol, fname, mo_coeff, occ=mo_occ, ene=mo_energy) if mol.symmetry: # assert (symmetry is right) try: orbsym = label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo_coeff) except ValueError as e: raise ValueError(("Problem understanding Molcas symmetry?\n" "{}").format(str(e))) return mo_coeff
mf.verbose = 3 mf.scf() ############################# # Build the Hamiltonian # ############################# L = mf.mol.nao_nr() N = mf.mol.nelectron CONST = mf.mol.energy_nuc() OEImo = np.dot( np.dot(mf.mo_coeff.T, mf.mol.intor('cint1e_kin_sph') + mf.mol.intor('cint1e_nuc_sph')), mf.mo_coeff) TEImo = ao2mo.outcore.full_iofree(mf.mol, mf.mo_coeff, compact=False).reshape(L, L, L, L) orb2irrep = np.array(symm.label_orb_symm(mf.mol, mf.mol.irrep_id, mf.mol.symm_orb, mf.mo_coeff), dtype=ctypes.c_int) for cnt in range(len(orb2irrep)): orb2irrep[cnt] = orb2irrep[cnt] % 10 ####################################### # PySCF FCI calculation and 4-RDM # ####################################### fci_solver = fci.FCI(mol, mf.mo_coeff) fci_energy, fci_vector = fci_solver.kernel() print "PySCF FCI energy =", fci_energy + CONST pyscf_start = time.time() dm1, dm2, dm3, dm4 = fci.rdm.make_dm1234('FCI4pdm_kern_spin0', fci_vector, fci_vector, L, N) dm1, dm2, dm3, dm4 = fci.rdm.reorder_dm1234(dm1, dm2,
def label_symmetry_(mc, mo_coeff, ci0=None): log = logger.Logger(mc.stdout, mc.verbose) #irrep_name = mc.mol.irrep_name irrep_name = mc.mol.irrep_id s = mc._scf.get_ovlp() try: orbsym = scf.hf_symm.get_orbsym(mc._scf.mol, mo_coeff, s, True) except ValueError: log.warn('mc1step_symm symmetrizes input orbitals') ncore = mc.ncore nocc = mc.ncore + mc.ncas mo_cor = symm.symmetrize_space(mc.mol, mo_coeff[:, :ncore], s=s, check=False) mo_act = symm.symmetrize_space(mc.mol, mo_coeff[:,ncore:nocc], s=s, check=False) mo_vir = symm.symmetrize_space(mc.mol, mo_coeff[:,nocc: ], s=s, check=False) mo_coeff = numpy.hstack((mo_cor,mo_act,mo_vir)) orbsym = symm.label_orb_symm(mc.mol, irrep_name, mc.mol.symm_orb, mo_coeff, s=s) mo_coeff_with_orbsym = lib.tag_array(mo_coeff, orbsym=orbsym) active_orbsym = getattr(mc.fcisolver, 'orbsym', []) if (not hasattr(active_orbsym, '__len__')) or len(active_orbsym) == 0: ncore = mc.ncore nocc = mc.ncore + mc.ncas mc.fcisolver.orbsym = orbsym[ncore:nocc] log.debug('Active space irreps %s', str(mc.fcisolver.orbsym)) wfnsym = 0 if getattr(mc.fcisolver, 'wfnsym', None) is not None: wfnsym = mc.fcisolver.wfnsym elif ci0 is None: # Guess wfnsym based on HF determinant. mo_coeff may not be HF # canonical orbitals. Some checks are needed to ensure that mo_coeff # are derived from the symmetry adapted SCF calculations. if mo_coeff is mc._scf.mo_coeff: wfnsym = 0 for ir in orbsym[mc._scf.mo_occ == 1]: wfnsym ^= ir mc.fcisolver.wfnsym = wfnsym log.debug('Set CASCI wfnsym %s based on HF determinant', wfnsym) elif hasattr(mo_coeff, 'orbsym'): # It may be reordered SCF orbitals ncore = mc.ncore nocc = mc.ncore + mc.ncas cas_orb = mo_coeff[:,ncore:nocc] s = reduce(numpy.dot, (cas_orb.T, mc._scf.get_ovlp(), mc._scf.mo_coeff)) if numpy.all(numpy.max(s, axis=1) > 1-1e-9): idx = numpy.argmax(s, axis=1) cas_orbsym = orbsym[ncore:nocc] cas_occ = mc._scf.mo_occ[idx] wfnsym = 0 for ir in cas_orbsym[cas_occ == 1]: wfnsym ^= ir mc.fcisolver.wfnsym = wfnsym log.debug('Active space are constructed from canonical SCF ' 'orbitals %s', idx) log.debug('Set CASCI wfnsym %s based on HF determinant', wfnsym) elif hasattr(mc.fcisolver, 'guess_wfnsym'): wfnsym = mc.fcisolver.guess_wfnsym(mc.ncas, mc.nelecas, ci0, verbose=log) log.debug('CASCI wfnsym %s (based on CI initial guess)', wfnsym) if isinstance(wfnsym, (int, numpy.integer)): wfnsym = symm.irrep_id2name(mc.mol.groupname, wfnsym) log.info('Active space CI wfn symmetry = %s', wfnsym) return mo_coeff_with_orbsym
'B3': 2 }, 'Cs': { "A'": 1, 'A"': 2 }, 'C2': { 'A': 1, 'B': 2 }, 'Ci': { 'Ag': 1, 'Au': 2 }, 'C1': { 'A': 1, } } orbsym = [ MOLPRO_ID[mol.groupname][i] for i in symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, c) ] tools.fcidump.from_integrals('fcidump.example3', h1e, eri, c.shape[1], mol.nelectron, ms=0, orbsym=orbsym)
) fspt.write('La matriz D es:\n') for i in range(nmo): for j in range(nmo): fspt.write('%i %i %.16f\n' % ((i + 1), (j + 1), rdm1[i, j])) fspt.write('La matriz d es:\n') for i in range(nmo): for j in range(nmo): for k in range(nmo): for l in range(nmo): if (abs(rdm2[i, j, k, l]) > 1e-12): fspt.write('%i %i %i %i %.16f\n' % ((i + 1), (j + 1), (k + 1), (l + 1), rdm2[i, j, k, l])) fspt.close() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mc.mo_coeff[:, :nmo]) natocc, natorb = symm.eigh(-rdm1, orbsym) for i, k in enumerate(numpy.argmax(abs(natorb), axis=0)): if natorb[k, i] < 0: natorb[:, i] *= -1 natorb = numpy.dot(mc.mo_coeff[:, :nmo], natorb) natocc = -natocc with open('n2_cas.det', 'w') as f3: write_ci(f3, mc.ci, mc.ncas, mc.nelecas, mc.ncore) with open('n2_ref_nat.mol', 'w') as f2: molden.header(mol, f2) molden.orbital_coeff(mol, f2, natorb, occ=natocc) with open('n2_ref.mol', 'w') as f2: molden.header(mol, f2) molden.orbital_coeff(mol, f2,
def __init__(self, mol_or_hdf5, c=None, network=None, verbose=None): '''Initializing the T3NS calculation. Args: mol_or_hdf5: An instance of :class:`Mole` from PySCF or a string to a path of the hdf5 file. In this case c and network should be left as defaults. c: The orbital coefficients. The default are the RHF orbitals. network: Network of the tensor network. This can be the string 'DMRG' for a linear chain or 'T3NS' for a T3NS that is radially extended (i.e. the maximal distance between two sites is minimal). An instance of :class:`Network` is also accepted for custom networks or a path to a network file. Default is 'T3NS' if Mole instance was passed, else None. ''' from pyscf import symm if isinstance(mol_or_hdf5, pyscf.gto.Mole): # Initialize with RHF mol = mol_or_hdf5 if network is None: network = 'T3NS' if verbose is None: self.verbose = mol.verbose self.mol = mol # if no orbital coefficients are given, use RHF orbitals if c is None: myhf = pyscf.scf.RHF(mol) myhf.verbose = self.verbose myhf.kernel() c = myhf.mo_coeff self._c = c self._mol = mol self._eri = pyscf.ao2mo.kernel(mol, c) self.symmetries = ['Z2', 'U1', 'SU2'] self.target = [int(mol.nelectron % 2), mol.nelectron, mol.spin] try: irrep_ids = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, c) newsym = mol.groupname if mol.groupname == 'Dooh' or mol.groupname == 'Coov': newsym = 'D2h' if mol.groupname else 'C2v' if self.verbose > 1: print(f'Changed point group from {mol.groupname} to ' f'{newsym}') # mod 10 needed for translation Coov and Dooh # See https://sunqm.github.io/pyscf/symm.html self._pg_irrep = [ symm.irrep_id2name(newsym, int(ii % 10)) for ii in irrep_ids ] self.symmetries.append(newsym) self.target.append(symm.irrep_id2name(newsym, 0)) except (ValueError, TypeError): self._pg_irrep = None if isinstance(network, netw.Network): self._netw = network elif network == 'DMRG' or network == 'T3NS': isDMRG = network == 'DMRG' self._netw = netw.Network(c.shape[1], isDMRG=isDMRG) # exchange matrix # Kij = numpy.zeros((c.shape[1],) * 2) # trids = numpy.tril_indices(c.shape[1], 0) # for el, r, c in zip(self._eri.diagonal(), trids[0], trids[1]): # Kij[r, c] = el # Kij[c, r] = el # cost = self._netw.optimize(Kij) # if self.verbose >= 2: # print(f'Optimization Exchange-cost: {cost}') elif isinstance(network, str): self._netw = netw.Network() self._netw.readnetworkfile(network) else: raise ValueError(f'{network} is invalid for network') self._netw.pass_network() elif isinstance(mol_or_hdf5, str): # h5path = mol_or_hdf5 if verbose is None: self.verbose = 1 if c is not None or network is not None: raise ValueError( 'A hdf5 file does not expect a defined c or network') raise ValueError('Need to implement hdf5 readin still') else: raise ValueError( 'Expects a Mole instance or a path to a hdf5 file')
def analyze(self, verbose=logger.DEBUG, **kwargs): from pyscf.lo import orth from pyscf.tools import dump_mat if not self.mol.symmetry: return rohf.ROHF.analyze(self, verbose, **kwargs) mo_energy = self.mo_energy mo_occ = self.mo_occ mo_coeff = self.mo_coeff log = logger.Logger(self.stdout, verbose) mol = self.mol nirrep = len(mol.irrep_id) ovlp_ao = self.get_ovlp() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, ovlp_ao, False) orbsym = numpy.array(orbsym) wfnsym = 0 ndoccs = [] nsoccs = [] for k, ir in enumerate(mol.irrep_id): ndoccs.append(sum(orbsym[mo_occ == 2] == ir)) nsoccs.append(sum(orbsym[mo_occ == 1] == ir)) if nsoccs[k] % 2: wfnsym ^= ir if mol.groupname in ('Dooh', 'Coov'): log.info('TODO: total symmetry for %s', mol.groupname) else: log.info('total symmetry = %s', symm.irrep_id2name(mol.groupname, wfnsym)) log.info('occupancy for each irrep: ' + (' %4s' * nirrep), *mol.irrep_name) log.info('double occ ' + (' %4d' * nirrep), *ndoccs) log.info('single occ ' + (' %4d' * nirrep), *nsoccs) log.info('**** MO energy ****') irname_full = {} for k, ir in enumerate(mol.irrep_id): irname_full[ir] = mol.irrep_name[k] irorbcnt = {} if self._focka_ao is None: for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note('MO #%-3d (%s #%-2d), energy= %-18.15g occ= %g', k + 1, irname_full[j], irorbcnt[j], mo_energy[k], mo_occ[k]) else: mo_ea = numpy.einsum('ik,ik->k', mo_coeff, self._focka_ao.dot(mo_coeff)) mo_eb = numpy.einsum('ik,ik->k', mo_coeff, self._fockb_ao.dot(mo_coeff)) log.note( ' Roothaan | alpha | beta' ) for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note( 'MO #%-4d(%-3s #%-2d) energy= %-18.15g | %-18.15g | %-18.15g occ= %g', k + 1, irname_full[j], irorbcnt[j], mo_energy[k], mo_ea[k], mo_eb[k], mo_occ[k]) if verbose >= logger.DEBUG: label = mol.spheric_labels(True) molabel = [] irorbcnt = {} for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 molabel.append('#%-d(%s #%d)' % (k + 1, irname_full[j], irorbcnt[j])) log.debug(' ** MO coefficients (expansion on meta-Lowdin AOs) **') orth_coeff = orth.orth_ao(mol, 'meta_lowdin', s=ovlp_ao) c = reduce(numpy.dot, (orth_coeff.T, ovlp_ao, mo_coeff)) dump_mat.dump_rec(self.stdout, c, label, molabel, start=1, **kwargs) dm = self.make_rdm1(mo_coeff, mo_occ) return self.mulliken_meta(mol, dm, s=ovlp_ao, verbose=verbose)
def run(b, dm_guess, mo_guess, ci=None): mol = gto.Mole() mol.verbose = 5 mol.output = 'cr2-%3.2f.out' % b mol.atom = [ ['Cr', (0., 0., -b / 2)], ['Cr', (0., 0., b / 2)], ] mol.basis = 'ccpvdzdk' mol.symmetry = True mol.build() mf = scf.RHF(mol).x2c() mf.max_cycle = 100 mf.conv_tol = 1e-9 mf.kernel(dm_guess) #--------------------- # CAS(12,12) # # The active space of CAS(12,42) can be generated by function sort_mo_by_irrep, # or AVAS, dmet_cas methods. Here we first run a CAS(12,12) calculation and # using the lowest CASSCF canonicalized orbitals in the CAS(12,42) calculation # as the core and valence orbitals. mc = mcscf.CASSCF(mf, 12, 12) if mo_guess is None: # the initial guess for first calculation ncas = { 'A1g': 2, 'E1gx': 1, 'E1gy': 1, 'E2gx': 1, 'E2gy': 1, 'A1u': 2, 'E1ux': 1, 'E1uy': 1, 'E2ux': 1, 'E2uy': 1 } mo_guess = mcscf.sort_mo_by_irrep(mc, mf.mo_coeff, ncas, ncore) else: mo_guess = mcscf.project_init_guess(mc, mo_guess) # Projection may destroy the spatial symmetry of the MCSCF orbitals. try: print( 'Irreps of the projected CAS(12,12) orbitals', symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_guess)) except: print('Projected CAS(12,12) orbitals does not have right symmetry') # FCI solver with multi-threads is not stable enough for this sytem mc.fcisolver.threads = 1 # To avoid spin contamination mc.fix_spin_() # By default, canonicalization as well as the CASSCF optimization do not # change the orbital symmetry labels. "Orbital energy" mc.mo_energy, the # diagonal elements of the general fock matrix, may have wrong ordering. # To use the lowest CASSCF orbitals as the core + active orbitals in the next # step, we have to sort the orbitals based on the "orbital energy". This # operation will change the orbital symmetry labels. mc.sorting_mo_energy = True # "mc.natorb = True" will transform the active space, to its natural orbital # representation. By default, the active space orbitals are NOT reordered # even the option sorting_mo_energy is enabled. Transforming the active space # orbitals is a dangerous operation because it needs also to update the CI # wavefunction. For DMRG solver (or other approximate FCI solver), the CI # wavefunction may not be able to consistently converged and it leads to # inconsistency between the orbital space and the CI wavefunction # representations. Unless required by the following CAS calculation, setting # mc.natorb=True should be avoided # mc.natorb = True mc.kernel(mo_guess, ci) mc.analyze() #--------------------- # CAS(12,42) # # Using the lowest CASSCF canonicalized orbitals in the CAS(12,42) DMRG-CASSCF # calculation. norb = 42 nelec = 12 mc1 = DMRGSCF(mf, norb, nelec) mc1.fcisolver.maxM = 4000 # Enable internal rotation since the bond dimension of DMRG calculation is # small, the active space energy can be optimized wrt to the orbital rotation # within the active space. mc1.internal_rotation = True # Sorting the orbital energy is not a step of must here. # mc1.sorting_mo_energy = True # mc1.natorb = True mc1.kernel() # Passing the results as an initial guess to the next point. return mf.make_rdm1(), mc.mo_coeff, mc.ci
def init(self, molecule, charge, spin, basis_set, orb_basis='scf', cas=False, cas_nstart=None, cas_nstop=None, cas_nel=None, loc_nstart=None, loc_nstop=None, scf_conv_tol=1e-14): # {{{ import pyscf from pyscf import gto, scf, ao2mo, molden, lo pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues #PYSCF inputs print(" ---------------------------------------------------------") print(" Using Pyscf:") print(" ---------------------------------------------------------") print(" ") mol = gto.Mole() mol.atom = molecule mol.max_memory = 1000 # MB mol.symmetry = True mol.charge = charge mol.spin = spin mol.basis = basis_set mol.build() print("symmertry") print(mol.topgroup) #SCF #mf = scf.RHF(mol).run(init_guess='atom') mf = scf.RHF(mol).run(conv_tol=scf_conv_tol) #C = mf.mo_coeff #MO coeffs enu = mf.energy_nuc() print(" SCF Total energy: %12.8f" % mf.e_tot) print(" SCF Elec energy: %12.8f" % (mf.e_tot - enu)) print(mf.get_fock()) print(np.linalg.eig(mf.get_fock())[0]) if mol.symmetry == True: from pyscf import symm mo = symm.symmetrize_orb(mol, mf.mo_coeff) osym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo) #symm.addons.symmetrize_space(mol, mo, s=None, check=True, tol=1e-07) for i in range(len(osym)): print("%4d %8s %16.8f" % (i + 1, osym[i], mf.mo_energy[i])) #orbitals and lectrons n_orb = mol.nao_nr() n_b, n_a = mol.nelec nel = n_a + n_b self.n_orb = mol.nao_nr() if cas == True: cas_norb = cas_nstop - cas_nstart from pyscf import mcscf assert (cas_nstart != None) assert (cas_nstop != None) assert (cas_nel != None) else: cas_nstart = 0 cas_nstop = n_orb cas_nel = nel ##AO 2 MO Transformation: orb_basis or scf if orb_basis == 'scf': print("\nUsing Canonical Hartree Fock orbitals...\n") C = cp.deepcopy(mf.mo_coeff) print("C shape") print(C.shape) elif orb_basis == 'lowdin': assert (cas == False) S = mol.intor('int1e_ovlp_sph') print("Using lowdin orthogonalized orbitals") C = lowdin(S) #end elif orb_basis == 'boys': pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues cl_c = mf.mo_coeff[:, :cas_nstart] cl_a = lo.Boys(mol, mf.mo_coeff[:, cas_nstart:cas_nstop]).kernel(verbose=4) cl_v = mf.mo_coeff[:, cas_nstop:] C = np.column_stack((cl_c, cl_a, cl_v)) elif orb_basis == 'boys2': pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues cl_c = mf.mo_coeff[:, :loc_nstart] cl_a = lo.Boys(mol, mf.mo_coeff[:, loc_nstart:loc_nstop]).kernel(verbose=4) cl_v = mf.mo_coeff[:, loc_nstop:] C = np.column_stack((cl_c, cl_a, cl_v)) elif orb_basis == 'PM': pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues cl_c = mf.mo_coeff[:, :cas_nstart] cl_a = lo.PM(mol, mf.mo_coeff[:, cas_nstart:cas_nstop]).kernel(verbose=4) cl_v = mf.mo_coeff[:, cas_nstop:] C = np.column_stack((cl_c, cl_a, cl_v)) elif orb_basis == 'PM2': pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues cl_c = mf.mo_coeff[:, :loc_nstart] cl_a = lo.PM(mol, mf.mo_coeff[:, loc_nstart:loc_nstop]).kernel(verbose=4) cl_v = mf.mo_coeff[:, loc_nstop:] C = np.column_stack((cl_c, cl_a, cl_v)) elif orb_basis == 'ER': pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues cl_c = mf.mo_coeff[:, :cas_nstart] cl_a = lo.PM(mol, mf.mo_coeff[:, cas_nstart:cas_nstop]).kernel(verbose=4) cl_v = mf.mo_coeff[:, cas_nstop:] C = np.column_stack((cl_c, cl_a, cl_v)) elif orb_basis == 'ER2': pyscf.lib.num_threads( 1 ) #with degenerate states and multiple processors there can be issues cl_c = mf.mo_coeff[:, :loc_nstart] cl_a = lo.ER(mol, mf.mo_coeff[:, loc_nstart:loc_nstop]).kernel(verbose=4) cl_v = mf.mo_coeff[:, loc_nstop:] C = np.column_stack((cl_c, cl_a, cl_v)) elif orb_basis == 'ibmo': loc_vstop = loc_nstop - n_a print(loc_vstop) mo_occ = mf.mo_coeff[:, mf.mo_occ > 0] mo_vir = mf.mo_coeff[:, mf.mo_occ == 0] c_core = mo_occ[:, :loc_nstart] iao_occ = lo.iao.iao(mol, mo_occ[:, loc_nstart:]) iao_vir = lo.iao.iao(mol, mo_vir[:, :loc_vstop]) c_out = mo_vir[:, loc_vstop:] # Orthogonalize IAO iao_occ = lo.vec_lowdin(iao_occ, mf.get_ovlp()) iao_vir = lo.vec_lowdin(iao_vir, mf.get_ovlp()) # # Method 1, using Knizia's alogrithm to localize IAO orbitals # ''' Generate IBOS from orthogonal IAOs ''' ibo_occ = lo.ibo.ibo(mol, mo_occ[:, loc_nstart:], iaos=iao_occ) ibo_vir = lo.ibo.ibo(mol, mo_vir[:, :loc_vstop], iaos=iao_vir) C = np.column_stack((c_core, ibo_occ, ibo_vir, c_out)) else: print("Error:NO orbital basis defined") molden.from_mo(mol, 'orbitals.molden', C) if cas == True: print(C.shape) print(cas_norb) print(cas_nel) mycas = mcscf.CASSCF(mf, cas_norb, cas_nel) h1e_cas, ecore = mycas.get_h1eff( mo_coeff=C) #core core orbs to form ecore and eff h2e_cas = ao2mo.kernel(mol, C[:, cas_nstart:cas_nstop], aosym='s4', compact=False).reshape(4 * ((cas_norb), )) print(h1e_cas) print(h1e_cas.shape) #return h1e_cas,h2e_cas,ecore,C,mol,mf self.h = h1e_cas self.g = h2e_cas self.ecore = ecore self.mf = mf self.mol = mol self.C = cp.deepcopy(C[:, cas_nstart:cas_nstop]) J, K = mf.get_jk() self.J = self.C.T @ J @ self.C self.K = self.C.T @ J @ self.C #HF density if orb_basis == 'scf': #C = C[:,cas_nstart:cas_nstop] D = mf.make_rdm1(mo_coeff=C) S = mf.get_ovlp() sal, svec = np.linalg.eigh(S) idx = sal.argsort()[::-1] sal = sal[idx] svec = svec[:, idx] sal = sal**-0.5 sal = np.diagflat(sal) X = svec @ sal @ svec.T C_ao2mo = np.linalg.inv(X) @ C Cocc = C_ao2mo[:, :n_a] D = Cocc @ Cocc.T DMO = C_ao2mo.T @ D @ C_ao2mo #only for cas space DMO = DMO[cas_nstart:cas_nstop, cas_nstart:cas_nstop] self.dm_aa = DMO self.dm_bb = DMO print("DENSITY") print(self.dm_aa.shape) if 0: h = C.T.dot(mf.get_hcore()).dot(C) g = ao2mo.kernel(mol, C, aosym='s4', compact=False).reshape(4 * ((n_orb), )) const, heff = get_eff_for_casci(cas_nstart, cas_nstop, h, g) print(heff) print("const", const) print("ecore", ecore) idx = range(cas_nstart, cas_nstop) h = h[:, idx] h = h[idx, :] g = g[:, :, :, idx] g = g[:, :, idx, :] g = g[:, idx, :, :] g = g[idx, :, :, :] self.ecore = const self.h = h + heff self.g = g elif cas == False: h = C.T.dot(mf.get_hcore()).dot(C) g = ao2mo.kernel(mol, C, aosym='s4', compact=False).reshape(4 * ((n_orb), )) print(h) #return h, g, enu, C,mol,mf self.h = h self.g = g self.ecore = enu self.mf = mf self.mol = mol self.C = C J, K = mf.get_jk() self.J = self.C.T @ J @ self.C self.K = self.C.T @ J @ self.C #HF density if orb_basis == 'scf': D = mf.make_rdm1(mo_coeff=None) S = mf.get_ovlp() sal, svec = np.linalg.eigh(S) idx = sal.argsort()[::-1] sal = sal[idx] svec = svec[:, idx] sal = sal**-0.5 sal = np.diagflat(sal) X = svec @ sal @ svec.T C_ao2mo = np.linalg.inv(X) @ C Cocc = C_ao2mo[:, :n_a] D = Cocc @ Cocc.T DMO = C_ao2mo.T @ D @ C_ao2mo self.dm_aa = DMO self.dm_bb = DMO print("DENSITY") print(self.dm_aa)
def caslst_by_irrep(casscf, mo_coeff, cas_irrep_nocc, cas_irrep_ncore=None, s=None, base=1): '''Given number of active orbitals for each irrep, return the orbital indices of active space Args: casscf : an :class:`CASSCF` or :class:`CASCI` object cas_irrep_nocc : list or dict Number of active orbitals for each irrep. It can be a dict, eg {'A1': 2, 'B2': 4} to indicate the active space size based on irrep names, or {0: 2, 3: 4} for irrep Id, or a list [2, 0, 0, 4] (identical to {0: 2, 3: 4}) in which the list index is served as the irrep Id. Kwargs: cas_irrep_ncore : list or dict Number of closed shells for each irrep. It can be a dict, eg {'A1': 6, 'B2': 4} to indicate the closed shells based on irrep names, or {0: 6, 3: 4} for irrep Id, or a list [6, 0, 0, 4] (identical to {0: 6, 3: 4}) in which the list index is served as the irrep Id. If cas_irrep_ncore is not given, the program will generate a guess based on the lowest :attr:`CASCI.ncore` orbitals. s : ndarray overlap matrix base : int 0-based (C-like) or 1-based (Fortran-like) caslst Returns: A list of orbital indices Examples: >>> from pyscf import gto, scf, mcscf >>> mol = gto.M(atom='N 0 0 0; N 0 0 1', basis='ccpvtz', symmetry=True, verbose=0) >>> mf = scf.RHF(mol) >>> mf.kernel() >>> mc = mcscf.CASSCF(mf, 12, 4) >>> mcscf.caslst_by_irrep(mc, mf.mo_coeff, {'E1gx':4, 'E1gy':4, 'E1ux':2, 'E1uy':2}) [5, 7, 8, 10, 11, 14, 15, 20, 25, 26, 31, 32] ''' mol = casscf.mol log = logger.Logger(casscf.stdout, casscf.verbose) if s is None: s = casscf._scf.get_ovlp() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s) orbsym = numpy.asarray(orbsym) ncore = casscf.ncore irreps = set(orbsym) if cas_irrep_ncore is not None: irrep_ncore = {} for k, v in cas_irrep_ncore.items(): if isinstance(k, str): irrep_ncore[symm.irrep_name2id(mol.groupname, k)] = v else: irrep_ncore[k] = v ncore_rest = casscf.ncore - sum(irrep_ncore.values()) if ncore_rest > 0: # guess core configuration mask = numpy.ones(len(orbsym), dtype=bool) for ir in irrep_ncore: mask[orbsym == ir] = False core_rest = orbsym[mask][:ncore_rest] core_rest = dict([(ir, numpy.count_nonzero(core_rest==ir)) for ir in set(core_rest)]) log.info('Given core space %s < casscf core size %d', cas_irrep_ncore, casscf.ncore) log.info('Add %s to core configuration', core_rest) irrep_ncore.update(core_rest) elif ncore_rest < 0: raise ValueError('Given core space %s > casscf core size %d' % (cas_irrep_ncore, casscf.ncore)) else: irrep_ncore = dict([(ir, sum(orbsym[:ncore]==ir)) for ir in irreps]) if not isinstance(cas_irrep_nocc, dict): # list => dict cas_irrep_nocc = dict([(ir, n) for ir,n in enumerate(cas_irrep_nocc) if n > 0]) irrep_ncas = {} for k, v in cas_irrep_nocc.items(): if isinstance(k, str): irrep_ncas[symm.irrep_name2id(mol.groupname, k)] = v else: irrep_ncas[k] = v ncas_rest = casscf.ncas - sum(irrep_ncas.values()) if ncas_rest > 0: mask = numpy.ones(len(orbsym), dtype=bool) # remove core and specified active space for ir in irrep_ncas: mask[orbsym == ir] = False for ir, ncore in irrep_ncore.items(): idx = numpy.where(orbsym == ir)[0] mask[idx[:ncore]] = False cas_rest = orbsym[mask][:ncas_rest] cas_rest = dict([(ir, numpy.count_nonzero(cas_rest==ir)) for ir in set(cas_rest)]) log.info('Given active space %s < casscf active space size %d', cas_irrep_nocc, casscf.ncas) log.info('Add %s to active space', cas_rest) irrep_ncas.update(cas_rest) elif ncas_rest < 0: raise ValueError('Given active space %s > casscf active space size %d' % (cas_irrep_nocc, casscf.ncas)) caslst = [] for ir, ncas in irrep_ncas.items(): if ncas > 0: if ir in irrep_ncore: nc = irrep_ncore[ir] else: nc = 0 no = nc + ncas idx = numpy.where(orbsym == ir)[0] caslst.extend(idx[nc:no]) caslst = numpy.sort(numpy.asarray(caslst)) + base if len(caslst) < casscf.ncas: raise ValueError('Not enough orbitals found for core %s, cas %s' % (cas_irrep_ncore, cas_irrep_nocc)) if log.verbose >= logger.INFO: log.info('ncore for each irreps %s', dict([(symm.irrep_id2name(mol.groupname, k), v) for k,v in irrep_ncore.items()])) log.info('ncas for each irreps %s', dict([(symm.irrep_id2name(mol.groupname, k), v) for k,v in irrep_ncas.items()])) log.info('(%d-based) caslst = %s', base, caslst) return caslst
H 2.49475714 0. -0.00736748 H 1.24762314 2.16037824 -0.00925948 H -1.24752386 2.16043824 -0.01063248 H -2.49460686 0. -0.00886348 ''', basis = 'ccpvdz') mf = scf.RHF(mol) mf.kernel() # Change error tolerence (to 0.1 Bohr, default is 1e-5 Bohr) for symmetry # detection, so that the program can find the raw symmetry. symm.geom.GEOM_THRESHOLD = .1 symm.geom.PLACE = 1 mol.symmetry = True mol.build(False, False) print('Pseudo symmetry %s' % mol.groupname) # Call mol.build again to avoid the atom coordinates changed mol.symmetry = mol.groupname mol.build(False, False) irname = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mf.mo_coeff, check=False) s = mol.intor('cint1e_ovlp_sph') print('MO id irreps likely') for i, ir in enumerate(irname): k = mol.irrep_name.index(ir) s1 = reduce(numpy.dot, (mol.symm_orb[k].T, s, mf.mo_coeff[:,i])) s0 = reduce(numpy.dot, (mol.symm_orb[k].T, s, mol.symm_orb[k])) print('MO %3d %-3s %8.5f' % (i, ir, numpy.dot(s1, numpy.linalg.solve(s0, s1))))
def writeNevpt2Integrals(mc, dm1, dm2, dm1eff, aaavsplit, frozen): eris = _ERIS(mc, mc.mo_coeff) nocc = mc.ncore + mc.ncas ncore = mc.ncore nact = mc.ncas norbs = eris['ppaa'].shape[0] nvirt = norbs-ncore-nact eris_sp={} #eris_sp['cvcv']= numpy.zeros(shape=(1,1)) #numpy.zeros(shape=(mc.ncore, norbs-mc.ncore-mc.ncas, mc.ncore, norbs-mc.ncas-mc.ncore)) eris_sp['h1eff']= 1.*eris['h1eff'] #numpy.zeros(shape=(norbs, norbs)) int1 = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_hcore(), mc.mo_coeff)) #eris_sp['h1eff'] = makeheff(int1, eris['papa'], eris['ppaa'], dm1, ncore, nvirt) eris_sp['h1eff'][:mc.ncore,:mc.ncore] += numpy.einsum('abcd,cd', eris['ppaa'][:mc.ncore, :mc.ncore,:,:], dm1eff) eris_sp['h1eff'][:mc.ncore,:mc.ncore] -= numpy.einsum('abcd,bd', eris['papa'][:mc.ncore, :, :mc.ncore,:], dm1eff)*0.5 eris_sp['h1eff'][mc.ncas+mc.ncore:,mc.ncas+mc.ncore:] += numpy.einsum('abcd,cd', eris['ppaa'][mc.ncas+mc.ncore:,mc.ncas+mc.ncore:,:,:], dm1eff) eris_sp['h1eff'][mc.ncas+mc.ncore:,mc.ncas+mc.ncore:] -= numpy.einsum('abcd,bd', eris['papa'][mc.ncas+mc.ncore:,:,mc.ncas+mc.ncore:,:], dm1eff)*0.5 offdiagonal = 0.0 #zero out off diagonal core for k in range(mc.ncore): for l in range(mc.ncore): if(k != l): offdiagonal = max(abs(offdiagonal), abs(eris_sp['h1eff'][k,l] )) #zero out off diagonal virtuals for k in range(mc.ncore+mc.ncas, norbs): for l in range(mc.ncore+mc.ncas,norbs): if(k != l): offdiagonal = max(abs(offdiagonal), abs(eris_sp['h1eff'][k,l] )) if (abs(offdiagonal) > 1e-6): print "WARNING ***** Have to use natorual orbitals from casscf ****" print "offdiagonal elements ", offdiagonal eriscvcv = eris['cvcv'] if (not isinstance(eris['cvcv'], type(eris_sp['h1eff']))): #eriscvcv = h5py.File(eris['cvcv'].name,'r')["eri_mo"] eriscvcv = lib.chkfile.load(eris['cvcv'].name, "eri_mo")#h5py.File(eris['cvcv'].name,'r')["eri_mo"] eris_sp['cvcv'] = eriscvcv.reshape(mc.ncore, norbs-mc.ncore-mc.ncas, mc.ncore, norbs-mc.ncore-mc.ncas) import os os.system("mkdir int") numpy.save("int/W:caac", numpy.asfortranarray(eris['papa'][frozen:mc.ncore, :, frozen:mc.ncore, :].transpose(0,3,1,2))) numpy.save("int/W:aeca", numpy.asfortranarray(eris['papa'][frozen:mc.ncore, :, mc.ncore+mc.ncas:, :].transpose(1,2,0,3))) numpy.save("int/W:ccaa", numpy.asfortranarray(eris['papa'][frozen:mc.ncore, :, frozen:mc.ncore, :].transpose(0,2,1,3))) numpy.save("int/W:eeaa", numpy.asfortranarray(eris['papa'][mc.ncore+mc.ncas:, :, mc.ncore+mc.ncas:, :].transpose(0,2,1,3))) numpy.save("int/W:caca", numpy.asfortranarray(eris['ppaa'][frozen:mc.ncore, frozen:mc.ncore, :, :].transpose(0,2,1,3))) numpy.save("int/W:eaca", numpy.asfortranarray(eris['ppaa'][mc.ncore+mc.ncas:, frozen:mc.ncore, :, :].transpose(0,2,1,3))) numpy.save("int/W:eecc", numpy.asfortranarray(eris_sp['cvcv'][frozen:,:,frozen:,:].transpose(1,3,0,2))) numpy.save("int/W:ccae", numpy.asfortranarray(eris['pacv'][frozen:mc.ncore,:,frozen:,:].transpose(0,2,1,3))) numpy.save("int/W:aaaa", numpy.asfortranarray(eris['ppaa'][mc.ncore:mc.ncore+mc.ncas, mc.ncore:mc.ncore+mc.ncas, :, :].transpose(0,2,1,3))) numpy.save("int/W:eeca", numpy.asfortranarray(eris['pacv'][mc.ncore+mc.ncas:, :, frozen:, :].transpose(3,0,2,1))) numpy.save("int/int1eff", numpy.asfortranarray(eris_sp['h1eff'][frozen:,frozen:])) numpy.save("int/E1.npy", numpy.asfortranarray(dm1)) numpy.save("int/E2.npy", numpy.asfortranarray(dm2)) #numpy.save("int/E3",dm3) #numpy.save("int/E3B.npy", dm3.transpose(0,3,1,4,2,5)) #numpy.save("int/E3C.npy", dm3.transpose(5,0,2,4,1,3)) nc = mc.ncore+mc.ncas energyE0 = 1.0*numpy.einsum('ij,ij', eris_sp['h1eff'][ncore:nc, ncore:nc], dm1) energyE0 += 0.5*numpy.einsum('ijkl,ijkl', eris['ppaa'][mc.ncore:mc.ncore+mc.ncas, mc.ncore:mc.ncore+mc.ncas, :, :].transpose(0,2,1,3), dm2) mo = mc.mo_coeff dmcore = numpy.dot(mo[:,:ncore], mo[:,:ncore].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) energyE0 += numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 energyE0 += mc.mol.energy_nuc() print "Energy = ", energyE0 from pyscf import symm mol = mc.mol orbsymout=[] orbsym = [] if (mol.symmetry): orbsym = symm.label_orb_symm(mc.mol, mc.mol.irrep_id, mc.mol.symm_orb, mc.mo_coeff, s=mc._scf.get_ovlp()) if mol.symmetry and orbsym: if mol.groupname.lower() == 'dooh': orbsymout = [dmrg_sym.IRREP_MAP['D2h'][i % 10] for i in orbsym] elif mol.groupname.lower() == 'coov': orbsymout = [dmrg_sym.IRREP_MAP['C2v'][i % 10] for i in orbsym] else: orbsymout = [dmrg_sym.IRREP_MAP[mol.groupname][i] for i in orbsym] else: orbsymout = [] ncore = mc.ncore mo = mc.mo_coeff dmcore = numpy.dot(mo[:,:ncore], mo[:,:ncore].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) energy_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 print energy_core virtOrbs = range(ncore+mc.ncas, eris_sp['h1eff'].shape[0]) chunks = len(virtOrbs)/aaavsplit virtRange = [virtOrbs[i:i+chunks] for i in xrange(0, len(virtOrbs), chunks)] for K in range(aaavsplit): currentOrbs = range(ncore, mc.ncas+ncore)+virtRange[K] fout = open('FCIDUMP_aaav%d'%(K),'w') #tools.fcidump.write_head(fout, eris_sp['h1eff'].shape[0]-ncore, mol.nelectron-2*ncore, orbsym= orbsymout[ncore:]) tools.fcidump.write_head(fout, mc.ncas+len(virtRange[K]), mol.nelectron-2*ncore, orbsym= (orbsymout[ncore:ncore+mc.ncas]+orbsymout[virtRange[K][0]:virtRange[K][-1]+1]) ) ij = ncore*(ncore+1)/2 for i in range(len(currentOrbs)): for j in range(ncore, mc.ncas+ncore): for k in range(mc.ncas): for l in range(k+1): I = currentOrbs[i] if abs(eris['ppaa'][I,j,k,l]) > 1.e-8 : fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (eris['ppaa'][I,j,k,l], i+1, j+1-ncore, k+1, l+1)) h1eff = numpy.zeros(shape=(mc.ncas+len(virtRange[K]), mc.ncas+len(virtRange[K]))) h1eff[:mc.ncas, :mc.ncas] = eris_sp['h1eff'][ncore:ncore+mc.ncas,ncore:ncore+mc.ncas] h1eff[mc.ncas:, mc.ncas:] = eris_sp['h1eff'][virtRange[K][0]:virtRange[K][-1]+1, virtRange[K][0]:virtRange[K][-1]+1] h1eff[:mc.ncas, mc.ncas:] = eris_sp['h1eff'][ncore:ncore+mc.ncas, virtRange[K][0]:virtRange[K][-1]+1] h1eff[mc.ncas:, :mc.ncas] = eris_sp['h1eff'][virtRange[K][0]:virtRange[K][-1]+1, ncore:ncore+mc.ncas] tools.fcidump.write_hcore(fout, h1eff, mc.ncas+len(virtRange[K]), tol=1e-8) #tools.fcidump.write_hcore(fout, eris_sp['h1eff'][virtRange[K][0]:virtRange[K][-1]+1, virtRange[K][0]:virtRange[K][-1]+1], len(virtRange[K]), tol=1e-8) fout.write(' %17.9e 0 0 0 0\n' %( mol.energy_nuc()+energy_core-energyE0)) fout.close() nc = ncore+mc.ncas fout = open('FCIDUMP_aaac','w') tools.fcidump.write_head(fout, nc-frozen, mol.nelectron-2*frozen, orbsym= orbsymout[frozen:nc]) for i in range(frozen,nc): for j in range(ncore, nc): for k in range(ncore, nc): for l in range(ncore,k+1): if abs(eris['ppaa'][i,j,k-ncore,l-ncore]) > 1.e-8 : fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (eris['ppaa'][i,j,k-ncore,l-ncore], i+1-frozen, j+1-frozen, k+1-frozen, l+1-frozen)) dmrge = energyE0-mol.energy_nuc()-energy_core ecore_aaac = 0.0; for i in range(frozen,ncore): ecore_aaac += 2.0*eris_sp['h1eff'][i,i] tools.fcidump.write_hcore(fout, eris_sp['h1eff'][frozen:nc,frozen:nc], nc-frozen, tol=1e-8) fout.write(' %17.9e 0 0 0 0\n' %( -dmrge-ecore_aaac)) fout.close() return norbs, energyE0
mol.verbose = 0 mol.atom = [ ['O', (0.000000, 0.000000, 1.210000)], ['C', (0.000000, 0.000000, 0.000000)], ['H', (0.000000, 0.943435, -0.599878)], ['H', (0.000000, -0.943435, -0.599878)], ] mol.basis = {'H': 'cc-pVTZ', 'C': 'cc-pVTZ', 'O': 'cc-pVTZ'} mol.symmetry = 'c1' mol.build() m = scf.RHF(mol) m.kernel() irrep_name = m.mol.irrep_id sym = symm.label_orb_symm(m.mol, irrep_name,m.mol.symm_orb,m.mo_coeff) orbsym = [IRREP_MAP['C1'][i % 10] for i in sym] m.verbose = 4 ehf = m.scf() mc=mcscf.CASCI(m,16,16) mc.verbose = 4 # ci_e = mc.kernel()[0] # print 'CI energy', ci_e # mc.casci() mo_cas_coeff = mc.mo_coeff[:,mc.ncore:mc.ncore+mc.ncas] AOdipInt = mol.intor('cint1e_r_sph', comp=3) MOdipInt = numpy.zeros([3,mo_cas_coeff.shape[1],mo_cas_coeff.shape[1]])
def get_occ(self, mo_energy=None, mo_coeff=None, orbsym=None): ''' We assumed mo_energy are grouped by symmetry irreps, (see function self.eig). The orbitals are sorted after SCF. ''' if mo_energy is None: mo_energy = self.mo_energy mol = self.mol if orbsym is None: if mo_coeff is not None: orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) else: orbsym = [numpy.repeat(ir, mol.symm_orb[i].shape[1]) for i, ir in enumerate(mol.irrep_id)] orbsym = numpy.hstack(orbsym) else: orbsym = numpy.asarray(orbsym) assert(mo_energy.size == orbsym.size) mo_occ = numpy.zeros_like(mo_energy) rest_idx = [] nelec_fix = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = numpy.where(orbsym == ir)[0] if irname in self.irrep_nelec: n = self.irrep_nelec[irname] occ_sort = numpy.argsort(mo_energy[ir_idx].round(9)) occ_idx = ir_idx[occ_sort[:n//2]] mo_occ[occ_idx] = 2 nelec_fix += n else: rest_idx.append(ir_idx) nelec_float = mol.nelectron - nelec_fix assert(nelec_float >= 0) if nelec_float > 0: rest_idx = numpy.hstack(rest_idx) occ_sort = numpy.argsort(mo_energy[rest_idx].round(9)) occ_idx = rest_idx[occ_sort[:nelec_float//2]] mo_occ[occ_idx] = 2 vir_idx = (mo_occ==0) if self.verbose >= logger.INFO and numpy.count_nonzero(vir_idx) > 0: ehomo = max(mo_energy[mo_occ>0 ]) elumo = min(mo_energy[mo_occ==0]) noccs = [] for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = (orbsym == ir) noccs.append(int(mo_occ[ir_idx].sum())) if ehomo in mo_energy[ir_idx]: irhomo = irname if elumo in mo_energy[ir_idx]: irlumo = irname logger.info(self, 'H**O (%s) = %.15g LUMO (%s) = %.15g', irhomo, ehomo, irlumo, elumo) logger.debug(self, 'irrep_nelec = %s', noccs) _dump_mo_energy(mol, mo_energy, mo_occ, ehomo, elumo, orbsym, verbose=self.verbose) return mo_occ
def label_symmetry_(mc, mo_coeff, ci0=None): log = logger.Logger(mc.stdout, mc.verbose) #irrep_name = mc.mol.irrep_name irrep_name = mc.mol.irrep_id s = mc._scf.get_ovlp() ncore = mc.ncore nocc = ncore + mc.ncas try: orbsym = scf.hf_symm.get_orbsym(mc._scf.mol, mo_coeff, s, True) except ValueError: log.warn('mc1step_symm symmetrizes input orbitals') mo_cor = symm.symmetrize_space(mc.mol, mo_coeff[:, :ncore], s=s, check=False) mo_act = symm.symmetrize_space(mc.mol, mo_coeff[:,ncore:nocc], s=s, check=False) mo_vir = symm.symmetrize_space(mc.mol, mo_coeff[:,nocc: ], s=s, check=False) mo_coeff = numpy.hstack((mo_cor,mo_act,mo_vir)) orbsym = symm.label_orb_symm(mc.mol, irrep_name, mc.mol.symm_orb, mo_coeff, s=s) mo_coeff_with_orbsym = lib.tag_array(mo_coeff, orbsym=orbsym) active_orbsym = getattr(mc.fcisolver, 'orbsym', []) if (not getattr(active_orbsym, '__len__', None)) or len(active_orbsym) == 0: mc.fcisolver.orbsym = orbsym[ncore:nocc] log.debug('Active space irreps %s', str(mc.fcisolver.orbsym)) wfnsym = 0 if getattr(mc.fcisolver, 'wfnsym', None) is not None: wfnsym = mc.fcisolver.wfnsym elif ci0 is None: # Guess wfnsym based on HF determinant. mo_coeff may not be HF # canonical orbitals. Some checks are needed to ensure that mo_coeff # are derived from the symmetry adapted SCF calculations. if mo_coeff is mc._scf.mo_coeff: wfnsym = 0 for ir in orbsym[mc._scf.mo_occ == 1]: wfnsym ^= ir mc.fcisolver.wfnsym = wfnsym log.debug('Set CASCI wfnsym %s based on HF determinant', wfnsym) elif getattr(mo_coeff, 'orbsym', None) is not None: # It may be reordered SCF orbitals cas_orb = mo_coeff[:,ncore:nocc] s = reduce(numpy.dot, (cas_orb.T, mc._scf.get_ovlp(), mc._scf.mo_coeff)) if numpy.all(numpy.max(s, axis=1) > 1-1e-9): idx = numpy.argmax(s, axis=1) cas_orbsym = orbsym[ncore:nocc] cas_occ = mc._scf.mo_occ[idx] wfnsym = 0 for ir in cas_orbsym[cas_occ == 1]: wfnsym ^= ir mc.fcisolver.wfnsym = wfnsym log.debug('Active space are constructed from canonical SCF ' 'orbitals %s', idx) log.debug('Set CASCI wfnsym %s based on HF determinant', wfnsym) elif getattr(mc.fcisolver, 'guess_wfnsym', None): wfnsym = mc.fcisolver.guess_wfnsym(mc.ncas, mc.nelecas, ci0, verbose=log) log.debug('CASCI wfnsym %s (based on CI initial guess)', wfnsym) if isinstance(wfnsym, (int, numpy.integer)): wfnsym = symm.irrep_id2name(mc.mol.groupname, wfnsym) log.info('Active space CI wfn symmetry = %s', wfnsym) return mo_coeff_with_orbsym
def writeNumpyforMRLCC(mc, E1, E2, frozen): ncore = mc.ncore nact = mc.ncas norbs = mc.mo_coeff.shape[1] nelec = mc.nelecas[0] + mc.nelecas[1] nvirt = norbs - ncore - nact nc = ncore + nact nactElec = nelec - 2 * ncore #this is chemistry notation int2popo = ao2mo.outcore.general_iofree( mc.mol, (mc.mo_coeff, mc.mo_coeff[:, :nc], mc.mo_coeff, mc.mo_coeff[:, :nc]), compact=False) int2ppoo = ao2mo.outcore.general_iofree( mc.mol, (mc.mo_coeff, mc.mo_coeff, mc.mo_coeff[:, :nc], mc.mo_coeff[:, :nc]), compact=False) int2popo.shape = (norbs, nc, norbs, nc) int2ppoo.shape = (norbs, norbs, nc, nc) mo = mc.mo_coeff dmcore = numpy.dot(mo[:, :frozen], mo[:, :frozen].T) * 2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj - vk * 0.5, mo)) int1 = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_hcore(), mc.mo_coeff)) + vhfcore dmcore = numpy.dot(mo[:, :ncore], mo[:, :ncore].T) * 2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj - vk * 0.5, mo)) int1_eff = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_hcore(), mc.mo_coeff)) + vhfcore #int1_eff = makeheff(int1, int2popo, int2ppoo, E1, ncore, nvirt, frozen) energy_frozen_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 #numpy.save("int/E3",E3) #numpy.save("int/E3B.npy", E3.transpose(0,3,1,4,2,5)) #numpy.save("int/E3C.npy", E3.transpose(5,0,2,4,1,3)) numpy.save("int/E2", numpy.asfortranarray(E2)) numpy.save("int/E1", numpy.asfortranarray(E1)) #numpy.save("int/int2",int2) numpy.save("int/int1", numpy.asfortranarray(int1[frozen:, frozen:])) numpy.save("int/int1eff", numpy.asfortranarray(int1_eff[frozen:, frozen:])) numpy.save( "int/W:caca", numpy.asfortranarray(int2ppoo[frozen:ncore, frozen:ncore, ncore:nc, ncore:nc].transpose(0, 2, 1, 3))) numpy.save( "int/W:caac", numpy.asfortranarray(int2popo[frozen:ncore, ncore:nc, ncore:nc, frozen:ncore].transpose(0, 2, 1, 3))) numpy.save( "int/W:cece", numpy.asfortranarray(int2ppoo[nc:, nc:, frozen:ncore, frozen:ncore].transpose(2, 0, 3, 1))) numpy.save( "int/W:ceec", numpy.asfortranarray(int2popo[nc:, frozen:ncore, nc:, frozen:ncore].transpose(1, 2, 0, 3))) numpy.save( "int/W:aeae", numpy.asfortranarray(int2ppoo[nc:, nc:, ncore:nc, ncore:nc].transpose(2, 0, 3, 1))) numpy.save( "int/W:aeea", numpy.asfortranarray(int2popo[nc:, ncore:nc, nc:, ncore:nc].transpose(1, 2, 0, 3))) numpy.save( "int/W:cccc", numpy.asfortranarray(int2ppoo[frozen:ncore, frozen:ncore, frozen:ncore, frozen:ncore].transpose(0, 2, 1, 3))) numpy.save( "int/W:aaaa", numpy.asfortranarray(int2ppoo[ncore:nc, ncore:nc, ncore:nc, ncore:nc].transpose(0, 2, 1, 3))) feri = h5py.File("int/int2eeee.hdf5", 'w') ao2mo.full(mc.mol, mc.mo_coeff[:, nc:], feri, compact=False) for o in range(nvirt): int2eee = feri['eri_mo'][o * (norbs - nc):(o + 1) * (norbs - nc), :] numpy.asfortranarray(int2eee).tofile("int/W:eeee%04d" % (o)) #store perturbers numpy.save( "int/W:eecc", numpy.asfortranarray(int2popo[nc:, frozen:ncore, nc:, frozen:ncore].transpose(0, 2, 1, 3))) numpy.save( "int/W:eeca", numpy.asfortranarray(int2popo[nc:, frozen:ncore, nc:, ncore:nc].transpose(0, 2, 1, 3))) numpy.save( "int/W:ccaa", numpy.asfortranarray(int2popo[frozen:ncore, ncore:nc, frozen:ncore, ncore:nc].transpose(0, 2, 1, 3))) numpy.save( "int/W:eeaa", numpy.asfortranarray(int2popo[nc:, ncore:nc, nc:, ncore:nc].transpose(0, 2, 1, 3))) numpy.save( "int/W:eaca", numpy.asfortranarray(int2popo[nc:, frozen:ncore, ncore:nc, ncore:nc].transpose(0, 2, 1, 3))) numpy.save( "int/W:aeca", numpy.asfortranarray(int2popo[ncore:nc, frozen:ncore, nc:, ncore:nc].transpose(0, 2, 1, 3))) numpy.save( "int/W:ccae", numpy.asfortranarray(int2popo[frozen:ncore, ncore:nc, nc:, frozen:ncore].transpose(0, 3, 1, 2))) #write FCIDUMP_AAAV and FCIDUMP_AAAC from pyscf import symm mol = mc.mol orbsymout = [] orbsym = [] if (mol.symmetry): orbsym = symm.label_orb_symm(mc.mol, mc.mol.irrep_id, mc.mol.symm_orb, mc.mo_coeff, s=mc._scf.get_ovlp()) if mol.symmetry and orbsym: if mol.groupname.lower() == 'dooh': orbsymout = [dmrg_sym.IRREP_MAP['D2h'][i % 10] for i in orbsym] elif mol.groupname.lower() == 'coov': orbsymout = [dmrg_sym.IRREP_MAP['C2v'][i % 10] for i in orbsym] else: orbsymout = [dmrg_sym.IRREP_MAP[mol.groupname][i] for i in orbsym] else: orbsymout = [] ''' dmcore = numpy.dot(mo[:,frozen:ncore], mo[:,frozen:ncore].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) h1eff = int1+vhfcore energy_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5\ +energy_frozen_core ''' dmcore = numpy.dot(mo[:, :ncore], mo[:, :ncore].T) * 2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj - vk * 0.5, mo)) h1eff = int1_eff energy_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 #print energy_core2+mc.mol.energy_nuc(), energy_core+mc.mol.energy_nuc(), energy_frozen_core+mc.mol.energy_nuc() nc = mc.ncore + mc.ncas energyE0 = 1.0 * numpy.einsum('ij,ij', h1eff[ncore:nc, ncore:nc], E1) #+ 0.5*numpy.einsum('ikjl,ijkl', E2, int2ppoo[ncore:,ncore:,ncore:,ncore:]) for i in range(mc.ncas): for j in range(mc.ncas): for k in range(mc.ncas): for l in range(mc.ncas): I, J = max(i, j) + ncore, min(i, j) + ncore K, L = max(k, l) + ncore, min(k, l) + ncore energyE0 += 0.5 * E2[i, k, j, l] * int2ppoo[i + ncore, j + ncore, k + ncore, l + ncore] energyE0 += energy_core energyE0 += mc.mol.energy_nuc() print "Energy = ", energyE0 fout = open('FCIDUMP_aaav0', 'w') tools.fcidump.write_head(fout, int1.shape[0] - ncore, mc.mol.nelectron - 2 * ncore, orbsym=orbsymout[ncore:]) for i in range(ncore, int1.shape[0]): for j in range(ncore, i + 1): for k in range(mc.ncas): for l in range(k + 1): if abs(int2ppoo[i, j, k + ncore, l + ncore]) > 1.e-8: fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (int2ppoo[i,j, k+ncore,l+ncore], i+1-ncore, j+1-ncore, k+1, l+1)) if (j >= nc and abs(int2popo[i, k + ncore, j, l + ncore]) > 1.e-8): fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (int2popo[i,k+ncore,j, l+ncore], i+1-ncore, k+1, l+1, j+1-ncore)) if (j >= nc and abs(int2popo[i, l + ncore, j, k + ncore]) > 1.e-8): fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (int2popo[i,l+ncore, j, k+ncore], i+1-ncore, l+1, k+1, j+1-ncore)) tools.fcidump.write_hcore(fout, h1eff[ncore:, ncore:], int1.shape[0] - ncore, tol=1e-8) fout.write(' %17.9e 0 0 0 0\n' % (mc.mol.energy_nuc() + energy_core - energyE0)) fout.close() nc = ncore + mc.ncas eri1cas = ao2mo.outcore.general_iofree( mc.mol, (mc.mo_coeff[:, frozen:nc], mc.mo_coeff[:, frozen:nc], mc.mo_coeff[:, frozen:nc], mc.mo_coeff[:, frozen:nc]), compact=True) tools.fcidump.from_integrals("FCIDUMP_aaac", int1[frozen:nc, frozen:nc], eri1cas, nc - frozen, mc.mol.nelectron - 2 * frozen, nuc=mc.mol.energy_nuc() - energyE0, orbsym=orbsymout[frozen:nc], tol=1e-8) return energyE0, norbs
def analyze(mf, verbose=logger.DEBUG): from pyscf.lo import orth from pyscf.tools import dump_mat mo_energy = mf.mo_energy mo_occ = mf.mo_occ mo_coeff = mf.mo_coeff mol = mf.mol log = pyscf.lib.logger.Logger(mf.stdout, verbose) nirrep = len(mol.irrep_id) ovlp_ao = mf.get_ovlp() orbsyma = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff[0], s=ovlp_ao) orbsymb = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff[1], s=ovlp_ao) orbsyma = numpy.array(orbsyma) orbsymb = numpy.array(orbsymb) tot_sym = 0 noccsa = [sum(orbsyma[mo_occ[0] > 0] == ir) for ir in mol.irrep_id] noccsb = [sum(orbsymb[mo_occ[1] > 0] == ir) for ir in mol.irrep_id] for i, ir in enumerate(mol.irrep_id): if (noccsa[i] + noccsb[i]) % 2: tot_sym ^= ir if mol.groupname in ('Dooh', 'Coov', 'SO3'): log.note('TODO: total symmetry for %s', mol.groupname) else: log.note('total symmetry = %s', symm.irrep_id2name(mol.groupname, tot_sym)) log.note('alpha occupancy for each irrep: ' + (' %4s' * nirrep), *mol.irrep_name) log.note(' ' + (' %4d' * nirrep), *noccsa) log.note('beta occupancy for each irrep: ' + (' %4s' * nirrep), *mol.irrep_name) log.note(' ' + (' %4d' * nirrep), *noccsb) ss, s = mf.spin_square( (mo_coeff[0][:, mo_occ[0] > 0], mo_coeff[1][:, mo_occ[1] > 0]), ovlp_ao) log.note('multiplicity <S^2> = %.8g 2S+1 = %.8g', ss, s) if verbose >= logger.NOTE: log.note('**** MO energy ****') irname_full = {} for k, ir in enumerate(mol.irrep_id): irname_full[ir] = mol.irrep_name[k] irorbcnt = {} for k, j in enumerate(orbsyma): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note('alpha MO #%d (%s #%d), energy= %.15g occ= %g', k + 1, irname_full[j], irorbcnt[j], mo_energy[0][k], mo_occ[0][k]) irorbcnt = {} for k, j in enumerate(orbsymb): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note('beta MO #%d (%s #%d), energy= %.15g occ= %g', k + 1, irname_full[j], irorbcnt[j], mo_energy[1][k], mo_occ[1][k]) ovlp_ao = mf.get_ovlp() if mf.verbose >= logger.DEBUG: label = mol.spheric_labels(True) molabel = [] irorbcnt = {} for k, j in enumerate(orbsyma): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 molabel.append('#%-d(%s #%d)' % (k + 1, irname_full[j], irorbcnt[j])) log.debug( ' ** alpha MO coefficients (expansion on meta-Lowdin AOs) **') orth_coeff = orth.orth_ao(mol, 'meta_lowdin', s=ovlp_ao) c_inv = numpy.dot(orth_coeff.T, ovlp_ao) dump_mat.dump_rec(mol.stdout, c_inv.dot(mo_coeff[0]), label, molabel, start=1) molabel = [] irorbcnt = {} for k, j in enumerate(orbsymb): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 molabel.append('#%-d(%s #%d)' % (k + 1, irname_full[j], irorbcnt[j])) log.debug(' ** beta MO coefficients (expansion on meta-Lowdin AOs) **') dump_mat.dump_rec(mol.stdout, c_inv.dot(mo_coeff[1]), label, molabel, start=1) dm = mf.make_rdm1(mo_coeff, mo_occ) return mf.mulliken_meta(mol, dm, s=ovlp_ao, verbose=log)
def caslst_by_irrep(casscf, mo_coeff, cas_irrep_nocc, cas_irrep_ncore=None, s=None, base=1): '''Given number of active orbitals for each irrep, return the orbital indices of active space Args: casscf : an :class:`CASSCF` or :class:`CASCI` object cas_irrep_nocc : list or dict Number of active orbitals for each irrep. It can be a dict, eg {'A1': 2, 'B2': 4} to indicate the active space size based on irrep names, or {0: 2, 3: 4} for irrep Id, or a list [2, 0, 0, 4] (identical to {0: 2, 3: 4}) in which the list index is served as the irrep Id. Kwargs: cas_irrep_ncore : list or dict Number of closed shells for each irrep. It can be a dict, eg {'A1': 6, 'B2': 4} to indicate the closed shells based on irrep names, or {0: 6, 3: 4} for irrep Id, or a list [6, 0, 0, 4] (identical to {0: 6, 3: 4}) in which the list index is served as the irrep Id. If cas_irrep_ncore is not given, the program will generate a guess based on the lowest :attr:`CASCI.ncore` orbitals. s : ndarray overlap matrix base : int 0-based (C-like) or 1-based (Fortran-like) caslst Returns: A list of orbital indices Examples: >>> from pyscf import gto, scf, mcscf >>> mol = gto.M(atom='N 0 0 0; N 0 0 1', basis='ccpvtz', symmetry=True, verbose=0) >>> mf = scf.RHF(mol) >>> mf.kernel() >>> mc = mcscf.CASSCF(mf, 12, 4) >>> mcscf.caslst_by_irrep(mc, mf.mo_coeff, {'E1gx':4, 'E1gy':4, 'E1ux':2, 'E1uy':2}) [5, 7, 8, 10, 11, 14, 15, 20, 25, 26, 31, 32] ''' mol = casscf.mol log = logger.Logger(casscf.stdout, casscf.verbose) if s is None: s = casscf._scf.get_ovlp() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s) orbsym = numpy.asarray(orbsym) ncore = casscf.ncore irreps = set(orbsym) if cas_irrep_ncore is not None: irrep_ncore = {} for k, v in cas_irrep_ncore.items(): if isinstance(k, str): irrep_ncore[symm.irrep_name2id(mol.groupname, k)] = v else: irrep_ncore[k] = v ncore_rest = casscf.ncore - sum(irrep_ncore.values()) if ncore_rest > 0: # guess core configuration mask = numpy.ones(len(orbsym), dtype=bool) for ir in irrep_ncore: mask[orbsym == ir] = False core_rest = orbsym[mask][:ncore_rest] core_rest = dict([(ir, numpy.count_nonzero(core_rest == ir)) for ir in set(core_rest)]) log.info('Given core space %s < casscf core size %d', cas_irrep_ncore, casscf.ncore) log.info('Add %s to core configuration', core_rest) irrep_ncore.update(core_rest) elif ncore_rest < 0: raise ValueError('Given core space %s > casscf core size %d' % (cas_irrep_ncore, casscf.ncore)) else: irrep_ncore = dict([(ir, sum(orbsym[:ncore] == ir)) for ir in irreps]) if not isinstance(cas_irrep_nocc, dict): # list => dict cas_irrep_nocc = dict([(ir, n) for ir, n in enumerate(cas_irrep_nocc) if n > 0]) irrep_ncas = {} for k, v in cas_irrep_nocc.items(): if isinstance(k, str): irrep_ncas[symm.irrep_name2id(mol.groupname, k)] = v else: irrep_ncas[k] = v ncas_rest = casscf.ncas - sum(irrep_ncas.values()) if ncas_rest > 0: mask = numpy.ones(len(orbsym), dtype=bool) # remove core and specified active space for ir in irrep_ncas: mask[orbsym == ir] = False for ir, ncore in irrep_ncore.items(): idx = numpy.where(orbsym == ir)[0] mask[idx[:ncore]] = False cas_rest = orbsym[mask][:ncas_rest] cas_rest = dict([(ir, numpy.count_nonzero(cas_rest == ir)) for ir in set(cas_rest)]) log.info('Given active space %s < casscf active space size %d', cas_irrep_nocc, casscf.ncas) log.info('Add %s to active space', cas_rest) irrep_ncas.update(cas_rest) elif ncas_rest < 0: raise ValueError( 'Given active space %s > casscf active space size %d' % (cas_irrep_nocc, casscf.ncas)) caslst = [] for ir, ncas in irrep_ncas.items(): if ncas > 0: if ir in irrep_ncore: nc = irrep_ncore[ir] else: nc = 0 no = nc + ncas idx = numpy.where(orbsym == ir)[0] caslst.extend(idx[nc:no]) caslst = numpy.sort(numpy.asarray(caslst)) + base if len(caslst) < casscf.ncas: raise ValueError('Not enough orbitals found for core %s, cas %s' % (cas_irrep_ncore, cas_irrep_nocc)) if log.verbose >= logger.INFO: log.info( 'ncore for each irreps %s', dict([(symm.irrep_id2name(mol.groupname, k), v) for k, v in irrep_ncore.items()])) log.info( 'ncas for each irreps %s', dict([(symm.irrep_id2name(mol.groupname, k), v) for k, v in irrep_ncas.items()])) log.info('(%d-based) caslst = %s', base, caslst) return caslst
def analyze(self, verbose=logger.DEBUG): from pyscf.lo import orth from pyscf.tools import dump_mat mo_energy = self.mo_energy mo_occ = self.mo_occ mo_coeff = self.mo_coeff log = logger.Logger(self.stdout, verbose) mol = self.mol nirrep = len(mol.irrep_id) ovlp_ao = self.get_ovlp() orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_coeff, s=ovlp_ao) orbsym = numpy.array(orbsym) wfnsym = 0 ndoccs = [] nsoccs = [] for k,ir in enumerate(mol.irrep_id): ndoccs.append(sum(orbsym[mo_occ==2] == ir)) nsoccs.append(sum(orbsym[mo_occ==1] == ir)) if nsoccs[k] % 2: wfnsym ^= ir if mol.groupname in ('Dooh', 'Coov'): log.info('TODO: total symmetry for %s', mol.groupname) else: log.info('total symmetry = %s', symm.irrep_id2name(mol.groupname, wfnsym)) log.info('occupancy for each irrep: ' + (' %4s'*nirrep), *mol.irrep_name) log.info('double occ ' + (' %4d'*nirrep), *ndoccs) log.info('single occ ' + (' %4d'*nirrep), *nsoccs) log.info('**** MO energy ****') irname_full = {} for k,ir in enumerate(mol.irrep_id): irname_full[ir] = mol.irrep_name[k] irorbcnt = {} if self._focka_ao is None: for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note('MO #%-3d (%s #%-2d), energy= %-18.15g occ= %g', k+1, irname_full[j], irorbcnt[j], mo_energy[k], mo_occ[k]) else: mo_ea = numpy.einsum('ik,ik->k', mo_coeff, self._focka_ao.dot(mo_coeff)) mo_eb = numpy.einsum('ik,ik->k', mo_coeff, self._fockb_ao.dot(mo_coeff)) log.note(' Roothaan | alpha | beta') for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 log.note('MO #%-4d(%-3s #%-2d) energy= %-18.15g | %-18.15g | %-18.15g occ= %g', k+1, irname_full[j], irorbcnt[j], mo_energy[k], mo_ea[k], mo_eb[k], mo_occ[k]) if verbose >= logger.DEBUG: label = mol.spheric_labels(True) molabel = [] irorbcnt = {} for k, j in enumerate(orbsym): if j in irorbcnt: irorbcnt[j] += 1 else: irorbcnt[j] = 1 molabel.append('#%-d(%s #%d)' % (k+1, irname_full[j], irorbcnt[j])) log.debug(' ** MO coefficients (expansion on meta-Lowdin AOs) **') orth_coeff = orth.orth_ao(mol, 'meta_lowdin', s=ovlp_ao) c = reduce(numpy.dot, (orth_coeff.T, ovlp_ao, mo_coeff)) dump_mat.dump_rec(self.stdout, c, label, molabel, start=1) dm = self.make_rdm1(mo_coeff, mo_occ) return self.mulliken_meta(mol, dm, s=ovlp_ao, verbose=verbose)
def get_occ(self, mo_energy=None, mo_coeff=None, orbsym=None): ''' We assumed mo_energy are grouped by symmetry irreps, (see function self.eig). The orbitals are sorted after SCF. ''' if mo_energy is None: mo_energy = self.mo_energy mol = self.mol if not mol.symmetry: return hf.RHF.get_occ(self, mo_energy, mo_coeff) if orbsym is None: if mo_coeff is not None: orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) else: orbsym = [ numpy.repeat(ir, mol.symm_orb[i].shape[1]) for i, ir in enumerate(mol.irrep_id) ] orbsym = numpy.hstack(orbsym) else: orbsym = numpy.asarray(orbsym) assert (mo_energy.size == orbsym.size) mo_occ = numpy.zeros_like(mo_energy) rest_idx = [] nelec_fix = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = numpy.where(orbsym == ir)[0] if irname in self.irrep_nelec: n = self.irrep_nelec[irname] occ_sort = numpy.argsort(mo_energy[ir_idx].round(9)) occ_idx = ir_idx[occ_sort[:n // 2]] mo_occ[occ_idx] = 2 nelec_fix += n else: rest_idx.append(ir_idx) nelec_float = mol.nelectron - nelec_fix assert (nelec_float >= 0) if nelec_float > 0: rest_idx = numpy.hstack(rest_idx) occ_sort = numpy.argsort(mo_energy[rest_idx].round(9)) occ_idx = rest_idx[occ_sort[:nelec_float // 2]] mo_occ[occ_idx] = 2 vir_idx = (mo_occ == 0) if self.verbose >= logger.INFO and numpy.count_nonzero(vir_idx) > 0: ehomo = max(mo_energy[mo_occ > 0]) elumo = min(mo_energy[mo_occ == 0]) noccs = [] for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = (orbsym == ir) noccs.append(int(mo_occ[ir_idx].sum())) if ehomo in mo_energy[ir_idx]: irhomo = irname if elumo in mo_energy[ir_idx]: irlumo = irname logger.info(self, 'H**O (%s) = %.15g LUMO (%s) = %.15g', irhomo, ehomo, irlumo, elumo) logger.debug(self, 'irrep_nelec = %s', noccs) _dump_mo_energy(mol, mo_energy, mo_occ, ehomo, elumo, orbsym, verbose=self.verbose) return mo_occ
def writeNumpyforMRLCC(mc, E1, E2, frozen) : ncore = mc.ncore nact = mc.ncas norbs = mc.mo_coeff.shape[1] nelec = mc.nelecas[0]+mc.nelecas[1] nvirt = norbs - ncore-nact nc = ncore+nact nactElec = nelec - 2*ncore #this is chemistry notation int2popo = ao2mo.outcore.general_iofree(mc.mol, (mc.mo_coeff, mc.mo_coeff[:,:nc], mc.mo_coeff, mc.mo_coeff[:,:nc]), compact=False) int2ppoo = ao2mo.outcore.general_iofree(mc.mol, (mc.mo_coeff, mc.mo_coeff, mc.mo_coeff[:,:nc], mc.mo_coeff[:,:nc]), compact=False) int2popo.shape=(norbs, nc, norbs, nc) int2ppoo.shape=(norbs, norbs, nc, nc) mo = mc.mo_coeff dmcore = numpy.dot(mo[:,:frozen], mo[:,:frozen].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) int1 = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_hcore(), mc.mo_coeff)) +vhfcore dmcore = numpy.dot(mo[:,:ncore], mo[:,:ncore].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) int1_eff = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_hcore(), mc.mo_coeff)) +vhfcore #int1_eff = makeheff(int1, int2popo, int2ppoo, E1, ncore, nvirt, frozen) energy_frozen_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 #numpy.save("int/E3",E3) #numpy.save("int/E3B.npy", E3.transpose(0,3,1,4,2,5)) #numpy.save("int/E3C.npy", E3.transpose(5,0,2,4,1,3)) numpy.save("int/E2",numpy.asfortranarray(E2)) numpy.save("int/E1",numpy.asfortranarray(E1)) #numpy.save("int/int2",int2) numpy.save("int/int1",numpy.asfortranarray(int1[frozen:,frozen:])) numpy.save("int/int1eff",numpy.asfortranarray(int1_eff[frozen:, frozen:])) numpy.save("int/W:caca", numpy.asfortranarray(int2ppoo[frozen:ncore, frozen:ncore, ncore:nc, ncore:nc].transpose(0,2,1,3))) numpy.save("int/W:caac", numpy.asfortranarray(int2popo[frozen:ncore,ncore:nc, ncore:nc, frozen:ncore].transpose(0,2,1,3))) numpy.save("int/W:cece", numpy.asfortranarray(int2ppoo[nc:, nc:, frozen:ncore, frozen:ncore].transpose(2,0,3,1))) numpy.save("int/W:ceec", numpy.asfortranarray(int2popo[nc:, frozen:ncore, nc:, frozen:ncore].transpose(1,2,0,3))) numpy.save("int/W:aeae", numpy.asfortranarray(int2ppoo[nc:, nc:, ncore:nc,ncore:nc].transpose(2,0,3,1))) numpy.save("int/W:aeea", numpy.asfortranarray(int2popo[nc:, ncore:nc,nc:, ncore:nc].transpose(1,2,0,3))) numpy.save("int/W:cccc", numpy.asfortranarray(int2ppoo[frozen:ncore,frozen:ncore, frozen:ncore, frozen:ncore].transpose(0,2,1,3))) numpy.save("int/W:aaaa", numpy.asfortranarray(int2ppoo[ncore:nc,ncore:nc, ncore:nc, ncore:nc].transpose(0,2,1,3))) feri = h5py.File("int/int2eeee.hdf5", 'w') ao2mo.full(mc.mol, mc.mo_coeff[:,nc:], feri, compact=False) for o in range(nvirt): int2eee = feri['eri_mo'][o*(norbs-nc):(o+1)*(norbs-nc),:] numpy.asfortranarray(int2eee).tofile("int/W:eeee%04d"%(o)) #store perturbers numpy.save("int/W:eecc", numpy.asfortranarray(int2popo[nc:,frozen:ncore,nc:,frozen:ncore].transpose(0,2,1,3))) numpy.save("int/W:eeca", numpy.asfortranarray(int2popo[nc:,frozen:ncore, nc:, ncore:nc].transpose(0,2,1,3))) numpy.save("int/W:ccaa", numpy.asfortranarray(int2popo[frozen:ncore,ncore:nc, frozen:ncore, ncore:nc].transpose(0,2,1,3))) numpy.save("int/W:eeaa", numpy.asfortranarray(int2popo[nc:,ncore:nc, nc:, ncore:nc].transpose(0,2,1,3))) numpy.save("int/W:eaca", numpy.asfortranarray(int2popo[nc:,frozen:ncore, ncore:nc, ncore:nc].transpose(0,2,1,3))) numpy.save("int/W:aeca", numpy.asfortranarray(int2popo[ncore:nc,frozen:ncore, nc:,ncore:nc].transpose(0,2,1,3))) numpy.save("int/W:ccae", numpy.asfortranarray(int2popo[frozen:ncore,ncore:nc, nc:, frozen:ncore].transpose(0,3,1,2))) #write FCIDUMP_AAAV and FCIDUMP_AAAC from pyscf import symm mol = mc.mol orbsymout=[] orbsym = [] if (mol.symmetry): orbsym = symm.label_orb_symm(mc.mol, mc.mol.irrep_id, mc.mol.symm_orb, mc.mo_coeff, s=mc._scf.get_ovlp()) if mol.symmetry and orbsym: if mol.groupname.lower() == 'dooh': orbsymout = [dmrg_sym.IRREP_MAP['D2h'][i % 10] for i in orbsym] elif mol.groupname.lower() == 'coov': orbsymout = [dmrg_sym.IRREP_MAP['C2v'][i % 10] for i in orbsym] else: orbsymout = [dmrg_sym.IRREP_MAP[mol.groupname][i] for i in orbsym] else: orbsymout = [] ''' dmcore = numpy.dot(mo[:,frozen:ncore], mo[:,frozen:ncore].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) h1eff = int1+vhfcore energy_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5\ +energy_frozen_core ''' dmcore = numpy.dot(mo[:,:ncore], mo[:,:ncore].T)*2 vj, vk = mc._scf.get_jk(mc.mol, dmcore) vhfcore = reduce(numpy.dot, (mo.T, vj-vk*0.5, mo)) h1eff = int1_eff energy_core = numpy.einsum('ij,ji', dmcore, mc.get_hcore()) \ + numpy.einsum('ij,ji', dmcore, vj-0.5*vk) * .5 #print energy_core2+mc.mol.energy_nuc(), energy_core+mc.mol.energy_nuc(), energy_frozen_core+mc.mol.energy_nuc() nc = mc.ncore+mc.ncas energyE0 = 1.0*numpy.einsum('ij,ij', h1eff[ncore:nc, ncore:nc], E1) #+ 0.5*numpy.einsum('ikjl,ijkl', E2, int2ppoo[ncore:,ncore:,ncore:,ncore:]) for i in range(mc.ncas): for j in range(mc.ncas): for k in range(mc.ncas): for l in range(mc.ncas): I,J = max(i,j)+ncore, min(i,j)+ncore K,L = max(k,l)+ncore, min(k,l)+ncore energyE0 += 0.5*E2[i,k,j,l] * int2ppoo[i+ncore, j+ncore, k+ncore, l+ncore] energyE0 += energy_core energyE0 += mc.mol.energy_nuc() print "Energy = ", energyE0 fout = open('FCIDUMP_aaav0','w') tools.fcidump.write_head(fout, int1.shape[0]-ncore, mc.mol.nelectron-2*ncore, orbsym= orbsymout[ncore:]) for i in range(ncore,int1.shape[0]): for j in range(ncore, i+1): for k in range(mc.ncas): for l in range(k+1): if abs(int2ppoo[i,j, k+ncore,l+ncore]) > 1.e-8 : fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (int2ppoo[i,j, k+ncore,l+ncore], i+1-ncore, j+1-ncore, k+1, l+1)) if (j >= nc and abs(int2popo[i, k+ncore, j, l+ncore]) > 1.e-8): fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (int2popo[i,k+ncore,j, l+ncore], i+1-ncore, k+1, l+1, j+1-ncore)) if (j >= nc and abs(int2popo[i, l+ncore, j, k+ncore]) > 1.e-8): fout.write(' %17.9e %4d %4d %4d %4d\n' \ % (int2popo[i,l+ncore, j, k+ncore], i+1-ncore, l+1, k+1, j+1-ncore)) tools.fcidump.write_hcore(fout, h1eff[ncore:,ncore:], int1.shape[0]-ncore, tol=1e-8) fout.write(' %17.9e 0 0 0 0\n' %( mc.mol.energy_nuc()+energy_core-energyE0)) fout.close() nc = ncore+mc.ncas eri1cas = ao2mo.outcore.general_iofree(mc.mol, (mc.mo_coeff[:,frozen:nc], mc.mo_coeff[:,frozen:nc], mc.mo_coeff[:,frozen:nc], mc.mo_coeff[:,frozen:nc]), compact=True) tools.fcidump.from_integrals("FCIDUMP_aaac", int1[frozen:nc,frozen:nc], eri1cas, nc-frozen, mc.mol.nelectron-2*frozen, nuc=mc.mol.energy_nuc()-energyE0, orbsym = orbsymout[frozen:nc], tol=1e-8) return energyE0, norbs
# # call mol.build to construct symmetry adapted basis. # # NOTE the molecule orientation. Simply assigning mol.build(symmetry=True) # may change the orientation of the molecule. If the orientation is different # to the orientation of the orbital space, the orbitals cannot be symmetrized. # To keep the molecule orientation fixed, we need specify the molecular # symmetry. # mol.build(0, 0, symmetry='D2') # # H**O-2 H**O-1 H**O are degenerated. They may not be properly symmetrized. # try: irrep_ids = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo) except ValueError: print('The orbital symmetry cannot be labelled because some ' 'degenerated orbitals are not symmetrized.\n' 'Degenerated H**O energy: %s' % mf.mo_energy[2:5]) nocc = mol.nelectron // 2 occ_orb = symm.symmetrize_space(mol, mo[:,:nocc]) irrep_ids = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, occ_orb) print('Occupied orbital symmetry: %s' % irrep_ids) virt_orb = symm.symmetrize_space(mol, mo[:,nocc:]) irrep_ids = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, virt_orb) print('Virtual orbital symmetry: %s' % irrep_ids)
'O': 'sto-3g',} mol.symmetry = 1 mol.build() m = scf.RHF(mol) ehf = m.scf() norb = m.mo_coeff.shape[1] nelec = mol.nelectron h1e = reduce(numpy.dot, (m.mo_coeff.T, scf.hf.get_hcore(mol), m.mo_coeff)) eri = ao2mo.incore.full(m._eri, m.mo_coeff) numpy.random.seed(1) na = cistring.num_strings(norb, nelec//2) fcivec = numpy.random.random((na,na)) fcivec = fcivec + fcivec.T orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, m.mo_coeff) print(numpy.allclose(orbsym, [0, 0, 2, 0, 3, 0, 2])) cis = FCISolver(mol) cis.orbsym = cis.orbsym ci1 = cis.contract_2e(eri, fcivec, norb, nelec) ci1ref = direct_spin0.contract_2e(eri, fcivec, norb, nelec) print(numpy.allclose(ci1ref, ci1)) mol.atom = [['H', (0, 0, i)] for i in range(8)] mol.basis = {'H': 'sto-3g'} mol.symmetry = True mol.build() m = scf.RHF(mol) ehf = m.scf() norb = m.mo_coeff.shape[1]
def dmrgci(mf, TwoS, Nelec, Irrep, DSU2, Econv, MaxSweeps, NoisePrefac, frozen, active): ### Check whether the frozen and active arrays make sense ### Norbs = mf.mol.nao_nr() assert (np.sum(frozen < Norbs) == len(frozen)) assert (np.sum(active < Norbs) == len(active)) assert (np.sum(frozen >= 0) == len(frozen)) assert (np.sum(active >= 0) == len(active)) mo_occ = mf.mo_occ for item in frozen: assert (mo_occ[item] == 2) for item2 in active: assert (item != item2) frozen = frozen[frozen.argsort()] active = active[active.argsort()] ### Get orbital information ### if (len(frozen) > 0): mo_fro = mf.mo_coeff[:, frozen] mo_act = mf.mo_coeff[:, active] Orbsym = np.array( symm.label_orb_symm( mf.mol, mf.mol.irrep_id, mf.mol.symm_orb, mf.mo_coeff))[active] # Same conventions in PySCF and CheMPS2 for cnt in range(len(Orbsym)): # https://github.com/sunqm/pyscf/blob/master/symm/basis.py#L128 Orbsym[cnt] = Orbsym[cnt] % 10 ### Get the JK matrix for the doubly occupied frozen orbitals ### if (len(frozen) > 0): DM_docc = np.zeros([Norbs], dtype=float) DM_docc[frozen] = 2.0 JK_docc = fetchJK_mo(mf, np.diag(DM_docc), mf.mo_coeff) JK_fro = (JK_docc[:, frozen])[frozen, :] JK_act = (JK_docc[:, active])[active, :] ### Build the rotated MO matrix elements ### Lrot = len(active) OEIao = mf.mol.intor('cint1e_kin_sph') + mf.mol.intor('cint1e_nuc_sph') CONST = mf.mol.energy_nuc() OEImo = np.dot(np.dot(mo_act.T, OEIao), mo_act) if (len(frozen) > 0): CONST += np.einsum( 'ii->', 2 * np.dot(np.dot(mo_fro.T, OEIao), mo_fro) + JK_fro) OEImo += JK_act #TEINT in chemical notation; also possible to pass different shapes; see http://www.sunqm.net/pyscf/tutorial.html#hf-mp2-mcscf TEImo = ao2mo.outcore.full_iofree(mf.mol, mo_act, compact=False).reshape( Lrot, Lrot, Lrot, Lrot) ### Reorder per irrep ### --> not strictly necessary for CheMPS2, but converges faster idx = Orbsym.argsort() OEImo = OEImo[:, idx] OEImo = OEImo[idx, :] TEImo = TEImo[:, :, :, idx] TEImo = TEImo[:, :, idx, :] TEImo = TEImo[:, idx, :, :] TEImo = TEImo[idx, :, :, :] Orbsym = Orbsym[idx] ### Do DMRG calculation with CheMPS2 ### EnergyDMRG, TwoRDM = call_chemps2(Lrot, mf.mol.groupname, Orbsym, CONST, OEImo, TEImo, TwoS, Nelec - 2 * len(frozen), Irrep, DSU2, Econv, MaxSweeps, NoisePrefac) ### Reorder back to original ordering ### idx2 = idx.argsort() assert (np.linalg.norm(idx[idx2] - idx2[idx]) < 1e-10) TwoRDM = TwoRDM[:, :, :, idx2] TwoRDM = TwoRDM[:, :, idx2, :] TwoRDM = TwoRDM[:, idx2, :, :] TwoRDM = TwoRDM[idx2, :, :, :] return (EnergyDMRG, TwoRDM)
idx = ordering_diatomics(mol, C, basis_set=basis_set) norb = cas_nstop - cas_nstart h, g = reorder_integrals(idx, h, g) C = C[:, idx] mo_energy = mo_energy[idx] dm_aa = dm_aa[:, idx] dm_aa = dm_aa[idx, :] dm_bb = dm_bb[:, idx] dm_bb = dm_bb[idx, :] print(h) print(dm_aa) from pyscf import symm mo = symm.symmetrize_orb(mol, C) osym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo) #symm.addons.symmetrize_space(mol, mo, s=None, check=True, tol=1e-07) for i in range(len(osym)): print("%4d %8s %16.8f" % (i, osym[i], mo_energy[i])) print("r:", r0) print(h) if do_tci: oocmf = CmfSolver(h, g, ecore, blocks, init_fspace, C, max_roots=100) oocmf.init((dm_aa, dm_bb)) oocmf.form_extra_fspace() #form excited fock space configurations h = oocmf.h g = oocmf.g
# # Symmetry adapted FCI solver can be called with arbitrary Hamiltonian. In the # following example, you need to prepare 1-electron and 2-electron integrals, # core energy shift, and the symmetry of orbitals. # cas_idx = numpy.arange(2, 10) core_idx = numpy.arange(2) mo_cas = m.mo_coeff[:, cas_idx] mo_core = m.mo_coeff[:, core_idx] dm_core = mo_core.dot(mo_core.T) * 2 vhf_core = m.get_veff(mol, dm_core) h1 = mo_cas.T.dot(m.get_hcore() + vhf_core).dot(mo_cas) h2 = ao2mo.kernel(mol, mo_cas) ecore = (numpy.einsum('ij,ji', dm_core, m.get_hcore()) + .5 * numpy.einsum('ij,ji', dm_core, vhf_core) + m.energy_nuc()) orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo_cas) norb = mo_cas.shape[1] ncore = mo_core.shape[1] nelec = mol.nelectron - ncore * 2 fs = fci.direct_spin0_symm.FCI(mol) fs.wfnsym = 'A2' e, c = fs.kernel(h1, h2, norb, nelec, ecore=ecore, orbsym=orbsym, verbose=5) print('Energy of %s state %.12f' % (fs.wfnsym, e)) # # mcscf module has a function h1e_for_cas to generate 1-electron Hamiltonian and # core energy. # cas_idx = numpy.arange(2, 10) core_idx = numpy.arange(2)
def get_occ(self, mo_energy=None, mo_coeff=None, orbsym=None): if mo_energy is None: mo_energy = self.mo_energy mol = self.mol if mo_coeff is None or self._focka_ao is None: mo_ea = mo_eb = mo_energy else: mo_ea = numpy.einsum('ik,ik->k', mo_coeff, self._focka_ao.dot(mo_coeff)) mo_eb = numpy.einsum('ik,ik->k', mo_coeff, self._fockb_ao.dot(mo_coeff)) nmo = mo_ea.size mo_occ = numpy.zeros(nmo) if orbsym is None: if mo_coeff is not None: orbsym = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff, self.get_ovlp(), False) orbsym = numpy.asarray(orbsym) else: orbsym = [numpy.repeat(ir, mol.symm_orb[i].shape[1]) for i, ir in enumerate(mol.irrep_id)] orbsym = numpy.hstack(orbsym) else: orbsym = numpy.asarray(orbsym) assert(mo_energy.size == orbsym.size) float_idx = [] neleca_fix = 0 nelecb_fix = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = numpy.where(orbsym == ir)[0] if irname in self.irrep_nelec: if isinstance(self.irrep_nelec[irname], (int, numpy.integer)): nelecb = self.irrep_nelec[irname] // 2 neleca = self.irrep_nelec[irname] - nelecb else: neleca, nelecb = self.irrep_nelec[irname] mo_occ[ir_idx] = rohf._fill_rohf_occ(mo_energy[ir_idx], mo_ea[ir_idx], mo_eb[ir_idx], nelecb, neleca-nelecb) neleca_fix += neleca nelecb_fix += nelecb else: float_idx.append(ir_idx) nelec_float = mol.nelectron - neleca_fix - nelecb_fix assert(nelec_float >= 0) if len(float_idx) > 0: float_idx = numpy.hstack(float_idx) nopen = mol.spin - (neleca_fix - nelecb_fix) ncore = (nelec_float - nopen)//2 mo_occ[float_idx] = rohf._fill_rohf_occ(mo_energy[float_idx], mo_ea[float_idx], mo_eb[float_idx], ncore, nopen) ncore = self.nelec[1] nocc = self.nelec[0] nopen = nocc - ncore vir_idx = (mo_occ==0) if self.verbose >= logger.INFO and nocc < nmo and ncore > 0: ehomo = max(mo_energy[mo_occ> 0]) elumo = min(mo_energy[mo_occ==0]) ndoccs = [] nsoccs = [] for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idx = (orbsym == ir) ndoccs.append(numpy.count_nonzero(mo_occ[ir_idx]==2)) nsoccs.append(numpy.count_nonzero(mo_occ[ir_idx]==1)) if ehomo in mo_energy[ir_idx]: irhomo = irname if elumo in mo_energy[ir_idx]: irlumo = irname # to help self.eigh compute orbital energy self._irrep_doccs = ndoccs self._irrep_soccs = nsoccs logger.info(self, 'H**O (%s) = %.15g LUMO (%s) = %.15g', irhomo, ehomo, irlumo, elumo) logger.debug(self, 'double occ irrep_nelec = %s', ndoccs) logger.debug(self, 'single occ irrep_nelec = %s', nsoccs) #_dump_mo_energy(mol, mo_energy, mo_occ, ehomo, elumo, orbsym, # verbose=self.verbose) if nopen > 0: core_idx = mo_occ == 2 open_idx = mo_occ == 1 vir_idx = mo_occ == 0 logger.debug(self, ' Roothaan | alpha | beta') logger.debug(self, ' Highest 2-occ = %18.15g | %18.15g | %18.15g', max(mo_energy[core_idx]), max(mo_ea[core_idx]), max(mo_eb[core_idx])) logger.debug(self, ' Lowest 0-occ = %18.15g | %18.15g | %18.15g', min(mo_energy[vir_idx]), min(mo_ea[vir_idx]), min(mo_eb[vir_idx])) for i in numpy.where(open_idx)[0]: logger.debug(self, ' 1-occ = %18.15g | %18.15g | %18.15g', mo_energy[i], mo_ea[i], mo_eb[i]) numpy.set_printoptions(threshold=nmo) logger.debug(self, ' Roothaan mo_energy =\n%s', mo_energy) logger.debug1(self, ' alpha mo_energy =\n%s', mo_ea) logger.debug1(self, ' beta mo_energy =\n%s', mo_eb) numpy.set_printoptions(threshold=1000) return mo_occ
def get_occ(self, mo_energy=None, mo_coeff=None, orbsym=None): ''' We assumed mo_energy are grouped by symmetry irreps, (see function self.eig). The orbitals are sorted after SCF. ''' if mo_energy is None: mo_energy = self.mo_energy mol = self.mol if orbsym is None: if mo_coeff is not None: # due to linear-dep ovlp_ao = self.get_ovlp() orbsyma = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff[0], ovlp_ao, False) orbsymb = symm.label_orb_symm(self, mol.irrep_id, mol.symm_orb, mo_coeff[1], ovlp_ao, False) orbsyma = numpy.asarray(orbsyma) orbsymb = numpy.asarray(orbsymb) else: ovlp_ao = None orbsyma = [ numpy.repeat(ir, mol.symm_orb[i].shape[1]) for i, ir in enumerate(mol.irrep_id) ] orbsyma = orbsymb = numpy.hstack(orbsyma) else: orbsyma = numpy.asarray(orbsym[0]) orbsymb = numpy.asarray(orbsym[1]) assert (mo_energy[0].size == orbsyma.size) mo_occ = numpy.zeros_like(mo_energy) idx_ea_left = [] idx_eb_left = [] neleca_fix = nelecb_fix = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idxa = numpy.where(orbsyma == ir)[0] ir_idxb = numpy.where(orbsymb == ir)[0] if irname in self.irrep_nelec: if isinstance(self.irrep_nelec[irname], (int, numpy.integer)): nelecb = self.irrep_nelec[irname] // 2 neleca = self.irrep_nelec[irname] - nelecb else: neleca, nelecb = self.irrep_nelec[irname] ea_idx = numpy.argsort(mo_energy[0][ir_idxa]) eb_idx = numpy.argsort(mo_energy[1][ir_idxb]) mo_occ[0, ir_idxa[ea_idx[:neleca]]] = 1 mo_occ[1, ir_idxb[eb_idx[:nelecb]]] = 1 neleca_fix += neleca nelecb_fix += nelecb else: idx_ea_left.append(ir_idxa) idx_eb_left.append(ir_idxb) neleca_float = self.nelec[0] - neleca_fix nelecb_float = self.nelec[1] - nelecb_fix assert (neleca_float >= 0) assert (nelecb_float >= 0) if len(idx_ea_left) > 0: idx_ea_left = numpy.hstack(idx_ea_left) ea_left = mo_energy[0][idx_ea_left] ea_sort = numpy.argsort(ea_left) occ_idx = idx_ea_left[ea_sort][:neleca_float] mo_occ[0][occ_idx] = 1 if len(idx_eb_left) > 0: idx_eb_left = numpy.hstack(idx_eb_left) eb_left = mo_energy[1][idx_eb_left] eb_sort = numpy.argsort(eb_left) occ_idx = idx_eb_left[eb_sort][:nelecb_float] mo_occ[1][occ_idx] = 1 vir_idx = (mo_occ[0] == 0) if self.verbose >= logger.INFO and numpy.count_nonzero(vir_idx) > 0: ehomoa = max(mo_energy[0][mo_occ[0] > 0]) elumoa = min(mo_energy[0][mo_occ[0] == 0]) ehomob = max(mo_energy[1][mo_occ[1] > 0]) elumob = min(mo_energy[1][mo_occ[1] == 0]) noccsa = [] noccsb = [] p0 = 0 for i, ir in enumerate(mol.irrep_id): irname = mol.irrep_name[i] ir_idxa = orbsyma == ir ir_idxb = orbsymb == ir noccsa.append(numpy.count_nonzero(mo_occ[0][ir_idxa])) noccsb.append(numpy.count_nonzero(mo_occ[1][ir_idxb])) if ehomoa in mo_energy[0][ir_idxa]: irhomoa = irname if elumoa in mo_energy[0][ir_idxa]: irlumoa = irname if ehomob in mo_energy[1][ir_idxb]: irhomob = irname if elumob in mo_energy[1][ir_idxb]: irlumob = irname logger.info(self, 'alpha H**O (%s) = %.15g LUMO (%s) = %.15g', irhomoa, ehomoa, irlumoa, elumoa) logger.info(self, 'beta H**O (%s) = %.15g LUMO (%s) = %.15g', irhomob, ehomob, irlumob, elumob) ehomo = max(ehomoa, ehomob) elumo = min(elumoa, elumob) logger.debug(self, 'alpha irrep_nelec = %s', noccsa) logger.debug(self, 'beta irrep_nelec = %s', noccsb) hf_symm._dump_mo_energy(mol, mo_energy[0], mo_occ[0], ehomo, elumo, orbsyma, 'alpha-', verbose=self.verbose) hf_symm._dump_mo_energy(mol, mo_energy[1], mo_occ[1], ehomo, elumo, orbsymb, 'beta-', verbose=self.verbose) if mo_coeff is not None and self.verbose >= logger.DEBUG: if ovlp_ao is None: ovlp_ao = self.get_ovlp() ss, s = self.spin_square((mo_coeff[0][:, mo_occ[0] > 0], mo_coeff[1][:, mo_occ[1] > 0]), ovlp_ao) logger.debug(self, 'multiplicity <S^2> = %.8g 2S+1 = %.8g', ss, s) return mo_occ
} mol.symmetry = 1 mol.build() m = scf.RHF(mol) ehf = m.scf() norb = m.mo_coeff.shape[1] nelec = mol.nelectron - 1 h1e = reduce(numpy.dot, (m.mo_coeff.T, scf.hf.get_hcore(mol), m.mo_coeff)) eri = ao2mo.incore.full(m._eri, m.mo_coeff) numpy.random.seed(1) na = cistring.num_strings(norb, nelec // 2 + 1) nb = cistring.num_strings(norb, nelec // 2) fcivec = numpy.random.random((na, nb)) orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, m.mo_coeff) cis = FCISolver(mol) cis.orbsym = orbsym fcivec = addons.symmetrize_wfn(fcivec, norb, nelec, cis.orbsym, wfnsym=0) ci1 = cis.contract_2e(eri, fcivec, norb, nelec, orbsym=cis.orbsym, wfnsym=0) ci1ref = direct_spin1.contract_2e(eri, fcivec, norb, nelec) print(numpy.allclose(ci1ref, ci1)) ci1 = contract_2e(eri, fcivec, norb, nelec, orbsym=orbsym) ci1ref = direct_spin1.contract_2e(eri, fcivec, norb, nelec)
def test_1(): ### PYSCF INPUT r0 = 2.0 molecule = ''' C -4.308669 0.197146 0.000000 C 4.308669 -0.197146 0.000000 C -3.110874 -0.411353 0.000000 C 3.110874 0.411353 0.000000 H -4.394907 1.280613 0.000000 H 4.394907 -1.280613 0.000000 H -5.234940 -0.367304 0.000000 H 5.234940 0.367304 0.000000 H -3.069439 -1.500574 0.000000 H 3.069439 1.500574 0.000000 C -1.839087 0.279751 0.000000 C 1.839087 -0.279751 0.000000 C -0.634371 -0.341144 0.000000 C 0.634371 0.341144 0.000000 H -1.871161 1.369551 0.000000 H 1.871161 -1.369551 0.000000 H -0.607249 -1.431263 0.000000 H 0.607249 1.431263 0.000000 ''' charge = 0 spin = 0 basis_set = 'sto-3g' npoly = 4 na = npoly nb = npoly ### TPSCI BASIS INPUT orb_basis = 'PM' cas_nel = 2*npoly cas_norb = 2*npoly #Integrals from pyscf import pyscf from pyscf import gto, scf, ao2mo, molden, lo pyscf.lib.num_threads(1) #with degenerate states and multiple processors there can be issues #PYSCF inputs mol = gto.Mole() mol.atom = molecule mol.max_memory = 1000 # MB mol.symmetry = True mol.charge = charge mol.spin = spin mol.basis = basis_set mol.build() print("symmertry") print(mol.topgroup) #SCF #mf = scf.RHF(mol).run(init_guess='atom') mf = scf.RHF(mol).run(conv_tol=1e-14) #C = mf.mo_coeff #MO coeffs enu = mf.energy_nuc() if mol.symmetry == True: from pyscf import symm mo = symm.symmetrize_orb(mol, mf.mo_coeff) osym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo) #symm.addons.symmetrize_space(mol, mo, s=None, check=True, tol=1e-07) for i in range(len(osym)): print("%4d %8s %16.8f"%(i+1,osym[i],mf.mo_energy[i])) h,ecore,g,C = get_pi_space(mol,mf,cas_norb,cas_nel,local=True) print("ecore %16.8f"%ecore) print("MULLIKEN") m1 = mulliken_ordering(mol,h.shape[0],C) ppp = np.column_stack(np.where(m1>.90)) print(ppp) idx = list(ppp[:,1]) m2 = np.where(m1>.90) idx = m2[1] C = C[:,idx] h,g = reorder_integrals(idx,h,g) #molden.from_mo(mol, 'cas.molden', C) blocks = [[0,1,2,3],[4,5],[6,7]] init_fspace = ((2,2),(1,1),(1,1)) #blocks = [[0,1,2,3],[4,5,6,7]] #init_fspace = ((2,2),(2,2)) from scipy import optimize oocmf = CmfSolver(h, g, ecore, blocks, init_fspace,C) oocmf.init() x = np.zeros_like(h) min_options = {'gtol': 1e-8, 'disp':False} opt_result = scipy.optimize.minimize(oocmf.energy, x, jac=oocmf.grad, method = 'BFGS', options=min_options ) #opt_result = scipy.optimize.minimize(oocmf.energy, x, jac=oocmf.grad, method = 'BFGS', callback=oocmf.callback) print(opt_result.x) Kpq = opt_result.x.reshape(h.shape) print(Kpq) e_fcmf = oocmf.energy_dps() oocmf.rotate(Kpq) e_ocmf = oocmf.energy_dps() print("Orbital Frozen CMF:%12.8f"%e_fcmf) print("Orbital Optimized CMF:%12.8f"%e_ocmf) h = oocmf.h g = oocmf.g clustered_ham = oocmf.clustered_ham ci_vector = oocmf.ci_vector edps = build_hamiltonian_diagonal(clustered_ham,ci_vector) print("%16.10f"%edps) #ref_grad = np.array([[-0., -0., -0., -0., -0.136637, -0.001116, -0.00094, 0.030398], # [ 0., 0., -0., -0., -0.001116, -0.136637, 0.030398, -0.00094 ], # [ 0., 0., 0., 0., 0.001942, -0.033806, 0.123316, -0.002399], # [ 0., 0., -0., -0., -0.033806, 0.001942, -0.002399, 0.123316], # [ 0.136637, 0.001116, -0.001942, 0.033806, 0., 0., 0., 0. ], # [ 0.001116, 0.136637, 0.033806, -0.001942, 0., -0., 0., 0. ], # [ 0.00094, -0.030398, -0.123316, 0.002399, -0., -0., 0., 0. ], # [-0.030398, 0.00094, 0.002399, -0.123316, -0., -0., 0., 0. ]]) ref_angles= np.array([[ 0., -0., -0., -0., -0.097782, 0.002467, -0.005287, 0.00192 ], [ 0., -0., -0., -0., 0.002467, -0.097782, 0.00192, -0.005287], [ 0., 0., 0., 0., -0.002466, -0.123235, 0.155944, -0.004683], [ 0., 0., -0., 0., -0.123235, -0.002466, -0.004683, 0.155944], [ 0.097782, -0.002467, 0.002466, 0.123235, 0., 0., -0.002248, 0.581917], [-0.002467, 0.097782, 0.123235, 0.002466, -0., -0., 0.581917, -0.002248], [ 0.005287, -0.00192, -0.155944, 0.004683, 0.002248, -0.581917, 0., -0. ], [-0.00192, 0.005287, 0.004683, -0.155944, -0.581917, 0.002248, 0., 0. ]]) print(Kpq) print(ref_angles) try: assert(np.allclose(Kpq,ref_angles,atol=1e-5)) except: assert(np.allclose(-1*Kpq,ref_angles,atol=1e-5)) assert(abs(e_fcmf - -8.266997040181 ) <1e-8) assert(abs(e_ocmf - -8.528879972678 ) <1e-8)