def opt_umat_homo_diff(self, umat, gtol=1e-6): ops = self.ops Ne_frag = self.Ne_frag Ne_env = self.Ne_env dim = self.dim subTEI = ops["subTEI"] subOEI1 = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc_bound1"] + umat subOEI2 = ops["subKin"] + ops["subVnuc2"] + ops[ "subVnuc_bound2"] + ops["subCoreJK"] + umat coredm = self.core1PDM_ao ao2sub = self.ao2sub[:, :dim] #frag_coredm_guess = tools.fock2onedm(subOEI1, Ne_frag//2)[0] frag_coredm_guess = self.P_imp mf_frag = qcwrap.qc_scf(Ne_frag,dim,self.mf_method,mol=self.mol,oei=subOEI1,tei=subTEI,\ dm0=frag_coredm_guess,coredm=0.0,ao2sub=ao2sub, smear_sigma = 0.0) mf_frag.runscf() #env_coredm_guess = tools.fock2onedm(subOEI2, Ne_env//2)[0] env_coredm_guess = self.P_bath mf_env = qcwrap.qc_scf(Ne_env,dim,self.mf_method,mol=self.mol,oei=subOEI2,tei=subTEI,\ dm0=env_coredm_guess,coredm=coredm,ao2sub=ao2sub, smear_sigma = 0.0) mf_env.runscf() print(np.linalg.norm(mf_frag.rdm1 - self.P_imp)) print(np.linalg.norm(mf_env.rdm1 - self.P_bath)) diffP = mf_frag.rdm1 + mf_env.rdm1 - self.P_ref print("|P_frag + P_env - P_ref| = ", np.linalg.norm(diffP)) print("max element of (P_frag + P_env - P_ref) = ", np.amax(np.absolute(diffP))) self.P_imp = mf_frag.rdm1 self.P_bath = mf_env.rdm1 #build null space vint = self.build_null_space(mf_frag, mf_env, Ne_frag, Ne_env, dim) if vint is None: return umat #minimize |ehomo_A-ehomo_B|^2 x0 = tools.mat2vec(umat, dim) n = vint.shape[-1] c = np.zeros((n)) res = self.minimize_ehomo_2(c, x0, vint, gtol) c = res.x #print '|c| = ', np.linalg.norm(c) for i in range(n): x0 += c[i] * vint[:, i] umat = tools.vec2mat(x0, dim) #xmat = xmat - np.eye( xmat.shape[ 0 ] ) * np.average( np.diag( xmat ) ) #tools.MatPrint(umat,'umat') #print '|umat| = ', np.linalg.norm(umat) return umat
def imp_mf_energy_dfet(self, dim): Ne_frag = self.Ne_frag ops = self.ops Vemb = self.umat Vxc = None subOEI = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc_bound1"] + Vemb subTEI = ops["subTEI"] ao2sub = self.ao2sub[:, :dim] mf = qcwrap.qc_scf(Ne_frag, dim, self.mf_method, mol=self.mol_frag, oei=subOEI, tei=subTEI, dm0=self.P_imp, coredm=0.0, ao2sub=ao2sub) #mf.init_guess = 'minao' mf.runscf() energy = mf.elec_energy #- np.trace(np.dot(mf.rdm1,Vemb)) print('|diffP| = ', np.linalg.norm(mf.rdm1 + self.P_bath - self.P_ref_sub)) print("embeded imp scf (electron) energy = ", energy) self.P_imp = mf.rdm1 return (energy, Vemb, Vxc)
def ks_ccsd_energy(self, dim): print("ECW method is CCSD") energy = 0.0 Ne_frag = self.Ne_frag ops = self.ops umat = self.umat subOEI = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc_bound1"] + umat subTEI = ops["subTEI"] ao2sub = self.ao2sub[:, :dim] mf = qcwrap.qc_scf(Ne_frag, dim, self.mf_method, mol=self.mol, oei=subOEI, tei=subTEI, dm0=self.P_imp, coredm=0.0, ao2sub=ao2sub) mf.runscf() e_ks = mf.elec_energy print("e_ks = ", e_ks) #HF JK veff = self.ints.impJK_sub(mf.make_rdm1(), subTEI) mf.get_veff = lambda *args: veff print("incore_anyway: ", mf.mol.incore_anyway) e_emb = 0.0 #onedm = mf.make_rdm1() #e_emb=np.trace(np.dot(umat,onedm)) #print "diffP = ",np.linalg.norm(self.P_imp - onedm) e_hf = pyscf.scf.hf.energy_elec(mf, mf.make_rdm1(), subOEI, veff)[0] print("e_hf = ", e_hf) mycc = cc.CCSD(mf).run() et = 0.0 if (self.ecw_method == 'ccsd(t)'): print('CCSD(T) correction') et = mycc.ccsd_t() #ccsd_dm_mo = mycc.make_rdm1() #ccsd_dm_sub = tools.dm_loc2ao(ccsd_dm_mo,mf.mo_coeff) #e_emb=np.trace(np.dot(umat,ccsd_dm_sub)) print(mycc.e_corr + et) e_ccsd = e_hf + mycc.e_corr + et e_ccsd -= e_emb print(e_ccsd) energy = e_ccsd - e_ks print("dmfet correction energy = ", energy) return energy
def imp_mf_energy2(self, dim): Ne_frag = self.Ne_frag ops = self.ops umat = self.umat proj = 0.5 * self.P_bath energy_shift = 1e5 Vemb = umat + energy_shift * proj Vxc = None subOEI = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc_bound1"] + Vemb subTEI = ops["subTEI"] ao2sub = self.ao2sub[:, :dim] mf = qcwrap.qc_scf(Ne_frag, dim, self.mf_method, mol=self.mol_frag, oei=subOEI, tei=subTEI, dm0=self.P_imp, coredm=0.0, ao2sub=ao2sub) mf.runscf() energy = mf.elec_energy print('|diffP| = ', np.linalg.norm(mf.rdm1 + self.P_bath - self.P_ref_sub)) print("embeded imp scf (electron) energy = ", energy) self.P_imp = mf.rdm1 return (energy, Vemb, Vxc)
def total_scf_energy(self): energy = 0.0 Norb = self.dim_sub Ne = self.Ne_frag + self.Ne_env ops = self.ops subOEI = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc2"] + ops[ "subCoreJK"] subTEI = ops["subTEI"] coredm = self.core1PDM_ao ao2sub = self.ao2sub[:, :Norb] #dm_guess = tools.fock2onedm(subOEI, Ne//2)[0] dm_guess = self.P_ref_sub mf = qcwrap.qc_scf(True, mol=self.mol, Ne=Ne, Norb=Norb, method=self.mf_method, \ oei=subOEI, tei=subTEI, dm0=dm_guess, coredm=coredm, ao2sub=ao2sub, smear_sigma = self.smear_sigma) #mf.init_guess = 'minao' mf.kernel() print('max(P_tot - P_ref) = ', np.amax(np.absolute(mf.rdm1 - self.P_ref_sub))) print('|P_tot - P_ref| = ', np.linalg.norm(mf.rdm1 - self.P_ref_sub)) self.ints.submo_molden(mf.mo_coeff, mf.mo_occ, self.loc2sub, "total_system_mo.molden", self.mol) energy = mf.elec_energy + self.core_energy() + self.ints.energy_nuc() print('total scf energy = %.15g ' % energy) print('%.15g, %.15g, %.15g' % (mf.elec_energy, self.core_energy(), self.ints.energy_nuc())) return energy
def debug_loc_orb(self): #fock = self.fock_loc() #eigvals, eigvecs = np.linalg.eigh(fock) ##eigvecs = eigvecs[ :, eigvals.argsort() ] #print eigvals oei = self.hcore_loc() tei = self.tei_loc() Ne = self.Nelec NOrb = self.NOrb mf = qcwrap.qc_scf(Ne, NOrb, 'hf', mol=self.mol, oei=oei, tei=tei) mf.runscf() #print mf.elec_energy mycc = cc.CCSD(mf).run() et = 0.0 et = mycc.ccsd_t() e_hf = mf.elec_energy + self.energy_nuc() print(e_hf) print(mycc.e_corr + et) e_ccsd = e_hf + mycc.e_corr + et print('total ccsd(t) energy = ', e_ccsd) exit()
def ccsd_energy_beta(self, dim): mol = self.mol_frag natm = mol.natm mol1 = mol.copy() for i in range(natm): if (self.deproton[i] == 1): mol1._atm[i][0] = 0 #make proton ghost print('mol_frag de:') print(mol1._atm) vnuc_sub = libgen.frag_vnuc_sub(mol1, self.ints, self.loc2sub, dim) print("ECW method is CCSD") energy = 0.0 Ne_frag = self.Ne_frag ops = self.ops umat = self.umat subOEI = ops["subKin"] + vnuc_sub + ops["subVnuc_bound1"] + umat subTEI = ops["subTEI"] mf = qcwrap.qc_scf(Ne_frag, dim, 'hf', mol=None, oei=subOEI, tei=subTEI, dm0=self.P_imp) mf.runscf() e_emb = 0.0 #onedm = mf.make_rdm1() #e_emb=np.trace(np.dot(umat,onedm)) #print "diffP = ",np.linalg.norm(self.P_imp - onedm) print(mf.elec_energy) mycc = cc.CCSD(mf).run() et = 0.0 if (self.ecw_method == 'ccsd(t)'): print('CCSD(T) correction') et = mycc.ccsd_t() e_hf = mf.elec_energy print(mycc.e_corr + et) e_ccsd = e_hf + mycc.e_corr + et e_ccsd -= e_emb print(e_ccsd) imp_mf_energy = self.imp_mf_energy_beta(dim) energy = e_ccsd - imp_mf_energy print("dmfet correction energy = ", energy) return energy
def mp2_energy(self, dim): print("ECW method is MP2") energy = 0.0 Ne_frag = self.Ne_frag ops = self.ops umat = self.umat Ne_env = self.Ne_env P_bath_JK = libgen.coreJK_sub( self.ints, self.loc2sub, dim, tools.dm_sub2ao(self.P_bath, self.loc2sub[:, :dim]), Ne_env, 1.0) subOEI = ops["subKin"] + ops["subVnuc1"] + ops[ "subVnuc2"] + P_bath_JK + 0.5 * 1e4 * self.P_bath #subOEI = ops["subKin"]+ops["subVnuc1"]+ops["subVnuc_bound1"]+umat subTEI = ops["subTEI"] mf = qcwrap.qc_scf(Ne_frag, dim, 'hf', mol=self.mol, oei=subOEI, tei=subTEI, dm0=self.P_imp) mf.runscf() #self.ints.submo_molden( mf.mo_coeff, mf.mo_occ, self.loc2sub, 'mo_imp.molden' ) print('|diffP| = ', np.linalg.norm(mf.rdm1 + self.P_bath - self.P_ref_sub)) print("mo_energy") print(mf.mo_energy) e_emb = 0.0 #onedm = mf.make_rdm1() #e_emb=np.trace(np.dot(umat,onedm)) #print "diffP = ",np.linalg.norm(self.P_imp - onedm) mp2 = mp.MP2(mf) mp2.kernel() e_mp2 = mf.elec_energy + mp2.e_corr e_mp2 -= e_emb imp_mf_energy = self.imp_mf_energy(dim) energy = e_mp2 - imp_mf_energy print("dmfet correction energy = ", energy) return energy
def imp_mf_energy_beta(self, dim): mol = self.mol_frag natm = mol.natm mol1 = mol.copy() for i in range(natm): if (self.deproton[i] == 1): mol1._atm[i][0] = 0 #make proton ghost vnuc_sub = libgen.frag_vnuc_sub(mol1, self.ints, self.loc2sub, dim) Ne_frag = self.Ne_frag ops = self.ops umat = self.umat subOEI = ops["subKin"] + vnuc_sub + ops["subVnuc_bound1"] + umat subTEI = ops["subTEI"] ao2sub = self.ao2sub[:, :dim] mf = qcwrap.qc_scf(Ne_frag, dim, self.mf_method, mol=self.mol, oei=subOEI, tei=subTEI, dm0=self.P_imp, coredm=0.0, ao2sub=ao2sub) mf.runscf() energy = mf.elec_energy e_emb = 0.0 #onedm = mf.make_rdm1() #e_emb = np.trace(np.dot(umat,onedm)) energy -= e_emb print("embeded imp scf (electron) energy = ", energy) return energy
def cost_ehomo_2(self, c, x0, vint): x = x0.copy() n = len(c) for i in range(n): x += c[i] * vint[:, i] ops = self.ops Ne_frag = self.Ne_frag Ne_env = self.Ne_env dim = self.dim umat = tools.vec2mat(x, dim) subTEI = ops["subTEI"] subOEI1 = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc_bound1"] + umat subOEI2 = ops["subKin"] + ops["subVnuc2"] + ops[ "subVnuc_bound2"] + ops["subCoreJK"] + umat coredm = self.core1PDM_ao ao2sub = self.ao2sub[:, :dim] frag_coredm_guess = self.P_imp mf_frag = qcwrap.qc_scf(Ne_frag,dim,self.mf_method,mol=self.mol,oei=subOEI1,tei=subTEI,\ dm0=frag_coredm_guess,coredm=0.0,ao2sub=ao2sub, smear_sigma = 0.0) mf_frag.runscf() env_coredm_guess = self.P_bath mf_env = qcwrap.qc_scf(Ne_env,dim,self.mf_method,mol=self.mol,oei=subOEI2,tei=subTEI,\ dm0=env_coredm_guess,coredm=coredm,ao2sub=ao2sub, smear_sigma = 0.0) mf_env.runscf() diffP = mf_frag.rdm1 + mf_env.rdm1 - self.P_ref #print "|P_frag + P_env - P_ref| = ", np.linalg.norm(diffP) #print "max element of (P_frag + P_env - P_ref) = ", np.amax(np.absolute(diffP) ) ehomo_A = mf_frag.mo_energy[Ne_frag // 2 - 1] ehomo_B = mf_env.mo_energy[Ne_env // 2 - 1] delta_ehomo = ehomo_A - ehomo_B #print 'ehomo_A=',ehomo_A,' ehomo_B=',ehomo_B, ' delta_ehomo=', delta_ehomo elumo_A = mf_frag.mo_energy[Ne_frag // 2] elumo_B = mf_env.mo_energy[Ne_env // 2] delta_elumo = elumo_A - elumo_B #print 'elumo_A=',elumo_A,' elumo_B=',elumo_B, ' delta_elumo=', delta_elumo #objective function f = delta_ehomo * delta_ehomo + delta_elumo * delta_elumo #+ (elumo_A-ehomo_A-0.3)**2 homo_A = mf_frag.mo_coeff[:, Ne_frag // 2 - 1] homo_B = mf_env.mo_coeff[:, Ne_env // 2 - 1] lumo_A = mf_frag.mo_coeff[:, Ne_frag // 2] lumo_B = mf_env.mo_coeff[:, Ne_env // 2] #gradient g = np.zeros((n)) for i in range(n): tmp = tools.vec2mat(vint[:, i], dim) EA = np.dot(homo_A, np.dot(tmp, homo_A)) EB = np.dot(homo_B, np.dot(tmp, homo_B)) g[i] = 2.0 * delta_ehomo * (EA - EB) EA = np.dot(lumo_A, np.dot(tmp, lumo_A)) EB = np.dot(lumo_B, np.dot(tmp, lumo_B)) g[i] += 2.0 * delta_elumo * (EA - EB) #EB=np.dot(homo_A,np.dot(tmp,homo_A)) #g[i] += 2.0*(elumo_A-ehomo_A-0.3)*(EA-EB) return (f, g)
def verify_scf(self, umat): ''' Extra SCF calculations with final umat ''' print('========================================') print(' SCF with converged embedding potential ') print('========================================') Ne_frag = self.Ne_frag Ne_env = self.Ne_env dim = self.dim dm0_frag = self.P_imp if self.use_suborb: coredm = self.core1PDM_ao ao2sub = self.ao2sub[:, :dim] mf_frag = qcwrap.qc_scf(True, mol=self.mol_frag, Ne=Ne_frag, Norb=dim, method=self.mf_method,\ vext_1e=umat, oei=self.oei_frag, tei=self.tei,\ dm0=dm0_frag, coredm=0.0, ao2sub=ao2sub, smear_sigma = self.smear_sigma,\ max_cycle=self.scf_max_cycle) else: mf_frag = qcwrap.qc_scf(False, mol=self.mol_frag, xc_func=self.mf_method,\ vext_1e=umat, extra_oei=self.vnuc_bound_frag_ao, \ dm0=dm0_frag, smear_sigma = self.smear_sigma, max_cycle=self.scf_max_cycle) #mf_frag.init_guess = 'minao' #mf_frag.conv_check = False mf_frag.kernel() FRAG_energy = mf_frag.elec_energy FRAG_1RDM = mf_frag.rdm1 frag_mo = mf_frag.mo_coeff frag_occ = mf_frag.mo_occ #mf_frag.stability(internal=True, external=False, verbose=5) dm0_env = self.P_bath if self.use_suborb: mf_env = qcwrap.qc_scf(True, mol=self.mol_env, Ne=Ne_env, Norb=dim, method=self.mf_method, \ vext_1e=umat, oei=self.oei_env, tei=self.tei,\ dm0=dm0_env, coredm=coredm, ao2sub=ao2sub, smear_sigma = self.smear_sigma,\ max_cycle=self.scf_max_cycle) else: mf_env = qcwrap.qc_scf(False, mol=self.mol_env, xc_func=self.mf_method, \ vext_1e=umat, extra_oei=self.vnuc_bound_env_ao, \ dm0=dm0_env, smear_sigma = self.smear_sigma, max_cycle=self.scf_max_cycle) #mf_env.init_guess = 'minao' #mf_env.conv_check = False mf_env.kernel() ENV_energy = mf_env.elec_energy ENV_1RDM = mf_env.rdm1 env_mo = mf_env.mo_coeff env_occ = mf_env.mo_occ print("scf energies:") print("EA (no vemb contrib.) = ", FRAG_energy - np.trace(np.dot(FRAG_1RDM, umat))) print("EB (no vemb contrib.) = ", ENV_energy - np.trace(np.dot(ENV_1RDM, umat))) #print np.trace(np.dot(FRAG_1RDM,umat)), np.trace(np.dot(ENV_1RDM,umat)),np.trace(np.dot(FRAG_1RDM+ENV_1RDM,umat)) W = FRAG_energy + ENV_energy - np.trace(np.dot(self.P_ref, umat)) print("W = ", W) ''' deltaN = 0.001 mf_frag.mo_occ[Ne_frag//2] = deltaN mu_A = (mf_frag.energy_tot() - FRAG_energy)/deltaN mf_env.mo_occ[Ne_env//2] = deltaN mu_B = (mf_env.energy_tot() - ENV_energy)/deltaN print ('mu_A = ',mu_A) print ('mu_B = ',mu_B) mf_frag.mo_occ[Ne_frag//2-1] = mf_frag.mo_occ[Ne_frag//2-1] - deltaN mu_A = (-mf_frag.energy_tot() + FRAG_energy)/deltaN mf_env.mo_occ[Ne_env//2-1] = mf_env.mo_occ[Ne_env//2-1] - deltaN mu_B = (-mf_env.energy_tot() + ENV_energy)/deltaN print ('mu_A = ',mu_A) print ('mu_B = ',mu_B) ''' if (self.P_imp is not None): print("P_imp change (scf - non-scf): ", tools.mat_diff_norm(FRAG_1RDM, self.P_imp)) print("P_bath change (scf - non-scf): ", tools.mat_diff_norm(ENV_1RDM, self.P_bath)) diffP = FRAG_1RDM + ENV_1RDM - self.P_ref diffP_norm = np.linalg.norm(diffP) diffP_max = np.amax(np.absolute(diffP)) print("|P_frag + P_env - P_ref| = ", diffP_norm) print("max element of (P_frag + P_env - P_ref) = ", diffP_max) self.frag_mo = mf_frag.mo_coeff self.env_mo = mf_env.mo_coeff print('mo orthogonality:') if self.use_suborb: ortho = np.dot(mf_frag.mo_coeff[:, :Ne_frag // 2].T, mf_env.mo_coeff[:, :Ne_env // 2]) print(ortho) else: s = self.mol_full.intor_symmetric('int1e_ovlp') ortho = reduce(np.dot, (mf_frag.mo_coeff[:, mf_frag.mo_occ > 1e-8].T, s, mf_env.mo_coeff[:, mf_env.mo_occ > 1e-8])) print(ortho) return (FRAG_1RDM, ENV_1RDM)
def oep_loop(self, umat0, do_leastsq=False): ''' oep with split loops ''' t0 = tools.time0() params = self.params gtol0 = copy.copy(params.options["gtol"]) gtol_min = 1e6 dim = self.dim threshold = params.diffP_tol maxit = params.outer_maxit it = 0 umat = copy.copy(umat0) while it < maxit: it += 1 print(" OEP iteration ", it) P_imp_old = copy.copy(self.P_imp) P_bath_old = copy.copy(self.P_bath) diffP = (self.P_imp + self.P_bath - self.P_ref) gtol = np.amax(np.absolute(diffP)) gtol_min = min(gtol, gtol_min) self.params.options["gtol"] = max(gtol_min / 5.0, gtol0) #gradually reduce gtol ''' if self.use_suborb and it ==1: gtol_min = 0.25 #hack self.params.options["gtol"] = max(gtol_min/5.0, gtol0) ''' if do_leastsq: umat = self.oep_leastsq(umat, nonscf=True, dm0_frag=P_imp_old, dm0_env=P_bath_old) else: umat = self.oep_old(umat, nonscf=True, dm0_frag=P_imp_old, dm0_env=P_bath_old) if self.use_suborb: #sdmfet ao2sub = self.ao2sub[:, :dim] scf_args_frag = {'mol':self.mol_frag, 'Ne':self.Ne_frag, 'Norb':dim, 'method':self.mf_method,\ 'vext_1e':umat, 'oei':self.oei_frag, 'vhxc':self.vhxc_frag, 'tei':self.tei, 'dm0':P_imp_old, 'coredm':0.0, \ 'ao2sub':ao2sub, 'smear_sigma':self.smear_sigma, 'max_cycle':self.scf_max_cycle} mf_frag = qcwrap.qc_scf(True, nonscf=True, **scf_args_frag) mf_frag.kernel() self.P_imp = mf_frag.rdm1 scf_args_env = {'mol':self.mol_env, 'Ne':self.Ne_env, 'Norb':dim, 'method':self.mf_method,\ 'vext_1e':umat, 'oei':self.oei_env, 'vhxc':self.vhxc_env, 'tei':self.tei, 'dm0':P_bath_old, 'coredm':self.core1PDM_ao, \ 'ao2sub':ao2sub, 'smear_sigma':self.smear_sigma, 'max_cycle':self.scf_max_cycle} mf_env = qcwrap.qc_scf(True, nonscf=True, **scf_args_env) mf_env.kernel() self.P_bath = mf_env.rdm1 else: #dmfet scf_args_frag = {'mol':self.mol_frag, 'xc_func':self.mf_method, 'dm0':P_imp_old, \ 'vext_1e':umat, 'extra_oei':self.vnuc_bound_frag_ao, 'smear_sigma':self.smear_sigma,\ 'max_cycle':self.scf_max_cycle} mf_frag = qcwrap.qc_scf(False, nonscf=True, **scf_args_frag) mf_frag.kernel() self.P_imp = mf_frag.rdm1 scf_args_env = {'mol':self.mol_env, 'xc_func':self.mf_method, 'dm0':P_bath_old, \ 'vext_1e':umat, 'extra_oei':self.vnuc_bound_env_ao, 'smear_sigma':self.smear_sigma,\ 'max_cycle':self.scf_max_cycle} mf_env = qcwrap.qc_scf(False, nonscf=True, **scf_args_env) mf_env.kernel() self.P_bath = mf_env.rdm1 gmax_imp = tools.mat_diff_max(self.P_imp, P_imp_old) gmax_bath = tools.mat_diff_max(self.P_bath, P_bath_old) print("diffP_max_imp, diffP_max_bath ") print(gmax_imp, gmax_bath) del (P_imp_old) del (P_bath_old) #convergence check if gmax_imp < threshold and gmax_bath < threshold: print("embedding potential optimization converged") break if it == maxit: print( "STOP: embedding potential optimization exceeds max No. of iterations" ) t1 = tools.timer("embedding potential optimization (split loops)", t0) self.params.options["gtol"] = gtol0 return umat
def ccsd_energy(self, dim): print("ECW method is CCSD") energy = 0.0 Ne_frag = self.Ne_frag ops = self.ops umat = self.umat Ne_env = self.Ne_env P_bath_JK = libgen.coreJK_sub( self.ints, self.loc2sub, dim, tools.dm_sub2ao(self.P_bath, self.loc2sub[:, :dim]), Ne_env, 1.0) subOEI = ops["subKin"] + ops["subVnuc1"] + ops[ "subVnuc2"] + P_bath_JK + ops["subCoreJK"] + 0.5 * 1e4 * self.P_bath #subOEI = ops["subKin"]+ops["subVnuc1"]+ops["subVnuc_bound1"]+umat + 0.5*1e4*self.P_bath subTEI = ops["subTEI"] mf = qcwrap.qc_scf(Ne_frag, dim, 'hf', mol=self.mol, oei=subOEI, tei=subTEI, dm0=self.P_imp) mf.runscf() e_emb = 0.0 #onedm = mf.make_rdm1() #e_emb=np.trace(np.dot(umat,onedm)) #print "diffP = ",np.linalg.norm(self.P_imp - onedm) print(mf.elec_energy) mycc = cc.CCSD(mf) mycc.max_cycle = 200 #mycc.conv_tol = 1e-6 #mycc.conv_tol_normt = 1e-4 mycc.kernel() et = 0.0 if (self.ecw_method == 'ccsd(t)'): print('CCSD(T) correction') et = mycc.ccsd_t() #ccsd_dm_mo = mycc.make_rdm1() #ccsd_dm_sub = tools.dm_loc2ao(ccsd_dm_mo,mf.mo_coeff) #e_emb=np.trace(np.dot(umat,ccsd_dm_sub)) e_hf = mf.elec_energy print(mycc.e_corr + et) e_ccsd = e_hf + mycc.e_corr + et e_ccsd -= e_emb print(e_ccsd) imp_mf_energy = self.imp_mf_energy(dim) energy = e_ccsd - imp_mf_energy print("dmfet correction energy = ", energy) return energy
def imp_mf_energy(self, dim): Ne_frag = self.Ne_frag ops = self.ops umat = self.umat Ne_env = self.Ne_env P_bath_loc = tools.dm_sub2ao(self.P_bath, self.loc2sub[:, :dim]) P_bath_JK = libgen.coreJK_sub(self.ints, self.loc2sub, dim, P_bath_loc, Ne_env, self.Kcoeff) proj = 0.5 * self.P_bath energy_shift = 1e5 ao2sub = self.ao2sub[:, :dim] coredm = self.core1PDM_ao + tools.dm_sub2ao(self.P_bath, ao2sub) Vemb = ops["subVnuc2"] + P_bath_JK + ops[ "subCoreJK"] + energy_shift * proj Vxc = None if (self.mf_method != 'hf'): P_imp_ao = tools.dm_sub2ao(self.P_imp, ao2sub) mf_frag = qcwrap.qc_scf(Ne_frag, dim, self.mf_method, mol=self.mol_frag, oei=None, tei=None, dm0=self.P_imp, coredm=0.0, ao2sub=ao2sub) vxc_imp_ao = qcwrap.pyscf_rks.get_vxc(mf_frag, self.mol_frag, P_imp_ao)[2] vxc_full_ao = qcwrap.pyscf_rks.get_vxc(self.mf_full, self.mol, coredm + P_imp_ao)[2] Vxc = tools.op_ao2sub(vxc_full_ao, ao2sub) - tools.op_ao2sub( vxc_imp_ao, ao2sub) Vemb += Vxc subOEI = ops["subKin"] + ops["subVnuc1"] + Vemb #subOEI = ops["subKin"]+ops["subVnuc1"]+ops["subVnuc2"]+P_bath_JK+ops["subCoreJK"]+ energy_shift*proj #subOEI = ops["subKin"]+ops["subVnuc1"]+ops["subVnuc_bound1"]+umat +0.5*1e4*self.P_bath subTEI = ops["subTEI"] mf = qcwrap.qc_scf(Ne_frag, dim, self.mf_method, mol=self.mol_frag, oei=subOEI, tei=subTEI, dm0=self.P_imp, coredm=0.0, ao2sub=ao2sub,\ smear_sigma = self.smear_sigma) mf.runscf() energy = mf.elec_energy #self.ints.submo_molden(mf.mo_coeff, mf.mo_occ, self.loc2sub, "mo_frag.molden" ) print('|diffP| = ', np.linalg.norm(mf.rdm1 + self.P_bath - self.P_ref_sub)) print("embeded imp scf (electron) energy = ", energy) self.P_imp = mf.rdm1 print('level shift energy contribution: ', np.trace(np.dot(energy_shift * proj, self.P_imp))) return (energy, Vemb, Vxc)
def ecw_energy(self, method, dim): mf_energy, Vemb, Vxc = self.imp_mf_energy(dim) Ne_frag = self.Ne_frag ops = self.ops subOEI = ops["subKin"] + ops["subVnuc1"] + Vemb subTEI = ops["subTEI"] mf = qcwrap.qc_scf(Ne_frag, dim, 'hf', mol=self.mol_frag, oei=subOEI, tei=subTEI, dm0=self.P_imp) mf.runscf() e_hf = mf.elec_energy # - np.trace(np.dot(mf.rdm1,Vemb)) if (self.plot_mo): self.ints.submo_molden(mf.mo_coeff, mf.mo_occ, self.loc2sub, "mo_frag.molden", self.mol_frag) exc = 0.0 if (Vxc is not None): # exc = np.einsum('ij,ji', Vxc, mf.rdm1-self.P_imp) exc = np.einsum('ij,ji', Vxc, self.P_imp) print('exc = ', exc) if (method == 'hf'): energy = e_hf elif (method == 'mp2'): mp2 = mp.MP2(mf) mp2.kernel() energy = e_hf + mp2.e_corr elif (method == 'ccsd' or method == 'ccsd(t)'): mycc = cc.CCSD(mf) mycc.max_cycle = 200 #mycc.conv_tol = 1e-6 #mycc.conv_tol_normt = 1e-4 mycc.kernel() et = 0.0 if (method == 'ccsd(t)'): print('CCSD(T) correction') et = mycc.ccsd_t() energy = e_hf + mycc.e_corr + et elif (method == 'eomccsd'): mf.verbose = 5 mycc = cc.RCCSD(mf) mycc.kernel() es, vs = mycc.eomee_ccsd_singlet(nroots=self.ex_nroots) if (self.ex_nroots == 1): r1, r2 = mycc.vector_to_amplitudes(vs) print('debug: ', r1.shape) else: for vn in vs: r1, r2 = mycc.vector_to_amplitudes(vn) energy = e_hf + mycc.e_corr elif (method == 'eomsfccsd'): self.mol_frag.spin = 2 mf = qcwrap.pyscf_rks.rohf_pyscf(Ne_frag, dim, mol=self.mol_frag, oei=subOEI, tei=subTEI, dm0=np.array((.5 * self.P_imp, .5 * self.P_imp))) mf.kernel(dm0=mf.dm_guess) mf1 = qcwrap.pyscf_rks.uhf_pyscf(Ne_frag, dim, mol=self.mol_frag, oei=subOEI, tei=subTEI, dm0=None) mf1.convert_from_rhf(mf) mycc = cc.UCCSD(mf1) mycc.verbose = 5 mycc.kernel() es, vs = mycc.eomsf_ccsd(nroots=self.ex_nroots) if (self.ex_nroots == 1): r1, r2 = cc.eom_uccsd.vector_to_amplitudes_eomsf( vs, mycc.nmo, mycc.nocc) tools.print_eomcc_t1(r1[0]) tools.print_eomcc_t1(r1[1]) else: for vn in vs: r1, r2 = cc.eom_uccsd.vector_to_amplitudes_eomsf( vn, mycc.nmo, mycc.nocc) tools.print_eomcc_t1(r1[0]) tools.print_eomcc_t1(r1[1]) energy = mf1.e_tot + mycc.e_corr else: raise Exception("ecw_method not supported!") energy -= mf_energy energy -= exc return energy
def pad_umat(self, occ_mo_imp, occ_mo_bath, dim_small, dim_big, core1dm_loc): if (dim_small == dim_big): return self.umat ops = libgen.build_subops(self.impAtom, self.mol_frag,self.mol_env, \ self.boundary_atoms,self.boundary_atoms2, self.ints, self.loc2sub, core1dm_loc, dim_big,self.Kcoeff, self.Nelec_core) self.ops = ops P_imp_small = 2.0 * np.dot(occ_mo_imp, occ_mo_imp.T) P_bath_small = 2.0 * np.dot(occ_mo_bath, occ_mo_bath.T) dim_ext = dim_big - dim_small P_imp_big = np.pad(P_imp_small, ((0, dim_ext), (0, dim_ext)), 'constant', constant_values=0) P_bath_big = np.pad(P_bath_small, ((0, dim_ext), (0, dim_ext)), 'constant', constant_values=0) self.P_imp = P_imp_big self.P_bath = P_bath_big self.P_ref_sub = tools.dm_loc2sub(self.OneDM_loc - self.core1PDM_loc, self.loc2sub[:, :dim_big]) JK_imp = self.ints.impJK_sub(P_imp_big, ops["subTEI"], self.Kcoeff) JK_bath = self.ints.impJK_sub(P_bath_big, ops["subTEI"], self.Kcoeff) ao2sub = self.ao2sub[:, :dim_big] coredm = self.core1PDM_ao if (self.mf_method != 'hf'): mf1 = qcwrap.qc_scf(True, mol=self.mol_frag, Ne=self.Ne_frag, Norb=dim_big, method=self.mf_method, \ oei=None,tei=None,dm0=P_imp_big,coredm=0.0,ao2sub=ao2sub) vxc_imp_ao = qcwrap.pyscf_rks.get_vxc( mf1, self.mol_frag, tools.dm_sub2ao(P_imp_big, ao2sub))[2] JK_imp += tools.op_ao2sub(vxc_imp_ao, ao2sub) env_dm = coredm + tools.dm_sub2ao(P_bath_big, ao2sub) mf2 = qcwrap.qc_scf(True, mol=self.mol_env, Ne=self.Ne_env, Norb=dim_big, method=self.mf_method, \ oei=None,tei=None,dm0=P_bath_big,coredm=coredm, ao2sub=ao2sub) vxc_bath_ao = qcwrap.pyscf_rks.get_vxc( mf2, self.mol_env, env_dm, n_core_elec=self.Nelec_core)[2] JK_bath += tools.op_ao2sub(vxc_bath_ao, ao2sub) oei_imp = ops["subKin"] + ops["subVnuc1"] + ops[ "subVnuc_bound1"] + JK_imp ext_oei_imp = oei_imp[dim_small:, :dim_small] oei_bath = ops["subKin"] + ops["subVnuc2"] + ops[ "subVnuc_bound2"] + ops["subCoreJK"] + JK_bath ext_oei_bath = oei_bath[dim_small:, :dim_small] b_imp = -np.dot(ext_oei_imp, occ_mo_imp) b_bath = -np.dot(ext_oei_bath, occ_mo_bath) #solve uv = b for u v = np.concatenate((occ_mo_imp, occ_mo_bath), axis=1) b = np.concatenate((b_imp, b_bath), axis=1) AAT = np.dot(v.T, v) #tools.MatPrint(AAT,'AAT') #tmp = np.dot(np.linalg.inv(AAT), b.T) tmp = b.T uT = np.dot(v, tmp) u = uT.T #u = scipy.linalg.lstsq(v.T, b.T, cond=None, overwrite_a=False, overwrite_b=False, check_finite=True, lapack_driver=None)[0] #u = np.linalg.lstsq(v.T, b.T, rcond=1e-9)[0] #tools.MatPrint(u.T,"u") #zero = np.dot(u.T,v)-b #tools.MatPrint(zero,"zero") #tools.MatPrint(self.umat,"umat") umat = np.pad(self.umat, ((0, dim_ext), (0, dim_ext)), 'constant', constant_values=0) umat[dim_small:, :dim_small] = u umat[:dim_small, dim_small:] = u.T #umat1=umat.copy() #umat1[dim_small:, :dim_small] = -ext_oei_bath #umat1[:dim_small, dim_small:] = -ext_oei_bath.T #print "u-u1=",np.linalg.norm(umat-umat1) #debug subOEI = ops["subKin"] + ops["subVnuc1"] + ops["subVnuc_bound1"] #energy, onedm, mo = qcwrap.pyscf_rhf.scf( subOEI, ops["subTEI"], dim_big, self.Ne_frag, P_imp_big, self.mf_method) mf1 = qcwrap.qc_scf(True, mol=self.mol_frag, Ne=self.Ne_frag, Norb=dim_big, method=self.mf_method,\ vext_1e = umat, oei=subOEI,tei=ops["subTEI"],dm0=P_imp_big,coredm=0.0,ao2sub=ao2sub) mf1.runscf() subOEI = ops["subKin"] + ops["subVnuc2"] + ops["subVnuc_bound2"] + ops[ "subCoreJK"] #energy2, onedm2, mo2 = qcwrap.pyscf_rhf.scf( subOEI, ops["subTEI"], dim_big, self.Ne_env, P_bath_big, self.mf_method) mf2 = qcwrap.qc_scf(True, mol=self.mol_env, Ne=self.Ne_env, Norb=dim_big, method=self.mf_method,\ vext_1e = umat, oei=subOEI,tei=ops["subTEI"],dm0=P_bath_big,coredm=coredm,ao2sub=ao2sub) #mf2.conv_check = False #temp #subOEI = ops["subKin"]+ops["subVnuc2"]+ops["subVnuc_bound2"]+umat1 #s = self.mf_full.get_ovlp(self.mol) #coredm_sub = tools.dm_ao2sub(coredm,s,ao2sub) #mf2 = qcwrap.qc_scf(self.Ne_env+self.Nelec_core,dim_big,self.mf_method,mol=self.mol_env,oei=subOEI,tei=ops["subTEI"],dm0=P_bath_big+coredm_sub,coredm=0.0,ao2sub=ao2sub) mf2.runscf() diffP = mf1.rdm1 + mf2.rdm1 - self.P_ref_sub #diffP = mf1.rdm1 + mf2.rdm1 - tools.dm_loc2sub(self.OneDM_loc, self.loc2sub[:,:dim_big]) print(np.linalg.norm(P_imp_big - mf1.rdm1), np.linalg.norm(P_bath_big - mf2.rdm1)) print('|diffP| = ', np.linalg.norm(diffP), 'max(diffP) = ', np.amax(np.absolute(diffP))) #tools.MatPrint(diffP,"diffP") #tools.MatPrint(mf1.rdm1,"P1") #tools.MatPrint(mf2.rdm1,"P2") #tools.MatPrint(P_imp_small,"P_imp_small") #tools.MatPrint(P_bath_small,"P_bath_small") return umat