def label_orb_symm(mol, irrep_name, symm_orb, mo, s=None, check=True): '''Label the symmetry of given orbitals irrep_name can be either the symbol or the ID of the irreducible representation. If the ID is provided, it returns the numeric code associated with XOR operator, see :py:meth:`symm.param.IRREP_ID_TABLE` Args: mol : an instance of :class:`Mole` irrep_name : list of str or int A list of irrep ID or name, it can be either mol.irrep_id or mol.irrep_name. It can affect the return "label". symm_orb : list of 2d array the symmetry adapted basis mo : 2d array the orbitals to label Returns: list of symbols or integers to represent the irreps for the given orbitals Examples: >>> from pyscf import gto, scf, symm >>> mol = gto.M(atom='H 0 0 0; H 0 0 1', basis='ccpvdz',verbose=0, symmetry=1) >>> mf = scf.RHF(mol) >>> mf.kernel() >>> symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mf.mo_coeff) ['Ag', 'B1u', 'Ag', 'B1u', 'B2u', 'B3u', 'Ag', 'B2g', 'B3g', 'B1u'] >>> symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mf.mo_coeff) [0, 5, 0, 5, 6, 7, 0, 2, 3, 5] ''' nmo = mo.shape[1] if s is None: s = mol.intor_symmetric('cint1e_ovlp_sph') mo_s = numpy.dot(mo.T, s) norm = numpy.empty((len(irrep_name), nmo)) for i,ir in enumerate(irrep_name): moso = numpy.dot(mo_s, symm_orb[i]) norm[i] = numpy.einsum('ij,ij->i', moso, moso) iridx = numpy.argmax(norm, axis=0) orbsym = [irrep_name[i] for i in iridx] logger.debug(mol, 'irreps of each MO %s', str(orbsym)) if check: norm[iridx,numpy.arange(nmo)] = 0 orbidx = numpy.where(norm > THRESHOLD) if orbidx[1].size > 0: idx = numpy.where(norm > THRESHOLD*1e2) if idx[1].size > 0: logger.error(mol, 'orbitals %s not symmetrized, norm = %s', idx[1], norm[idx]) raise ValueError('orbitals %s not symmetrized' % idx[1]) else: logger.warn(mol, 'orbitals %s not strictly symmetrized.', orbidx[1]) logger.warn(mol, 'They can be symmetrized with ' 'pyscf.symm.symmetrize_orb function.') logger.debug(mol, 'norm = %s', norm[orbidx]) return orbsym
def compress_approx(self,maxM=500, compress_schedule=None, tol=1e-7, stored_integral =False): '''SC-NEVPT2 with compressed perturber Kwargs : maxM : int DMRG bond dimension Examples: >>> mf = gto.M('N 0 0 0; N 0 0 1.4', basis='6-31g').apply(scf.RHF).run() >>> mc = dmrgscf.DMRGSCF(mf, 4, 4).run() >>> NEVPT(mc, root=0).compress_approx(maxM=100).kernel() -0.14058324991532101 ''' #TODO #Some preprocess for compressed perturber if hasattr(self.fcisolver, 'nevpt_intermediate'): logger.info(self, 'Use compressed mps perturber as an aaproximation') else: logger.error(self, 'Compressed mps perturber can be only used for DMRG wave function') exit() from pyscf.dmrgscf.nevpt_mpi import DMRG_COMPRESS_NEVPT if stored_integral: #Stored perturbation integral and read them again. For debugging purpose. DMRG_COMPRESS_NEVPT('nevpt_perturb_integral',maxM= maxM, root= self.root, nevptsolver= compress_schedule, tol= tol) else: DMRG_COMPRESS_NEVPT(self,maxM= maxM, root= self.root, nevptsolver= compress_schedule, tol= tol) self.canonicalized = True self.compressed_mps = True return self
def compress_approx(self,maxM=500, nevptsolver=None, tol=1e-7, stored_integral =False): '''SC-NEVPT2 with compressed perturber Kwargs : maxM : int DMRG bond dimension Examples: >>> mf = gto.M('N 0 0 0; N 0 0 1.4', basis='6-31g').apply(scf.RHF).run() >>> mc = dmrgscf.DMRGSCF(mf, 4, 4).run() >>> NEVPT(mc, root=0).compress_approx(maxM=100).kernel() -0.14058324991532101 ''' #TODO #Some preprocess for compressed perturber if getattr(self.fcisolver, 'nevpt_intermediate', None): logger.info(self, 'Use compressed mps perturber as an approximation') else: msg = 'Compressed mps perturber can be only used with DMRG wave function' logger.error(self, msg) raise RuntimeError(msg) self.nevptsolver = nevptsolver self.maxM = maxM self.tol = tol self.stored_integral = stored_integral self.canonicalized = True self.compressed_mps = True return self
def compress_approx(self,maxM=500, nevptsolver=None, tol=1e-7, stored_integral =False): '''SC-NEVPT2 with compressed perturber Kwargs : maxM : int DMRG bond dimension Examples: >>> mf = gto.M('N 0 0 0; N 0 0 1.4', basis='6-31g').apply(scf.RHF).run() >>> mc = dmrgscf.DMRGSCF(mf, 4, 4).run() >>> NEVPT(mc, root=0).compress_approx(maxM=100).kernel() -0.14058324991532101 ''' #TODO #Some preprocess for compressed perturber if hasattr(self.fcisolver, 'nevpt_intermediate'): logger.info(self, 'Use compressed mps perturber as an approximation') else: msg = 'Compressed mps perturber can be only used with DMRG wave function' logger.error(self, msg) raise RuntimeError(msg) self.nevptsolver = nevptsolver self.maxM = maxM self.tol = tol self.stored_integral = stored_integral self.canonicalized = True self.compressed_mps = True return self
def dump_flags(self): hf.SCF.dump_flags(self) logger.info(self, '%s with symmetry adapted basis', self.__class__.__name__) float_irname = [] fix_na = 0 fix_nb = 0 for ir in range(self.mol.symm_orb.__len__()): irname = self.mol.irrep_name[ir] if irname in self.irrep_nelec: fix_na += self.irrep_nelec[irname][0] fix_nb += self.irrep_nelec[irname][1] else: float_irname.append(irname) float_irname = set(float_irname) if fix_na+fix_nb > 0: logger.info(self, 'fix %d electrons in irreps: %s', fix_na+fix_nb, str(self.irrep_nelec.items())) if ((fix_na+fix_nb > self.mol.nelectron) or (fix_na>self.nelectron_alpha) or (fix_nb+self.nelectron_alpha>self.mol.nelectron)): logger.error(self, 'electron number error in irrep_nelec %s', self.irrep_nelec.items()) raise ValueError('irrep_nelec') if float_irname: logger.info(self, '%d free electrons in irreps %s', self.mol.nelectron-fix_na-fix_nb, ' '.join(float_irname)) elif fix_na+fix_nb != self.mol.nelectron: logger.error(self, 'electron number error in irrep_nelec %d', self.irrep_nelec.items()) raise ValueError('irrep_nelec')
def dump_flags(self): hf.RHF.dump_flags(self) logger.info(self, '%s with symmetry adapted basis', self.__class__.__name__) float_irname = [] fix_ne = 0 for ir in range(self.mol.symm_orb.__len__()): irname = self.mol.irrep_name[ir] if irname in self.irrep_nelec: fix_ne += self.irrep_nelec[irname] else: float_irname.append(irname) if fix_ne > 0: logger.info(self, 'fix %d electrons in irreps %s', fix_ne, self.irrep_nelec.items()) if fix_ne > self.mol.nelectron: logger.error(self, 'num. electron error in irrep_nelec %s', self.irrep_nelec.items()) raise ValueError('irrep_nelec') if float_irname: logger.info(self, '%d free electrons in irreps %s', self.mol.nelectron-fix_ne, ' '.join(float_irname)) elif fix_ne != self.mol.nelectron: logger.error(self, 'number of electrons error in irrep_nelec %s', self.irrep_nelec.items()) raise ValueError('irrep_nelec')
def atomic_pops(self, mol, mo_coeff, method=None): if method is None: method = self.pop_method if method.lower() in ('iao', 'ibo') and self._scf is None: logger.error(self, 'PM with IAO scheme should include an scf ' 'object when creating PM object.\n PM(mol, mf=scf_object)') raise ValueError('PM attribute method is not valid') return atomic_pops(mol, mo_coeff, method, self._scf)
def executeSHCI(SHCI): outFile = os.path.join(SHCI.runtimeDir, SHCI.outputFile) try: cmd = ' '.join((SHCI.mpiprefix, SHCI.executable)) cmd = "%s >> %s" % (cmd, outFile) check_call(cmd, shell=True) except CalledProcessError as err: logger.error(SHCI, cmd) raise err
def executeBLOCK(DMRGCI): inFile = os.path.join(DMRGCI.runtimeDir, DMRGCI.configFile) outFile = os.path.join(DMRGCI.runtimeDir, DMRGCI.outputFile) try: cmd = ' '.join((DMRGCI.mpiprefix, DMRGCI.executable, inFile)) cmd = "%s > %s 2>&1" % (cmd, outFile) check_call(cmd, shell=True) except CalledProcessError as err: logger.error(DMRGCI, cmd) raise err
def executeBLOCK(DMRGCI): inFile = DMRGCI.configFile outFile = DMRGCI.outputFile try: cmd = ' '.join((DMRGCI.mpiprefix, DMRGCI.executable, inFile)) cmd = "%s > %s 2>&1" % (cmd, outFile) check_call(cmd, cwd=DMRGCI.runtimeDir, shell=True) except CalledProcessError as err: logger.error(DMRGCI, cmd) DMRGCI.stdout.write(check_output(['tail', '-100', outFile])) raise err
def executeSHCI(SHCI): file1 = os.path.join(SHCI.runtimeDir, "%s/shci.e" % (SHCI.prefix)) if os.path.exists(file1): os.remove(file1) inFile = os.path.join(SHCI.runtimeDir, SHCI.configFile) outFile = os.path.join(SHCI.runtimeDir, SHCI.outputFile) try: cmd = ' '.join((SHCI.mpiprefix, SHCI.executable, inFile)) cmd = "%s > %s 2>&1" % (cmd, outFile) check_call(cmd, shell=True) except CalledProcessError as err: logger.error(SHCI, cmd) raise err
def executeBLOCK(DMRGCI): inFile = DMRGCI.configFile outFile = DMRGCI.outputFile try: cmd = ' '.join((DMRGCI.mpiprefix, DMRGCI.executable, inFile)) cmd = "%s > %s 2>&1" % (cmd, outFile) check_call(cmd, cwd=DMRGCI.runtimeDir, shell=True) except CalledProcessError as err: logger.error(DMRGCI, cmd) outFile = os.path.join(DMRGCI.runtimeDir, outFile) DMRGCI.stdout.write(check_output(['tail', '-100', outFile]).decode()) raise err
def execute_shci(shciobj): output = os.path.join(shciobj.runtimedir, shciobj.outputfile) cmd = ' '.join((shciobj.mpiprefix, shciobj.executable)) try: #cmd = ' '.join((shciobj.mpiprefix, shciobj.executable)) #cmd = "%s > %s 2>&1" % (cmd, output) #check_call(cmd, shell=True, cwd=shciobj.runtimedir) with open(output, 'w') as f: check_call(cmd.split(), cwd=shciobj.runtimedir, stdout=f, stderr=f) except CalledProcessError as err: logger.error(shciobj, cmd) shciobj.stdout.write(check_output(['tail', '-100', output])) raise err return output
def compress_approx(self,maxM=500, compress_schedule=None, tol=1e-7, stored_integral =False): #TODO #Some preprocess for compressed perturber if hasattr(self.fcisolver, 'nevpt_intermediate'): logger.info(self, 'Use compressed mps perturber as an aaproximation') else: logger.error(self, 'Compressed mps perturber can be only used for DMRG wave function') exit() from pyscf.dmrgscf.nevpt_mpi import DMRG_COMPRESS_NEVPT if stored_integral: #Stored perturbation integral and read them again. For debugging purpose. DMRG_COMPRESS_NEVPT('nevpt_perturb_integral',maxM= maxM, root= self.root, nevptsolver= compress_schedule, tol= tol) else: DMRG_COMPRESS_NEVPT(self,maxM= maxM, root= self.root, nevptsolver= compress_schedule, tol= tol) self.canonicalized = True self.compressed_mps = True return self
def compress_approx(self, maxM=500, nevptsolver=None, tol=1e-7, stored_integral=False): '''SC-NEVPT2 with compressed perturber Kwargs : maxM : int DMRG bond dimension Examples: >>> mf = gto.M('N 0 0 0; N 0 0 1.4', basis='6-31g').apply(scf.RHF).run() >>> mc = dmrgscf.DMRGSCF(mf, 4, 4).run() >>> NEVPT(mc, root=0).compress_approx(maxM=100).kernel() -0.14058324991532101 References: J. Chem. Theory Comput. 12, 1583 (2016), doi:10.1021/acs.jctc.5b01225 J. Chem. Phys. 146, 244102 (2017), doi:10.1063/1.4986975 ''' #TODO #Some preprocess for compressed perturber if getattr(self.fcisolver, 'nevpt_intermediate', None): logger.info(self, 'Use compressed mps perturber as an approximation') else: msg = 'Compressed mps perturber can be only used with DMRG wave function' logger.error(self, msg) raise RuntimeError(msg) self.nevptsolver = nevptsolver self.maxM = maxM self.tol = tol self.stored_integral = stored_integral self.canonicalized = True self.compressed_mps = True self.for_dmrg() return self
def runQDPT(mc, gtensor): if mc.fcisolver.__class__.__name__ == 'FakeCISolver': SHCI = mc.fcisolver.fcisolvers[0] outFile = os.path.join(SHCI.runtimeDir, SHCI.outputFile) writeSHCIConfFile(SHCI, mc.nelecas, False) confFile = os.path.join(SHCI.runtimeDir, SHCI.configFile) f = open(confFile, 'a') for SHCI2 in mc.fcisolver.fcisolvers[1:]: if (SHCI2.prefix != ""): f.write('prefix %s\n' % (SHCI2.prefix)) if (gtensor): f.write("dogtensor\n") f.close() try: cmd = ' '.join((SHCI.mpiprefix, SHCI.QDPTexecutable, confFile)) cmd = "%s > %s 2>&1" % (cmd, outFile) check_call(cmd, shell=True) check_call('cat %s|grep -v "#"' % (outFile), shell=True) except CalledProcessError as err: logger.error(mc.fcisolver, cmd) raise err else: writeSHCIConfFile(mc.fcisolver, mc.nelecas, False) confFile = os.path.join(mc.fcisolver.runtimeDir, mc.fcisolver.configFile) outFile = os.path.join(mc.fcisolver.runtimeDir, mc.fcisolver.outputFile) if (gtensor): f = open(confFile, 'a') f.write("dogtensor\n") f.close() try: cmd = ' '.join((mc.fcisolver.mpiprefix, mc.fcisolver.QDPTexecutable, confFile)) cmd = "%s > %s 2>&1" % (cmd, outFile) check_call(cmd, shell=True) check_call('cat %s|grep -v "#"' % (outFile), shell=True) except CalledProcessError as err: logger.error(mc.fcisolver, cmd) raise err
def dump_flags(self): rohf.ROHF.dump_flags(self) logger.info(self, '%s with symmetry adapted basis', self.__class__.__name__) #TODO: improve the sainity check float_irname = [] fix_na = 0 fix_nb = 0 for ir in range(self.mol.symm_orb.__len__()): irname = self.mol.irrep_name[ir] if irname in self.irrep_nelec: if isinstance(self.irrep_nelec[irname], (int, numpy.integer)): nb = self.irrep_nelec[irname] // 2 fix_na += self.irrep_nelec[irname] - nb fix_nb += nb else: fix_na += self.irrep_nelec[irname][0] fix_nb += self.irrep_nelec[irname][1] else: float_irname.append(irname) float_irname = set(float_irname) if fix_na+fix_nb > 0: logger.info(self, 'fix %d electrons in irreps: %s', fix_na+fix_nb, str(self.irrep_nelec.items())) if ((fix_na+fix_nb > self.mol.nelectron) or (fix_na>self.nelec[0]) or (fix_nb>self.nelec[1]) or (fix_na+self.nelec[1]>self.mol.nelectron) or (fix_nb+self.nelec[0]>self.mol.nelectron)): logger.error(self, 'electron number error in irrep_nelec %s', self.irrep_nelec.items()) raise ValueError('irrep_nelec') if float_irname: logger.info(self, '%d free electrons in irreps %s', self.mol.nelectron-fix_na-fix_nb, ' '.join(float_irname)) elif fix_na+fix_nb != self.mol.nelectron: logger.error(self, 'electron number error in irrep_nelec %s', self.irrep_nelec.items()) raise ValueError('irrep_nelec')
def opt_ci(self): for it in range(self.max_cycle[-1]): _ci=self.ci; _e_ele = self.e_ele for u in range(self.nocc-self.npair_d, self.nocc): hp = numpy.zeros((2,2)) for i in range(2): for j in range(2): hp[i,j] += 2*self.h_mo[self.pair[u,i],self.pair[u,i]]*delta(i,j) \ + self.g_mo[index(self.pair[u,i],self.pair[u,j],self.pair[u,i],self.pair[u,j])] if i==j: for v in range(self.nocc): t=self.t(u,v) if v!=u: for jj in range(2): hp[i,j] += _ci[v,jj]**2 * \ (4*self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,jj], self.pair[v,jj])] - 2*t*self.g_mo[index(self.pair[u,i], self.pair[v,jj], self.pair[u,i],self.pair[v,jj])]) s, a = numpy.linalg.eig(hp) a=a[:,numpy.argsort(s.real)] self.ci[u,:] = a[:,0].T self.e_ele=self.energy_elec() if (abs(_e_ele-self.e_ele)<self.conv_tol[-1]): break else: logger.error(self, 'Error: Not converge after %d cycles ci optimization' %self.max_cycle[-1])
def DMRG_COMPRESS_NEVPT(mc, maxM=500, root=0, nevptsolver=None, tol=1e-7, nevpt_integral=None): if isinstance(nevpt_integral, str) and h5py.is_hdf5(nevpt_integral): nevpt_integral_file = os.path.abspath(nevpt_integral) mol = chkfile.load_mol(nevpt_integral_file) fh5 = h5py.File(nevpt_integral_file, 'r') ncas = fh5['mc/ncas'].value ncore = fh5['mc/ncore'].value nvirt = fh5['mc/nvirt'].value nelecas = fh5['mc/nelecas'].value nroots = fh5['mc/nroots'].value wfnsym = fh5['mc/wfnsym'].value fh5.close() else : mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore nelecas = mc.nelecas nroots = mc.fcisolver.nroots wfnsym = mc.fcisolver.wfnsym nevpt_integral_file = None if nevptsolver is None: nevptsolver = default_nevpt_schedule(mc.fcisolver, maxM, tol) #nevptsolver.__dict__.update(mc.fcisolver.__dict__) nevptsolver.wfnsym = wfnsym nevptsolver.block_extra_keyword = mc.fcisolver.block_extra_keyword nevptsolver.nroots = nroots nevptsolver.executable = settings.BLOCKEXE_COMPRESS_NEVPT if nevptsolver.executable == getattr(mc.fcisolver, 'executable', None): logger.warn(mc, 'DMRG executable file for nevptsolver %s is the same ' 'to the executable file for DMRG solver %s. If they are ' 'both compiled by MPI compilers, they may cause error or ' 'random results in DMRG-NEVPT calculation.') nevpt_scratch = os.path.abspath(nevptsolver.scratchDirectory) dmrg_scratch = os.path.abspath(mc.fcisolver.scratchDirectory) # Integrals are not given by the kwarg nevpt_integral if nevpt_integral_file is None: nevpt_integral_file = os.path.join(nevpt_scratch, 'nevpt_perturb_integral') write_chk(mc, root, nevpt_integral_file) conf = dmrgci.writeDMRGConfFile(nevptsolver, nelecas, False, with_2pdm=False, extraline=['fullrestart','nevpt_state_num %d'%root]) with open(conf, 'r') as f: block_conf = f.readlines() block_conf = [l for l in block_conf if 'prefix' not in l] block_conf = ''.join(block_conf) with h5py.File(nevpt_integral_file) as fh5: if 'dmrg.conf' in fh5: del(fh5['dmrg.conf']) fh5['dmrg.conf'] = block_conf if nevptsolver.verbose >= logger.DEBUG1: logger.debug1(nevptsolver, 'Block Input conf') logger.debug1(nevptsolver, block_conf) t0 = (time.clock(), time.time()) # function nevpt_integral_mpi is called in this cmd cmd = ' '.join((nevptsolver.mpiprefix, os.path.realpath(os.path.join(__file__, '..', 'nevpt_mpi.py')), nevpt_integral_file, nevptsolver.executable, dmrg_scratch, nevpt_scratch)) logger.debug(nevptsolver, 'DMRG_COMPRESS_NEVPT cmd %s', cmd) try: output = subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: logger.error(nevptsolver, cmd) raise err if nevptsolver.verbose >= logger.DEBUG1: logger.debug1(nevptsolver, open(os.path.join(nevpt_scratch, '0', 'dmrg.out')).read()) perturb_file = os.path.join(nevpt_scratch, '0', 'Perturbation_%d'%root) fh5 = h5py.File(perturb_file, 'r') Vi_e = fh5['Vi/energy'].value Vr_e = fh5['Vr/energy'].value fh5.close() logger.note(nevptsolver,'Nevpt Energy:') logger.note(nevptsolver,'Sr Subspace: E = %.14f'%( Vr_e)) logger.note(nevptsolver,'Si Subspace: E = %.14f'%( Vi_e)) logger.timer(nevptsolver,'MPS NEVPT calculation time', *t0) return perturb_file
def DMRG_COMPRESS_NEVPT(mc, maxM=500, root=0, nevptsolver=None, tol=1e-7): if (isinstance(mc, str)): mol = chkfile.load_mol(mc) fh5 = h5py.File(mc, 'r') ncas = fh5['mc/ncas'].value ncore = fh5['mc/ncore'].value nvirt = fh5['mc/nvirt'].value nelecas = fh5['mc/nelecas'].value nroots = fh5['mc/nroots'].value wfnsym = fh5['mc/wfnsym'].value fh5.close() mc_chk = mc else : mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore nelecas = mc.nelecas nroots = mc.fcisolver.nroots wfnsym = mc.fcisolver.wfnsym mc_chk = 'nevpt_perturb_integral' write_chk(mc, root, mc_chk) if nevptsolver is None: nevptsolver = default_nevpt_schedule(mol,maxM, tol) nevptsolver.wfnsym = wfnsym nevptsolver.block_extra_keyword = mc.fcisolver.block_extra_keyword nevptsolver.nroots = nroots from pyscf.dmrgscf import settings nevptsolver.executable = settings.BLOCKEXE_COMPRESS_NEVPT scratch = nevptsolver.scratchDirectory nevptsolver.scratchDirectory = '' dmrgci.writeDMRGConfFile(nevptsolver, nelecas, False, with_2pdm=False, extraline=['fullrestart','nevpt_state_num %d'%root]) nevptsolver.scratchDirectory = scratch if nevptsolver.verbose >= logger.DEBUG1: inFile = os.path.join(nevptsolver.runtimeDir, nevptsolver.configFile) logger.debug1(nevptsolver, 'Block Input conf') logger.debug1(nevptsolver, open(inFile, 'r').read()) t0 = (time.clock(), time.time()) cmd = ' '.join((nevptsolver.mpiprefix, '%s/nevpt_mpi.py' % os.path.dirname(os.path.realpath(__file__)), mc_chk, nevptsolver.executable, os.path.join(nevptsolver.runtimeDir, nevptsolver.configFile), nevptsolver.outputFile, nevptsolver.scratchDirectory)) logger.debug(nevptsolver, 'DMRG_COMPRESS_NEVPT cmd %s', cmd) try: output = subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: logger.error(nevptsolver, cmd) raise err if nevptsolver.verbose >= logger.DEBUG1: logger.debug1(nevptsolver, open(os.path.join(nevptsolver.scratchDirectory, '0/dmrg.out')).read()) fh5 = h5py.File('Perturbation_%d'%root,'r') Vi_e = fh5['Vi/energy'].value Vr_e = fh5['Vr/energy'].value fh5.close() logger.note(nevptsolver,'Nevpt Energy:') logger.note(nevptsolver,'Sr Subspace: E = %.14f'%( Vr_e)) logger.note(nevptsolver,'Si Subspace: E = %.14f'%( Vi_e)) logger.timer(nevptsolver,'MPS NEVPT calculation time', *t0)
def DMRG_COMPRESS_NEVPT(mc, maxM=500, root=0, nevptsolver=None, tol=1e-7): if (isinstance(mc, str)): mol = chkfile.load_mol(mc) fh5 = h5py.File(mc, 'r') ncas = fh5['mc/ncas'].value ncore = fh5['mc/ncore'].value nvirt = fh5['mc/nvirt'].value nelecas = fh5['mc/nelecas'].value nroots = fh5['mc/nroots'].value wfnsym = fh5['mc/wfnsym'].value fh5.close() mc_chk = mc else : mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore nelecas = mc.nelecas nroots = mc.fcisolver.nroots wfnsym = mc.fcisolver.wfnsym mc_chk = 'nevpt_perturb_integral' write_chk(mc, root, mc_chk) if nevptsolver is None: nevptsolver = default_nevpt_schedule(mol,maxM, tol) nevptsolver.wfnsym = wfnsym nevptsolver.block_extra_keyword = mc.fcisolver.block_extra_keyword nevptsolver.nroots = nroots from pyscf.dmrgscf import settings nevptsolver.executable = settings.BLOCKEXE_COMPRESS_NEVPT scratch = nevptsolver.scratchDirectory nevptsolver.scratchDirectory = '' dmrgci.writeDMRGConfFile(nevptsolver, nelecas, False, with_2pdm=False, extraline=['fullrestart','nevpt_state_num %d'%root]) nevptsolver.scratchDirectory = scratch if nevptsolver.verbose >= logger.DEBUG1: inFile = os.path.join(nevptsolver.runtimeDir, nevptsolver.configFile) logger.debug1(nevptsolver, 'Block Input conf') logger.debug1(nevptsolver, open(inFile, 'r').read()) t0 = (time.clock(), time.time()) cmd = ' '.join((nevptsolver.mpiprefix, '%s/nevpt_mpi.py' % os.path.dirname(os.path.realpath(__file__)), mc_chk, nevptsolver.executable, nevptsolver.configFile, nevptsolver.outputFile, nevptsolver.scratchDirectory)) logger.debug(nevptsolver, 'DMRG_COMPRESS_NEVPT cmd %s', cmd) try: output = subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: logger.error(nevptsolver, cmd) raise err if nevptsolver.verbose >= logger.DEBUG1: logger.debug1(nevptsolver, open(os.path.join(nevptsolver.scratchDirectory, '0/dmrg.out')).read()) fh5 = h5py.File('Perturbation_%d'%root,'r') Vi_e = fh5['Vi/energy'].value Vr_e = fh5['Vr/energy'].value fh5.close() logger.note(nevptsolver,'Nevpt Energy:') logger.note(nevptsolver,'Sr Subspace: E = %.14f'%( Vr_e)) logger.note(nevptsolver,'Si Subspace: E = %.14f'%( Vi_e)) logger.timer(nevptsolver,'MPS NEVPT calculation time', *t0)
def DMRG_COMPRESS_NEVPT(mc, maxM=500, root=0, nevptsolver=None, tol=1e-7, nevpt_integral=None): if nevpt_integral: mol = chkfile.load_mol(nevpt_integral) fh5 = h5py.File(nevpt_integral, 'r') ncas = fh5['mc/ncas'].value ncore = fh5['mc/ncore'].value nvirt = fh5['mc/nvirt'].value nelecas = fh5['mc/nelecas'].value nroots = fh5['mc/nroots'].value wfnsym = fh5['mc/wfnsym'].value fh5.close() else: mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas - mc.ncore nelecas = mc.nelecas nroots = mc.fcisolver.nroots wfnsym = mc.fcisolver.wfnsym nevpt_integral_file = 'nevpt_perturb_integral' write_chk(mc, root, nevpt_integral_file) if nevptsolver is None: nevptsolver = default_nevpt_schedule(mol, maxM, tol) nevptsolver.__dict__.update(mc.fcisolver.__dict__) nevptsolver.wfnsym = wfnsym nevptsolver.block_extra_keyword = mc.fcisolver.block_extra_keyword nevptsolver.nroots = nroots nevptsolver.executable = settings.BLOCKEXE_COMPRESS_NEVPT conf = dmrgci.writeDMRGConfFile( nevptsolver, nelecas, False, with_2pdm=False, extraline=['fullrestart', 'nevpt_state_num %d' % root]) with open(conf, 'r') as f: block_conf = f.readlines() block_conf = [l for l in block_conf if 'prefix' not in l] block_conf = '\n'.join(block_conf) with h5py.File(nevpt_integral_file) as fh5: if 'dmrg.conf' in fh5: del (fh5['dmrg.conf']) fh5['dmrg.conf'] = block_conf if nevptsolver.verbose >= logger.DEBUG1: logger.debug1(nevptsolver, 'Block Input conf') logger.debug1(nevptsolver, block_conf) t0 = (time.clock(), time.time()) cmd = ' '.join( (nevptsolver.mpiprefix, os.path.realpath(os.path.join(__file__, '..', 'nevpt_mpi.py')), nevpt_integral_file, nevptsolver.executable, mc.fcisolver.scratchDirectory, nevptsolver.scratchDirectory)) logger.debug(nevptsolver, 'DMRG_COMPRESS_NEVPT cmd %s', cmd) try: output = subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: logger.error(nevptsolver, cmd) raise err if nevptsolver.verbose >= logger.DEBUG1: logger.debug1( nevptsolver, open(os.path.join(nevptsolver.scratchDirectory, '0/dmrg.out')).read()) fh5 = h5py.File('Perturbation_%d' % root, 'r') Vi_e = fh5['Vi/energy'].value Vr_e = fh5['Vr/energy'].value fh5.close() logger.note(nevptsolver, 'Nevpt Energy:') logger.note(nevptsolver, 'Sr Subspace: E = %.14f' % (Vr_e)) logger.note(nevptsolver, 'Si Subspace: E = %.14f' % (Vi_e)) logger.timer(nevptsolver, 'MPS NEVPT calculation time', *t0)
def get_t3p2_imds_slow(cc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None): """Calculates T1, T2 amplitudes corrected by second-order T3 contribution and intermediates used in IP/EA-CCSD(T)a For description of arguments, see `get_t3p2_imds_slow` in `gintermediates.py`. """ if eris is None: eris = cc.ao2mo() fock = eris.fock nocc, nvir = t1.shape fov = fock[:nocc, nocc:] foo = fock[:nocc, :nocc].diagonal() fvv = fock[nocc:, nocc:].diagonal() fov = fock[:nocc, nocc:] foo = fock[:nocc, :nocc].diagonal() fvv = fock[nocc:, nocc:].diagonal() dtype = np.result_type(t1, t2) if np.issubdtype(dtype, np.dtype(complex).type): logger.error( cc, 't3p2 imds has not been strictly checked for use with complex integrals' ) mo_e_o = eris.mo_energy[:nocc] mo_e_v = eris.mo_energy[nocc:] ovov = _cp(eris.ovov) ovvv = _cp(eris.get_ovvv()) eris_vvov = eris.get_ovvv().conj().transpose(1, 3, 0, 2) # Physicist notation eris_vooo = eris.ovoo[:].conj().transpose(1, 0, 3, 2) # Chemist notation ccsd_energy = cc.energy(t1, t2, eris) dtype = np.result_type(t1, t2) if t3p2_ip_out is None: t3p2_ip_out = np.zeros((nocc, nvir, nocc, nocc), dtype=dtype) Wmbkj = t3p2_ip_out if t3p2_ea_out is None: t3p2_ea_out = np.zeros((nvir, nvir, nvir, nocc), dtype=dtype) Wcbej = t3p2_ea_out tmp_t3 = np.einsum('abif,kjcf->ijkabc', eris_vvov, t2) tmp_t3 -= np.einsum('aimj,mkbc->ijkabc', eris_vooo, t2) tmp_t3 = (tmp_t3 + tmp_t3.transpose(0, 2, 1, 3, 5, 4) + tmp_t3.transpose(1, 0, 2, 4, 3, 5) + tmp_t3.transpose(1, 2, 0, 4, 5, 3) + tmp_t3.transpose(2, 0, 1, 5, 3, 4) + tmp_t3.transpose(2, 1, 0, 5, 4, 3)) eia = mo_e_o[:, None] - mo_e_v[None, :] eijab = eia[:, None, :, None] + eia[None, :, None, :] eijkabc = eijab[:, :, None, :, :, None] + eia[None, None, :, None, None, :] tmp_t3 /= eijkabc Ptmp_t3 = 2. * tmp_t3 - tmp_t3.transpose( 1, 0, 2, 3, 4, 5) - tmp_t3.transpose(2, 1, 0, 3, 4, 5) pt1 = 0.5 * lib.einsum('jbkc,ijkabc->ia', 2. * ovov - ovov.transpose(0, 3, 2, 1), Ptmp_t3) tmp = 0.5 * lib.einsum('ijkabc,ia->jkbc', Ptmp_t3, fov) pt2 = tmp + tmp.transpose(1, 0, 3, 2) # b\ / \ / # /\---\ / \ / # i\/a d\/j k\/c # ------------------ tmp = lib.einsum('ijkabc,iadb->jkdc', Ptmp_t3, ovvv) pt2 += (tmp + tmp.transpose(1, 0, 3, 2)) # m\ / \ / # /\---\ / \ / # i\/a j\/b k\/c # ------------------ tmp = lib.einsum('ijkabc,iajm->mkbc', Ptmp_t3, eris.ovoo) pt2 -= (tmp + tmp.transpose(1, 0, 3, 2)) eia = mo_e_o[:, None] - mo_e_v[None, :] eijab = eia[:, None, :, None] + eia[None, :, None, :] pt1 /= eia pt2 /= eijab pt1 += t1 pt2 += t2 Wmbkj += lib.einsum('ijkabc,mcia->mbkj', Ptmp_t3, ovov) Wcbej += -1.0 * lib.einsum('ijkabc,iake->cbej', Ptmp_t3, ovov) delta_ccsd_energy = cc.energy(pt1, pt2, eris) - ccsd_energy logger.info(cc, 'CCSD energy T3[2] correction : %14.8e', delta_ccsd_energy) return delta_ccsd_energy, pt1, pt2, Wmbkj, Wcbej
def sc_nevpt(mc, ci=None, useMPS=False, verbose=None): """Strongly contracted NEVPT2""" if ci is None: ci = mc.ci # mc.cas_natorb(ci=ci) if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(mc.stdout, mc.verbose) time0 = (time.clock(), time.time()) # By defaut, mc is canonicalized for the first root. if mc.fcisolver.nroots > 1: mc.mo_coeff, _, mc.mo_energy = mc.canonicalize(mc.mo_coeff, ci=ci, verbose=log) # if not useMPS: # mc.mo_coeff, _, orbe = mc.canonicalize(casdm1=dm1) # else: # orbe = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_fock(ci=ci), mc.mo_coeff)).diagonal() if hasattr(mc.fcisolver, "nevpt_intermediate"): logger.info(mc, "DMRG-NEVPT") dm1, dm2, dm3 = mc.fcisolver.make_rdm123(ci, mc.ncas, mc.nelecas, None) else: if useMPS: logger.error(mc, "MPS nevpt only used for DMRG calculation") exit() dm1, dm2, dm3 = fci.rdm.make_dm123("FCI3pdm_kern_sf", ci, ci, mc.ncas, mc.nelecas) dm4 = None dms = { "1": dm1, "2": dm2, "3": dm3, "4": dm4, #'h1': hdm1, 'h2': hdm2, 'h3': hdm3 } time1 = log.timer("3pdm, 4pdm", *time0) eris = _ERIS(mc, mc.mo_coeff) time1 = log.timer("integral transformation", *time1) nocc = mc.ncore + mc.ncas if not hasattr(mc.fcisolver, "nevpt_intermediate"): # regular FCI solver link_indexa = fci.cistring.gen_linkstr_index(range(mc.ncas), mc.nelecas[0]) link_indexb = fci.cistring.gen_linkstr_index(range(mc.ncas), mc.nelecas[1]) aaaa = eris["ppaa"][mc.ncore : nocc, mc.ncore : nocc].copy() f3ca = _contract4pdm("NEVPTkern_cedf_aedf", aaaa, ci, mc.ncas, mc.nelecas, (link_indexa, link_indexb)) f3ac = _contract4pdm("NEVPTkern_aedf_ecdf", aaaa, ci, mc.ncas, mc.nelecas, (link_indexa, link_indexb)) dms["f3ca"] = f3ca dms["f3ac"] = f3ac time1 = log.timer("eri-4pdm contraction", *time1) if useMPS: fh5 = h5py.File("Perturbation_%d" % ci, "r") e_Si = fh5["Vi/energy"].value norm_Si = fh5["Vi/norm"].value e_Sr = fh5["Vr/energy"].value norm_Sr = fh5["Vr/norm"].value fh5.close() logger.note(mc, "Sr (-1)', Norm = %.14f E = %.14f", norm_Sr, e_Sr) logger.note(mc, "Si (+1)', Norm = %.14f E = %.14f", norm_Si, e_Si) else: norm_Sr, e_Sr = Sr(mc, ci, dms, eris) logger.note(mc, "Sr (-1)', Norm = %.14f E = %.14f", norm_Sr, e_Sr) time1 = log.timer("space Sr (-1)'", *time1) norm_Si, e_Si = Si(mc, ci, dms, eris) logger.note(mc, "Si (+1)', Norm = %.14f E = %.14f", norm_Si, e_Si) time1 = log.timer("space Si (+1)'", *time1) norm_Sijrs, e_Sijrs = Sijrs(mc, eris) logger.note(mc, "Sijrs (0) , Norm = %.14f E = %.14f", norm_Sijrs, e_Sijrs) time1 = log.timer("space Sijrs (0)", *time1) norm_Sijr, e_Sijr = Sijr(mc, dms, eris) logger.note(mc, "Sijr (+1) , Norm = %.14f E = %.14f", norm_Sijr, e_Sijr) time1 = log.timer("space Sijr (+1)", *time1) norm_Srsi, e_Srsi = Srsi(mc, dms, eris) logger.note(mc, "Srsi (-1) , Norm = %.14f E = %.14f", norm_Srsi, e_Srsi) time1 = log.timer("space Srsi (-1)", *time1) norm_Srs, e_Srs = Srs(mc, dms, eris) logger.note(mc, "Srs (-2) , Norm = %.14f E = %.14f", norm_Srs, e_Srs) time1 = log.timer("space Srs (-2)", *time1) norm_Sij, e_Sij = Sij(mc, dms, eris) logger.note(mc, "Sij (+2) , Norm = %.14f E = %.14f", norm_Sij, e_Sij) time1 = log.timer("space Sij (+2)", *time1) norm_Sir, e_Sir = Sir(mc, dms, eris) logger.note(mc, "Sir (0)' , Norm = %.14f E = %.14f", norm_Sir, e_Sir) time1 = log.timer("space Sir (0)'", *time1) nevpt_e = e_Sr + e_Si + e_Sijrs + e_Sijr + e_Srsi + e_Srs + e_Sij + e_Sir logger.note(mc, "Nevpt2 Energy = %.15f", nevpt_e) log.timer("SC-NEVPT2", *time0) return nevpt_e
def mo_k2gamma(cell, mo_energy, mo_coeff, kpts, kmesh=None, degen_tol=1e-3, imag_tol=1e-9): logger.debug(cell, "Starting mo_k2gamma") scell, phase = get_phase(cell, kpts, kmesh) # Supercell Gamma-point MO energies e_gamma = np.hstack(mo_energy) # The number of MOs may be k-point dependent (eg. due to linear dependency) nmo_k = np.asarray([ck.shape[-1] for ck in mo_coeff]) nk = len(mo_coeff) nao = mo_coeff[0].shape[0] nr = phase.shape[0] # Transform mo_coeff from k-points to supercell Gamma-point: c_gamma = [] for k in range(nk): c_k = np.einsum('R,um->Rum', phase[:, k], mo_coeff[k]) c_k = c_k.reshape(nr * nao, nmo_k[k]) c_gamma.append(c_k) c_gamma = np.hstack(c_gamma) assert c_gamma.shape == (nr * nao, sum(nmo_k)) # Sort according to MO energy sort = np.argsort(e_gamma) e_gamma, c_gamma = e_gamma[sort], c_gamma[:, sort] # Determine overlap by unfolding for better accuracy s_k = cell.pbc_intor('int1e_ovlp', hermi=1, kpts=kpts, pbcopt=lib.c_null_ptr()) s_gamma = to_supercell_ao_integrals(cell, kpts, s_k) # Orthogonality error of unfolded MOs err_orth = abs( np.linalg.multi_dot((c_gamma.conj().T, s_gamma, c_gamma)) - np.eye(c_gamma.shape[-1])).max() if err_orth > 1e-4: logger.error(cell, "Orthogonality error of MOs= %.2e !!!", err_orth) else: logger.debug(cell, "Orthogonality error of MOs= %.2e", err_orth) # Make Gamma point MOs real: # Try to remove imaginary parts by multiplication of simple phase factors c_gamma = rotate_mo_to_real(cell, e_gamma, c_gamma, degen_tol=degen_tol) # For degenerated MOs, the transformed orbitals in super cell may not be # real. Construct a sub Fock matrix in super-cell to find a proper # transformation that makes the transformed MOs real. #e_k_degen = abs(e_gamma[1:] - e_gamma[:-1]) < degen_tol #degen_mask = np.append(False, e_k_degen) | np.append(e_k_degen, False) # Get eigenvalue solver with linear-dependency treatment eigh = cell.eigh_factory(lindep_threshold=1e-13, fallback_mode=True) c_gamma_out = c_gamma.copy() mo_mask = (np.linalg.norm(c_gamma.imag, axis=0) > imag_tol) logger.debug(cell, "Number of MOs with imaginary coefficients: %d out of %d", np.count_nonzero(mo_mask), len(mo_mask)) if np.any(mo_mask): #mo_mask = np.s_[:] #if np.any(~degen_mask): # err_imag = abs(c_gamma[:,~degen_mask].imag).max() # logger.debug(cell, "Imaginary part in non-degenerate MO coefficients= %.2e", err_imag) # # Diagonalize Fock matrix spanned by degenerate MOs only # if err_imag < 1e-8: # mo_mask = degen_mask # F #mo_mask = (np.linalg.norm(c_gamma.imag, axis=0) > imag_tol) # Shift all MOs above the eig=0 subspace, so they can be extracted below shift = 1.0 - min(e_gamma[mo_mask]) cs = np.dot(c_gamma[:, mo_mask].conj().T, s_gamma) f_gamma = np.dot(cs.T.conj() * (e_gamma[mo_mask] + shift), cs) logger.debug( cell, "Imaginary parts of Fock matrix: ||Im(F)||= %.2e max|Im(F)|= %.2e", np.linalg.norm(f_gamma.imag), abs(f_gamma.imag).max()) e, v = eigh(f_gamma.real, s_gamma) # Extract MOs from rank-deficient Fock matrix mask = (e > 0.5) assert np.count_nonzero(mask) == len(e_gamma[mo_mask]) e, v = e[mask], v[:, mask] e_delta = e_gamma[mo_mask] - (e - shift) if abs(e_delta).max() > 1e-4: logger.error( cell, "Error of MO energies: ||dE||= %.2e max|dE|= %.2e !!!", np.linalg.norm(e_delta), abs(e_delta).max()) else: logger.debug(cell, "Error of MO energies: ||dE||= %.2e max|dE|= %.2e", np.linalg.norm(e_delta), abs(e_delta).max()) c_gamma_out[:, mo_mask] = v err_imag = abs(c_gamma_out.imag).max() if err_imag > 1e-4: logger.error( cell, "Imaginary part in gamma-point MOs: max|Im(C)|= %7.2e !!!", err_imag) else: logger.debug(cell, "Imaginary part in gamma-point MOs: max|Im(C)|= %7.2e", err_imag) c_gamma_out = c_gamma_out.real # Determine mo_phase, i.e. the unitary transformation from k-adapted orbitals to gamma-point orbitals s_k_g = np.einsum('kuv,Rk->kuRv', s_k, phase.conj()).reshape(nk, nao, nr * nao) mo_phase = [] for k in range(nk): mo_phase_k = lib.einsum('um,uv,vi->mi', mo_coeff[k].conj(), s_k_g[k], c_gamma_out) mo_phase.append(mo_phase_k) return scell, e_gamma, c_gamma_out, mo_phase
def sc_nevpt(mc, ci=None, useMPS=False, verbose=None): '''Strongly contracted NEVPT2''' if ci is None: ci=mc.ci #mc.cas_natorb(ci=ci) if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(mc.stdout, mc.verbose) time0 = (time.clock(), time.time()) #dm1, dm2, dm3, dm4 = fci.rdm.make_dm1234('FCI4pdm_kern_sf', # mc.ci, mc.ci, mc.ncas, mc.nelecas) logger.debug(mc, 'mc.fcisolver = %s', type(mc.fcisolver)) if hasattr(mc.fcisolver, 'nevpt_intermediate'): logger.info(mc, 'DMRG-NEVPT') dm1, dm2, dm3 = mc.fcisolver.make_rdm123(ci,mc.ncas,mc.nelecas,None) else: if useMPS: logger.error(mc,"MPS nevpt only used for DMRG calculation") exit() dm1, dm2, dm3 = fci.rdm.make_dm123('FCI3pdm_kern_sf', ci, ci, mc.ncas, mc.nelecas) dm4 = None if not useMPS: mc.mo_coeff, _, orbe = mc.canonicalize(casdm1=dm1) else: orbe = reduce(numpy.dot, (mc.mo_coeff.T, mc.get_fock(), mc.mo_coeff)).diagonal() #hdm1 = make_hdm1(dm1) #hdm2 = make_hdm2(dm1,dm2) #hdm3 = make_hdm3(dm1,dm2,dm3,hdm1,hdm2) dms = {'1': dm1, '2': dm2, '3': dm3, '4': dm4, #'h1': hdm1, 'h2': hdm2, 'h3': hdm3 } time1 = log.timer('3pdm, 4pdm', *time0) eris = _ERIS(mc, mc.mo_coeff) time1 = log.timer('integral transformation', *time1) nocc = mc.ncore + mc.ncas if not hasattr(mc.fcisolver, 'nevpt_intermediate'): # regular FCI solver link_indexa = fci.cistring.gen_linkstr_index(range(mc.ncas), mc.nelecas[0]) link_indexb = fci.cistring.gen_linkstr_index(range(mc.ncas), mc.nelecas[1]) aaaa = eris['ppaa'][mc.ncore:nocc,mc.ncore:nocc].copy() f3ca = _contract4pdm('NEVPTkern_cedf_aedf', aaaa, ci, mc.ncas, mc.nelecas, (link_indexa,link_indexb)) f3ac = _contract4pdm('NEVPTkern_aedf_ecdf', aaaa, ci, mc.ncas, mc.nelecas, (link_indexa,link_indexb)) dms['f3ca'] = f3ca dms['f3ac'] = f3ac time1 = log.timer('eri-4pdm contraction', *time1) if useMPS: fh5 = h5py.File('Perturbation_%d'%ci,'r') e_Si = fh5['Vi/energy'].value norm_Si = fh5['Vi/norm'].value e_Sr = fh5['Vr/energy'].value norm_Sr = fh5['Vr/norm'].value fh5.close() logger.note(mc, "Sr (-1)', Norm = %.14f E = %.14f", norm_Sr , e_Sr ) logger.note(mc, "Si (+1)', Norm = %.14f E = %.14f", norm_Si , e_Si ) else: norm_Sr , e_Sr = Sr(mc,ci,orbe, dms, eris) logger.note(mc, "Sr (-1)', Norm = %.14f E = %.14f", norm_Sr , e_Sr ) time1 = log.timer("space Sr (-1)'", *time1) norm_Si , e_Si = Si(mc,ci,orbe, dms, eris) logger.note(mc, "Si (+1)', Norm = %.14f E = %.14f", norm_Si , e_Si ) time1 = log.timer("space Si (+1)'", *time1) norm_Sijrs, e_Sijrs = Sijrs(mc,orbe, eris) logger.note(mc, "Sijrs (0) , Norm = %.14f E = %.14f", norm_Sijrs,e_Sijrs) time1 = log.timer('space Sijrs (0)', *time1) norm_Sijr , e_Sijr = Sijr(mc,orbe, dms, eris) logger.note(mc, "Sijr (+1) , Norm = %.14f E = %.14f", norm_Sijr, e_Sijr) time1 = log.timer('space Sijr (+1)', *time1) norm_Srsi , e_Srsi = Srsi(mc,orbe, dms, eris) logger.note(mc, "Srsi (-1) , Norm = %.14f E = %.14f", norm_Srsi, e_Srsi) time1 = log.timer('space Srsi (-1)', *time1) norm_Srs , e_Srs = Srs(mc,orbe, dms, eris) logger.note(mc, "Srs (-2) , Norm = %.14f E = %.14f", norm_Srs , e_Srs ) time1 = log.timer('space Srs (-2)', *time1) norm_Sij , e_Sij = Sij(mc,orbe, dms, eris) logger.note(mc, "Sij (+2) , Norm = %.14f E = %.14f", norm_Sij , e_Sij ) time1 = log.timer('space Sij (+2)', *time1) norm_Sir , e_Sir = Sir(mc,orbe, dms, eris) logger.note(mc, "Sir (0)' , Norm = %.14f E = %.14f", norm_Sir , e_Sir ) time1 = log.timer("space Sir (0)'", *time1) nevpt_e = e_Sr + e_Si + e_Sijrs + e_Sijr + e_Srsi + e_Srs + e_Sij + e_Sir logger.note(mc, "Nevpt2 Energy = %.15f", nevpt_e) log.timer('SC-NEVPT2', *time0) return nevpt_e
def get_t3p2_imds_slow(cc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None): """Calculates T1, T2 amplitudes corrected by second-order T3 contribution and intermediates used in IP/EA-CCSD(T)a Args: cc (:obj:`GCCSD`): Object containing coupled-cluster results. t1 (:obj:`ndarray`): T1 amplitudes. t2 (:obj:`ndarray`): T2 amplitudes from which the T3[2] amplitudes are formed. eris (:obj:`_PhysicistsERIs`): Antisymmetrized electron-repulsion integrals in physicist's notation. t3p2_ip_out (:obj:`ndarray`): Store results of the intermediate used in IP-EOM-CCSD(T)a. t3p2_ea_out (:obj:`ndarray`): Store results of the intermediate used in EA-EOM-CCSD(T)a. Returns: delta_ccsd (float): Difference of perturbed and unperturbed CCSD ground-state energy, energy(T1 + T1[2], T2 + T2[2]) - energy(T1, T2) pt1 (:obj:`ndarray`): Perturbatively corrected T1 amplitudes. pt2 (:obj:`ndarray`): Perturbatively corrected T2 amplitudes. Reference: D. A. Matthews, J. F. Stanton "A new approach to approximate..." JCP 145, 124102 (2016); DOI:10.1063/1.4962910, Equation 14 Shavitt and Bartlett "Many-body Methods in Physics and Chemistry" 2009, Equation 10.33 """ if eris is None: eris = cc.ao2mo() fock = eris.fock nocc, nvir = t1.shape fov = fock[:nocc, nocc:] #foo = fock[:nocc, :nocc].diagonal() #fvv = fock[nocc:, nocc:].diagonal() mo_e_o = eris.mo_energy[:nocc] mo_e_v = eris.mo_energy[nocc:] oovv = _cp(eris.oovv) ovvv = _cp(eris.ovvv) ooov = _cp(eris.ooov) oovv = _cp(eris.oovv) vooo = _cp(ooov).conj().transpose(3, 2, 1, 0) vvvo = _cp(ovvv).conj().transpose(3, 2, 1, 0) ccsd_energy = cc.energy(t1, t2, eris) dtype = np.result_type(t1, t2) if np.issubdtype(dtype, np.dtype(complex).type): logger.error( cc, 't3p2 imds has not been strictly checked for use with complex integrals' ) if t3p2_ip_out is None: t3p2_ip_out = np.zeros((nocc, nvir, nocc, nocc), dtype=dtype) Wmcik = t3p2_ip_out if t3p2_ea_out is None: t3p2_ea_out = np.zeros((nvir, nvir, nvir, nocc), dtype=dtype) Wacek = t3p2_ea_out tmp_t3 = lib.einsum('bcdk,ijad->ijkabc', vvvo, t2) tmp_t3 -= lib.einsum('cmkj,imab->ijkabc', vooo, t2) # P(ijk) tmp_t3 = (tmp_t3 + tmp_t3.transpose(1, 2, 0, 3, 4, 5) + tmp_t3.transpose(2, 0, 1, 3, 4, 5)) # P(abc) tmp_t3 = (tmp_t3 + tmp_t3.transpose(0, 1, 2, 4, 5, 3) + tmp_t3.transpose(0, 1, 2, 5, 3, 4)) eia = mo_e_o[:, None] - mo_e_v[None, :] eijab = eia[:, None, :, None] + eia[None, :, None, :] eijkabc = eijab[:, :, None, :, :, None] + eia[None, None, :, None, None, :] tmp_t3 /= eijkabc pt1 = 0.25 * lib.einsum('mnef,imnaef->ia', oovv, tmp_t3) pt2 = lib.einsum('ijmabe,me->ijab', tmp_t3, fov) tmp2 = ovvv - 0.0 * lib.einsum('nmef,nb->mbfe', oovv, t1) tmp = lib.einsum('ijmaef,mbfe->ijab', tmp_t3, tmp2) tmp = tmp - tmp.transpose(0, 1, 3, 2) # P(ab) tmp *= 0.5 pt2 = pt2 + tmp tmp2 = ooov + 0.0 * lib.einsum('mnef,jf->nmje', oovv, t1) tmp = lib.einsum('inmabe,nmje->ijab', tmp_t3, tmp2) tmp *= -0.5 tmp = tmp - tmp.transpose(1, 0, 2, 3) # P(ij) pt2 = pt2 + tmp eia = mo_e_o[:, None] - mo_e_v[None, :] eijab = eia[:, None, :, None] + eia[None, :, None, :] pt1 /= eia pt2 /= eijab pt1 = pt1 + t1 pt2 = pt2 + t2 Wmcik += 0.5 * lib.einsum('ijkabc,mjab->mcik', tmp_t3, oovv) Wacek += -0.5 * lib.einsum('ijkabc,ijeb->acek', tmp_t3, oovv) delta_ccsd_energy = cc.energy(pt1, pt2, eris) - ccsd_energy logger.info(cc, 'CCSD energy T3[2] correction : %16.12e', delta_ccsd_energy) return delta_ccsd_energy, pt1, pt2, Wmcik, Wacek
def label_orb_symm(mol, irrep_name, symm_orb, mo, s=None, check=True): '''Label the symmetry of given orbitals irrep_name can be either the symbol or the ID of the irreducible representation. If the ID is provided, it returns the numeric code associated with XOR operator, see :py:meth:`symm.param.IRREP_ID_TABLE` Args: mol : an instance of :class:`Mole` irrep_name : list of str or int A list of irrep ID or name, it can be either mol.irrep_id or mol.irrep_name. It can affect the return "label". symm_orb : list of 2d array the symmetry adapted basis mo : 2d array the orbitals to label Returns: list of symbols or integers to represent the irreps for the given orbitals Examples: >>> from pyscf import gto, scf, symm >>> mol = gto.M(atom='H 0 0 0; H 0 0 1', basis='ccpvdz',verbose=0, symmetry=1) >>> mf = scf.RHF(mol) >>> mf.kernel() >>> symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mf.mo_coeff) ['Ag', 'B1u', 'Ag', 'B1u', 'B2u', 'B3u', 'Ag', 'B2g', 'B3g', 'B1u'] >>> symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mf.mo_coeff) [0, 5, 0, 5, 6, 7, 0, 2, 3, 5] ''' nmo = mo.shape[1] if s is None: s = mol.intor_symmetric('cint1e_ovlp_sph') mo_s = numpy.dot(mo.T, s) norm = numpy.empty((len(irrep_name), nmo)) for i,ir in enumerate(irrep_name): moso = numpy.dot(mo_s, symm_orb[i]) norm[i] = numpy.einsum('ij,ij->i', moso, moso) iridx = numpy.argmax(norm, axis=0) orbsym = [irrep_name[i] for i in iridx] logger.debug(mol, 'irreps of each MO %s', str(orbsym)) if check: norm[iridx,numpy.arange(nmo)] = 0 orbidx = numpy.where(norm > THRESHOLD) if orbidx[1].size > 0: idx = numpy.where(norm > THRESHOLD*1e2) if idx[1].size > 0: logger.error(mol, 'orbitals %s not symmetrized, norm = %s', idx[1], norm[idx]) raise ValueError('orbitals %s not symmetrized' % numpy.unique(idx[1])) else: logger.warn(mol, 'orbitals %s not strictly symmetrized.', numpy.unique(orbidx[1])) logger.warn(mol, 'They can be symmetrized with ' 'pyscf.symm.symmetrize_orb function.') logger.debug(mol, 'norm = %s', norm[orbidx]) return orbsym
def DMRG_COMPRESS_NEVPT(mc, maxM=500, root=0, nevptsolver=None, tol=1e-7, nevpt_integral=None): if isinstance(nevpt_integral, str) and h5py.is_hdf5(nevpt_integral): nevpt_integral_file = os.path.abspath(nevpt_integral) mol = chkfile.load_mol(nevpt_integral_file) fh5 = h5py.File(nevpt_integral_file, 'r') ncas = fh5['mc/ncas'][()] ncore = fh5['mc/ncore'][()] nvirt = fh5['mc/nvirt'][()] nelecas = fh5['mc/nelecas'][()] nroots = fh5['mc/nroots'][()] wfnsym = fh5['mc/wfnsym'][()] fh5.close() else: mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas - mc.ncore nelecas = mc.nelecas nroots = mc.fcisolver.nroots wfnsym = mc.fcisolver.wfnsym nevpt_integral_file = None if nevptsolver is None: nevptsolver = default_nevpt_schedule(mc.fcisolver, maxM, tol) #nevptsolver.__dict__.update(mc.fcisolver.__dict__) nevptsolver.wfnsym = wfnsym nevptsolver.block_extra_keyword = mc.fcisolver.block_extra_keyword nevptsolver.nroots = nroots nevptsolver.executable = settings.BLOCKEXE_COMPRESS_NEVPT if nevptsolver.executable == getattr(mc.fcisolver, 'executable', None): logger.warn( mc, 'DMRG executable file for nevptsolver is the same ' 'to the executable file for DMRG solver. If they are ' 'both compiled by MPI compilers, they may cause error or ' 'random results in DMRG-NEVPT calculation.') nevpt_scratch = os.path.abspath(nevptsolver.scratchDirectory) dmrg_scratch = os.path.abspath(mc.fcisolver.scratchDirectory) # Integrals are not given by the kwarg nevpt_integral if nevpt_integral_file is None: nevpt_integral_file = os.path.join(nevpt_scratch, 'nevpt_perturb_integral') write_chk(mc, root, nevpt_integral_file) conf = dmrgci.writeDMRGConfFile( nevptsolver, nelecas, False, with_2pdm=False, extraline=['fullrestart', 'nevpt_state_num %d' % root]) with open(conf, 'r') as f: block_conf = f.readlines() block_conf = [l for l in block_conf if 'prefix' not in l] block_conf = ''.join(block_conf) with h5py.File(nevpt_integral_file, 'a') as fh5: if 'dmrg.conf' in fh5: del (fh5['dmrg.conf']) fh5['dmrg.conf'] = block_conf if nevptsolver.verbose >= logger.DEBUG1: logger.debug1(nevptsolver, 'Block Input conf') logger.debug1(nevptsolver, block_conf) t0 = (time.clock(), time.time()) # function nevpt_integral_mpi is called in this cmd cmd = ' '.join( (nevptsolver.mpiprefix, os.path.realpath(os.path.join(__file__, '..', 'nevpt_mpi.py')), nevpt_integral_file, nevptsolver.executable, dmrg_scratch, nevpt_scratch)) logger.debug(nevptsolver, 'DMRG_COMPRESS_NEVPT cmd %s', cmd) try: output = subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: logger.error(nevptsolver, cmd) raise err if nevptsolver.verbose >= logger.DEBUG1: logger.debug1( nevptsolver, open(os.path.join(nevpt_scratch, '0', 'dmrg.out')).read()) perturb_file = os.path.join(nevpt_scratch, '0', 'Perturbation_%d' % root) fh5 = h5py.File(perturb_file, 'r') Vi_e = fh5['Vi/energy'][()] Vr_e = fh5['Vr/energy'][()] fh5.close() logger.note(nevptsolver, 'Nevpt Energy:') logger.note(nevptsolver, 'Sr Subspace: E = %.14f' % (Vr_e)) logger.note(nevptsolver, 'Si Subspace: E = %.14f' % (Vi_e)) logger.timer(nevptsolver, 'MPS NEVPT calculation time', *t0) return perturb_file
def sc_nevpt(mc, ci=None, useMPS=False, verbose=None): '''Strongly contracted NEVPT2''' if ci is None: ci=mc.ci #mc.cas_natorb(ci=ci) if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(mc.stdout, mc.verbose) time0 = (time.clock(), time.time()) #By defaut, mc is canonicalized for the first root. #For SC-NEVPT based on compressed MPS perturber functions, the mc was already canonicalized. if mc.fcisolver.nroots > 1 and not useMPS: mc.mo_coeff,_, mc.mo_energy = mc.canonicalize(mc.mo_coeff,ci=ci,verbose=log) if hasattr(mc.fcisolver, 'nevpt_intermediate'): logger.info(mc, 'DMRG-NEVPT') dm1, dm2, dm3 = mc.fcisolver.make_rdm123(ci,mc.ncas,mc.nelecas,None) else: if useMPS: logger.error(mc,"MPS nevpt only used for DMRG calculation") exit() dm1, dm2, dm3 = fci.rdm.make_dm123('FCI3pdm_kern_sf', ci, ci, mc.ncas, mc.nelecas) dm4 = None dms = {'1': dm1, '2': dm2, '3': dm3, '4': dm4, #'h1': hdm1, 'h2': hdm2, 'h3': hdm3 } time1 = log.timer('3pdm, 4pdm', *time0) eris = _ERIS(mc, mc.mo_coeff) time1 = log.timer('integral transformation', *time1) nocc = mc.ncore + mc.ncas if not hasattr(mc.fcisolver, 'nevpt_intermediate'): # regular FCI solver link_indexa = fci.cistring.gen_linkstr_index(range(mc.ncas), mc.nelecas[0]) link_indexb = fci.cistring.gen_linkstr_index(range(mc.ncas), mc.nelecas[1]) aaaa = eris['ppaa'][mc.ncore:nocc,mc.ncore:nocc].copy() f3ca = _contract4pdm('NEVPTkern_cedf_aedf', aaaa, ci, mc.ncas, mc.nelecas, (link_indexa,link_indexb)) f3ac = _contract4pdm('NEVPTkern_aedf_ecdf', aaaa, ci, mc.ncas, mc.nelecas, (link_indexa,link_indexb)) dms['f3ca'] = f3ca dms['f3ac'] = f3ac time1 = log.timer('eri-4pdm contraction', *time1) if useMPS: fh5 = h5py.File('Perturbation_%d'%ci,'r') e_Si = fh5['Vi/energy'].value #The definition of norm changed. #However, there is no need to print out it. #Only perturbation energy is wanted. norm_Si = fh5['Vi/norm'].value e_Sr = fh5['Vr/energy'].value norm_Sr = fh5['Vr/norm'].value fh5.close() logger.note(mc, "Sr (-1)' E = %.14f", e_Sr ) logger.note(mc, "Si (+1)' E = %.14f", e_Si ) else: norm_Sr , e_Sr = Sr(mc,ci, dms, eris) logger.note(mc, "Sr (-1)', E = %.14f", e_Sr ) time1 = log.timer("space Sr (-1)'", *time1) norm_Si , e_Si = Si(mc,ci, dms, eris) logger.note(mc, "Si (+1)', E = %.14f", e_Si ) time1 = log.timer("space Si (+1)'", *time1) norm_Sijrs, e_Sijrs = Sijrs(mc, eris) logger.note(mc, "Sijrs (0) , E = %.14f", e_Sijrs) time1 = log.timer('space Sijrs (0)', *time1) norm_Sijr , e_Sijr = Sijr(mc, dms, eris) logger.note(mc, "Sijr (+1) , E = %.14f", e_Sijr) time1 = log.timer('space Sijr (+1)', *time1) norm_Srsi , e_Srsi = Srsi(mc, dms, eris) logger.note(mc, "Srsi (-1) , E = %.14f", e_Srsi) time1 = log.timer('space Srsi (-1)', *time1) norm_Srs , e_Srs = Srs(mc, dms, eris) logger.note(mc, "Srs (-2) , E = %.14f", e_Srs ) time1 = log.timer('space Srs (-2)', *time1) norm_Sij , e_Sij = Sij(mc, dms, eris) logger.note(mc, "Sij (+2) , E = %.14f", e_Sij ) time1 = log.timer('space Sij (+2)', *time1) norm_Sir , e_Sir = Sir(mc, dms, eris) logger.note(mc, "Sir (0)' , E = %.14f", e_Sir ) time1 = log.timer("space Sir (0)'", *time1) nevpt_e = e_Sr + e_Si + e_Sijrs + e_Sijr + e_Srsi + e_Srs + e_Sij + e_Sir logger.note(mc, "Nevpt2 Energy = %.15f", nevpt_e) log.timer('SC-NEVPT2', *time0) return nevpt_e
def kernel(self): self.get_init() sys.exit() # rgvb.load_mo(self, in_pre2b+'_gvb.fchk') # self.mo_coeff[:,[6,7,8]]=self.mo_coeff[:,[7,8,6]] # swap orbital # self.ci[7,0]=0.998570; self.ci[7,1]=-0.053452 # self.ci[6,0]=0.981710; self.ci[6,1]=-0.190382 # self.mol.intor_symmetric('int1e_kin')+mol.intor_symmetric('int1e_nuc') hcore = scf.hf.get_hcore(self.mol) self.h_mo = reduce(numpy.dot, (self.mo_coeff.T, hcore, self.mo_coeff)) eri = self.mol.intor('int2e', aosym='s8') global i_lowTri; i_lowTri = [0]*self.nobt for i in range(1, self.nobt): i_lowTri[i] = i_lowTri[i-1]+i from pyscf import ao2mo # self.g_mo=ao2mo.outcore.full_iofree(self.mo_coeff[:,:self.nocc+self.npair_d],self.mo_coeff[:,:self.nocc+self.npair_d]) self.g_mo = ao2mo.kernel(eri, self.mo_coeff) # s4 # eri = self.mol.intor('int2e_cart', aosym='s8') # eri = self.mol.intor('int2e', aosym='s8') # self.g_mo = ao2mo.incore.full(ao2mo.restore(8, eri, self.nbs), self.mo_coeff) # check HF energy for i in range(self.nocc): logger.note(self, '%2d(%6f) <-> %2d(%6f)' % (self.pair[i, 0] + 1, self.ci[i, 0], self.pair[i, 1] + 1, self.ci[i, 1])) self.e_ele = self.energy_elec() self.e_tot = self.e_ele+self.e_nuc logger.note(self, 'e_ele = %10f, e_tot = %.10f' %(self.e_ele,self.e_tot)) self.opt_ci() self.e_tot = self.e_ele + self.e_nuc for i in range(self.nocc-self.npair_d,self.nocc): logger.note(self, '%2d(%6f) <-> %2d(%6f)' %(self.pair[i,0]+1, self.ci[i,0], self.pair[i,1]+1, self.ci[i,1])) logger.note(self, 'e_ele = %10f, e_tot = %.10f' % (self.e_ele, self.e_tot)) # rgvb.dump_mo(self, '%s_init.fchk' %in_pre2b, reffile) logger.note(self, 'start local optimization iteration') logger.note(self, ' it energy delta') logger.note(self, ' it obt1 orb2 q4 q3 q2 q1 theta energy delta(E) fun delta(f)') for it in range(self.max_cycle[0]): _e_ele = self.e_ele for u in reversed(range(self.nocc)): for i in range(2): if u < self.nocc-self.npair_d and i==1: continue for v in reversed(range(self.nocc-self.npair_d-self.nsig, self.nocc)): for j in range(2): if v < self.nocc - self.npair_d and j == 1: # 注意:单占据的geminal,只能j=0,不能j=1, continue # 因为默认单占据s=0,若j取到1时,也被设置为s=0,而vj=1是core轨道,双占据,就不对了 if u==v and i==j: continue b1 = 8*self.ci[u,i]**2 * self.ci[v,j]**2 * (1.-delta(u,v)) b2 = (self.s(u)*self.ci[u, i]**2 + self.s(v)*self.ci[v, j]**2 - 2*self.s(u)*self.ci[u, i]*self.ci[v, j]*delta(u, v) - 2 * self.ci[u, i]**2 * self.ci[v, j]**2 * (2-self.t(u,v)) * (1.-delta(u,v))) auv = (b1*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,j], self.pair[v,j])] - self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) +2.*(self.w(u,i,v,j,v,j) - self.w(u,i,u,i,u,i) - self.w(v,j,v,j,v,j) + self.w(v,j,u,i,u,i))) buv = self.w(u,i,u,i,v,j) - self.w(v,j,u,i,v,j) q1 = 4.*buv q2 = auv + 2.*b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,j], self.pair[v,j])] + self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) q3 = 4.*(buv + b2*(self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[v,j], self.pair[v,j])] - self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[v,j])])) q4 = auv + b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[u,i])] + self.g_mo[index(self.pair[v,j], self.pair[v,j], self.pair[v,j], self.pair[v,j])] -2.*self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) # theta=root(q4,q3,q2,q1)%(math.pi*2) theta=root(q4,q3,q2,q1) # if abs(theta)>self.conv_tol[1]: f=fun(q4, q3, q2, q1, theta); __e_ele=self.e_ele orb1 = self.mo_coeff[:, self.pair[u, i]].copy() orb2 = self.mo_coeff[:, self.pair[v, j]].copy() self.mo_coeff[:, self.pair[u, i]] = orb1*math.cos(theta)+orb2*math.sin(theta) self.mo_coeff[:, self.pair[v, j]] = -orb1*math.sin(theta)+orb2*math.cos(theta) self.h_mo = reduce(numpy.dot, (self.mo_coeff.T, hcore, self.mo_coeff)) # self.g_mo = ao2mo.outcore.full_iofree( # self.mo_coeff[:, :self.nocc + self.npair_d], # self.mo_coeff[:, :self.nocc + self.npair_d]) self.g_mo = ao2mo.kernel(eri, self.mo_coeff[:,:self.nocc+self.nactvir]) # eri = self.mol.intor('int2e_cart', aosym='s8') # self.g_mo = ao2mo.incore.full(ao2mo.restore(8, eri, self.nbs), self.mo_coeff) deltaf=self.energy_elec()-__e_ele self.opt_ci() self.e_ele=self.energy_elec() self.e_tot=self.e_ele+self.e_nuc; deltaE=self.e_ele-__e_ele logger.note(self,' %3d %3d<->%3d %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f' %(it+1,self.pair[u,i]+1,self.pair[v,j]+1,q4,q3,q2,q1,theta,self.e_tot,deltaE,f,deltaf)) for v in range(self.nocc,self.nocc+self.nactvir-self.npair_d): j = 0 b2 = self.s(u)*self.ci[u,i]**2 auv = self.w(u,i,v,j,v,j) - self.w(u,i,u,i,u,i) buv = self.w(u,i,u,i,v,j) q1 = 4.*buv q2 = 2.*(auv + b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,j], self.pair[v,j])] + self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])])) q3 = 4.*(buv + b2*(self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[v,j], self.pair[v,j])] - self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[v,j])])) q4 = 2.*auv + b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[u,i])] + self.g_mo[index(self.pair[v,j], self.pair[v,j], self.pair[v,j], self.pair[v,j])] -2.*self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) # theta=root(q4,q3,q2,q1)%(math.pi*2) theta=root(q4,q3,q2,q1) # if abs(theta)>self.conv_tol[1]: f = fun(q4, q3, q2, q1, theta); __e_ele = self.e_ele orb1 = self.mo_coeff[:, self.pair[u, i]].copy() orb2 = self.mo_coeff[:, self.pair[v, j]].copy() self.mo_coeff[:, self.pair[u, i]] = orb1*math.cos(theta)+orb2*math.sin(theta) self.mo_coeff[:, self.pair[v, j]] = -orb1*math.sin(theta)+orb2*math.cos(theta) self.h_mo = reduce(numpy.dot, (self.mo_coeff.T, hcore, self.mo_coeff)) self.g_mo = ao2mo.kernel(eri, self.mo_coeff[:,:self.nocc+self.nactvir]) # eri = self.mol.intor('int2e_cart', aosym='s8') # self.g_mo = ao2mo.incore.full(ao2mo.restore(8, eri, self.nbs), self.mo_coeff) deltaf = self.energy_elec() - __e_ele self.opt_ci() self.e_ele=self.energy_elec() self.e_tot=self.e_ele+self.e_nuc; deltaE=self.e_ele-__e_ele # logger.note(self,' %3d %3d<->%3d %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f' # %(it+1,self.pair[u,i]+1,self.pair[v,j]+1,q4,q3,q3,q2,theta,self.e_tot,deltaE, f, deltaf)) # for _i in range(self.nocc-self.npair_d,self.nocc): # print('%2d(%6f) <-> %2d(%6f)' %(self.pair[_i,0]+1, self.ci[_i,0], self.pair[_i,1]+1, self.ci[_i,1])) logger.note(self,' %3d %11.8f %12.9f' %(it+1, self.e_tot, self.e_ele-_e_ele)) if abs(_e_ele-self.e_ele)<self.conv_tol[1]: break # else: rgvb.dump_mo(self, '%s_gvb_init-II.fchk' %in_pre2b, reffile) else: logger.error(self, 'Not converge in local optimization') logger.note(self, 'The GVB pair:') for _i in range(self.nocc-self.npair_d, self.nocc): logger.note(self, '%2d(%6f) <-> %2d(%6f)' %(self.pair[_i,0]+1, self.ci[_i,0], self.pair[_i,1]+1, self.ci[_i,1])) self.e_tot=self.e_nuc+self.e_ele logger.note(self, 'gvb local converged energy = %11.8f' %self.e_tot) rgvb.dump_mo(self, '%s_gvb_init-II.fchk' %in_pre2b, reffile) self.h_mo = reduce(numpy.dot, (self.mo_coeff.T, hcore, self.mo_coeff)) self.g_mo = ao2mo.kernel(eri, self.mo_coeff) logger.note(self, 'start global optimization iteration') logger.note(self, ' it energy delta') logger.note(self, ' it obt1 orb2 q4 q3 q2 q1 theta energy delta(E) fun delta(f)') for it in range(self.max_cycle[0]): _e_ele = self.e_ele for u in reversed(range(self.nocc)): for i in range(2): if u<self.nocc-self.npair_d and i==1: continue for v in reversed(range(self.nocc-self.npair_d-self.nsig, self.nocc)): for j in range(2): if v < self.nocc - self.npair_d and j == 1: # 注意:单占据的geminal,只能j=0,不能j=1, continue # 因为默认单占据s=0,若j取到1时,也被设置为s=0,而vj=1是core轨道,双占据,就不对了 if u==v and i==j: continue b1 = 8*self.ci[u,i]**2 * self.ci[v,j]**2 * (1.-delta(u,v)) b2 = (self.s(u)*self.ci[u, i]**2 + self.s(v)*self.ci[v, j]**2 - 2*self.s(u)*self.ci[u, i]*self.ci[v, j]*delta(u, v) - 2 * self.ci[u, i]**2 * self.ci[v, j]**2 * (2-self.t(u,v)) * (1.-delta(u,v))) auv = (b1*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,j], self.pair[v,j])] - self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) +2.*(self.w(u,i,v,j,v,j) - self.w(u,i,u,i,u,i) - self.w(v,j,v,j,v,j) + self.w(v,j,u,i,u,i))) buv = self.w(u,i,u,i,v,j) - self.w(v,j,u,i,v,j) q1 = 4.*buv q2 = auv + 2.*b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,j], self.pair[v,j])] + self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) q3 = 4.*(buv + b2*(self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[v,j], self.pair[v,j])] - self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[v,j])])) q4 = auv + b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[u,i])] + self.g_mo[index(self.pair[v,j], self.pair[v,j], self.pair[v,j], self.pair[v,j])] -2.*self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) # theta=root(q4,q3,q2,q1)%(math.pi*2) theta=root(q4,q3,q2,q1) # if abs(theta-0.0)>self.conv_tol[0]: f=fun(q4, q3, q2, q1, theta); __e_ele=self.e_ele orb1 = self.mo_coeff[:, self.pair[u, i]].copy() orb2 = self.mo_coeff[:, self.pair[v, j]].copy() self.mo_coeff[:, self.pair[u, i]] = orb1*math.cos(theta)+orb2*math.sin(theta) self.mo_coeff[:, self.pair[v, j]] = -orb1*math.sin(theta)+orb2*math.cos(theta) self.h_mo = reduce(numpy.dot, (self.mo_coeff.T, hcore, self.mo_coeff)) self.g_mo = ao2mo.kernel(eri, self.mo_coeff) # eri = self.mol.intor('int2e_cart', aosym='s8') # self.g_mo = ao2mo.incore.full(ao2mo.restore(8, eri, self.nbs), self.mo_coeff) deltaf=self.energy_elec()-__e_ele self.opt_ci() self.e_ele=self.energy_elec() self.e_tot=self.e_ele+self.e_nuc; deltaE=self.e_ele-__e_ele # logger.note(self,' %3d %3d<->%3d %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f' # %(it+1,self.pair[u,i]+1,self.pair[v,j]+1,q4,q3,q2,q1,theta,self.e_tot,deltaE,f,deltaf)) for v in range(self.nocc, self.npair_t): j = 0 b2 = self.s(u)*self.ci[u,i]**2 auv = self.w(u,i,v,j,v,j) - self.w(u,i,u,i,u,i) buv = self.w(u,i,u,i,v,j) q1 = 4.*buv q2 = 2.*(auv + b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[v,j], self.pair[v,j])] + self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])])) q3 = 4.*(buv + b2*(self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[v,j], self.pair[v,j])] - self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[v,j])])) q4 = 2.*auv + b2*(self.g_mo[index(self.pair[u,i], self.pair[u,i], self.pair[u,i], self.pair[u,i])] + self.g_mo[index(self.pair[v,j], self.pair[v,j], self.pair[v,j], self.pair[v,j])] -2.*self.g_mo[index(self.pair[u,i], self.pair[v,j], self.pair[u,i], self.pair[v,j])]) # theta=root(q4,q3,q2,q1)%(math.pi*2) theta=root(q4,q3,q2,q1) # if abs(theta-0.0)>self.conv_tol[0]: f=fun(q4, q3, q2, q1, theta); __e_ele=self.e_ele orb1 = self.mo_coeff[:, self.pair[u, i]].copy() orb2 = self.mo_coeff[:, self.pair[v, j]].copy() self.mo_coeff[:, self.pair[u, i]] = orb1*math.cos(theta)+orb2*math.sin(theta) self.mo_coeff[:, self.pair[v, j]] = -orb1*math.sin(theta)+orb2*math.cos(theta) self.h_mo = reduce(numpy.dot, (self.mo_coeff.T, hcore, self.mo_coeff)) self.g_mo = ao2mo.kernel(eri, self.mo_coeff) # eri = self.mol.intor('int2e_cart', aosym='s8') # self.g_mo = ao2mo.incore.full(ao2mo.restore(8, eri, self.nbs), self.mo_coeff) deltaf = self.energy_elec() - __e_ele self.opt_ci() self.e_ele=self.energy_elec() self.e_tot=self.e_ele+self.e_nuc; deltaE=self.e_ele-__e_ele # logger.note(self,' %3d %3d<->%3d %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f %12.8f' # %(it+1,self.pair[u,i]+1,self.pair[v,j]+1,q4,q3,q2,q1,theta,self.e_tot,deltaE,f,deltaf)) # for _i in range(self.nocc-self.npair_d,self.nocc): # print('%2d(%6f) <-> %2d(%6f)' %(self.pair[_i, 0]+1, self.ci[_i, 0], self.pair[_i, 1]+1, self.ci[_i, 1])) logger.note(self, ' %3d %11.8f %12.9f' % (it + 1, self.e_tot, self.e_ele - _e_ele)) if abs(_e_ele-self.e_ele)<self.conv_tol[0]: break # else: rgvb.dump_mo(self, '%s_gvb_init-III.fchk' %in_pre2b, reffile) else: raise RuntimeError('Not converge in global optimization') logger.note(self, 'The GVB pair:') for _i in range(self.nocc - self.npair_d, self.nocc): logger.note(self, '%2d(%6f) <-> %2d(%6f)' %(self.pair[_i,0]+1, self.ci[_i,0], self.pair[_i,1]+1, self.ci[_i,1])) self.e_tot=self.e_nuc+self.e_ele logger.note(self, 'gvb global converged energy = %11.8f' %self.e_tot) rgvb.dump_mo(self, '%s_gvb_init-III.fchk' % in_pre2b, reffile)