def para(gobj, mo10, mo_coeff, mo_occ, qed_fac=1): mol = gobj.mol effspin = mol.spin * .5 muB = .5 # Bohr magneton #qed_fac = (nist.G_ELECTRON - 1) orboa = mo_coeff[0][:,mo_occ[0]>0] orbob = mo_coeff[1][:,mo_occ[1]>0] dm0a = numpy.dot(orboa, orboa.T) dm0b = numpy.dot(orbob, orbob.T) dm10a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T)) for x in mo10[0]] dm10b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T)) for x in mo10[1]] dm10a = numpy.asarray([x-x.T for x in dm10a]) dm10b = numpy.asarray([x-x.T for x in dm10b]) hso1e = uhf_g.make_h01_soc1e(gobj, mo_coeff, mo_occ, qed_fac) gpara1e =-numpy.einsum('xji,yij->xy', dm10a, hso1e) gpara1e+= numpy.einsum('xji,yij->xy', dm10b, hso1e) gpara1e *= 1./effspin / muB _write(gobj, align(gpara1e)[0], 'SOC(1e)/OZ') if gobj.para_soc2e: gpara2e = gobj.make_para_soc2e((dm0a,dm0b), (dm10a,dm10b), qed_fac) _write(gobj, align(gpara2e)[0], 'SOC(2e)/OZ') else: gpara2e = 0 gpara = gpara1e + gpara2e return gpara
def make_para_soc2e(gobj, dm0, dm10, sso_qed_fac=1): if isinstance(gobj.para_soc2e, str): with_sso = 'SSO' in gobj.para_soc2e.upper() with_soo = 'SOO' in gobj.para_soc2e.upper() with_somf = 'SOMF' in gobj.para_soc2e.upper() with_amfi = 'AMFI' in gobj.para_soc2e.upper() assert(not (with_somf and (with_sso or with_soo))) elif gobj.para_soc2e: with_sso = with_soo = True with_somf = with_amfi = False else: with_sso = with_soo = with_somf = False with_amfi = True mol = gobj.mol alpha2 = nist.ALPHA ** 2 effspin = mol.spin * .5 muB = .5 # Bohr magneton #sso_qed_fac = (nist.G_ELECTRON - 1) mf = gobj._scf ni = mf._numint omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin) if abs(omega) > 1e-10: raise NotImplementedError mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory*.9-mem_now) v1 = get_vxc_soc(ni, mol, mf.grids, mf.xc, dm0, max_memory=max_memory, verbose=gobj.verbose) dm10a, dm10b = dm10 if with_somf: ej = numpy.einsum('yil,xli->xy', v1[0]+v1[1], dm10a-dm10b) else: ej = numpy.einsum('yil,xli->xy', v1[0], dm10a) ej -= numpy.einsum('yil,xli->xy', v1[1], dm10b) #ej *= -2 #Veff(-2X) approximation of JCP 122 034107 gpara2e = 0 if abs(hyb) > 1e-10: if with_amfi: vj, vk = uhf_g.get_jk_amfi(mol, dm0) else: vj, vk = uhf_g.get_jk(mol, dm0) if with_sso or with_soo: ek = numpy.einsum('yil,xli->xy', vk[0], dm10a) ek -= numpy.einsum('yil,xli->xy', vk[1], dm10b) if with_sso: ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b) gpara2e -= sso_qed_fac * (ej - hyb * ek) if with_soo: ej += numpy.einsum('yij,xji->xy', vj[0]-vj[1], dm10a+dm10b) gpara2e -= 2 * (ej - hyb * ek) else: # SOMF, see JCP 122, 034107 Eq (19) ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b) ek = numpy.einsum('yil,xli->xy', vk[0]+vk[1], dm10a-dm10b) gpara2e -= ej - 1.5 * hyb * ek else: if with_amfi: vj = uhf_g.get_j_amfi(mol, dm0) else: vj = uhf_g.get_j(mol, dm0) if with_sso or with_soo: if with_sso: ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b) gpara2e -= sso_qed_fac * ej if with_soo: ej += numpy.einsum('yij,xji->xy', vj[0]-vj[1], dm10a+dm10b) gpara2e -= 2 * ej else: # SOMF, see JCP 122, 034107 Eq (19) ej += numpy.einsum('yij,xji->xy', vj[0]+vj[1], dm10a-dm10b) gpara2e -= ej gpara2e *= (alpha2/4) / effspin / muB if gobj.verbose >= logger.INFO: _write(gobj, align(gpara2e)[0], 'SOC(2e)/OZ') return gpara2e