def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, d1=None, d2=None, verbose=logger.INFO): if eris is not None: if abs(eris.fock - numpy.diag(eris.fock.diagonal())).max() > 1e-3: raise RuntimeError( 'CCSD gradients does not support NHF (non-canonical HF)') if t1 is None: t1 = mycc.t1 if t2 is None: t2 = mycc.t2 if l1 is None: l1 = mycc.l1 if l2 is None: l2 = mycc.l2 if mf_grad is None: mf_grad = mycc._scf.nuc_grad_method() log = logger.new_logger(mycc, verbose) time0 = time.clock(), time.time() log.debug('Build ccsd rdm1 intermediates') if d1 is None: d1 = ccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer_debug1('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') fdm2 = lib.H5TmpFile() if d2 is None: d2 = ccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True) time1 = log.timer_debug1('rdm2 intermediates', *time1) mol = mycc.mol mo_coeff = mycc.mo_coeff mo_energy = mycc._scf.mo_energy nao, nmo = mo_coeff.shape nocc = numpy.count_nonzero(mycc.mo_occ > 0) with_frozen = not (mycc.frozen is None or mycc.frozen is 0) OA, VA, OF, VF = _index_frozen_active(mycc.get_frozen_mask(), mycc.mo_occ) log.debug('symmetrized rdm2 and MO->AO transformation') # Roughly, dm2*2 is computed in _rdm2_mo2ao mo_active = mo_coeff[:, numpy.hstack((OA, VA))] _rdm2_mo2ao(mycc, d2, mo_active, fdm2) # transform the active orbitals time1 = log.timer_debug1('MO->AO transformation', *time1) hf_dm1 = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() diagidx = numpy.arange(nao) diagidx = diagidx * (diagidx + 1) // 2 + diagidx de = numpy.zeros((len(atmlst), 3)) Imat = numpy.zeros((nao, nao)) vhf1 = fdm2.create_dataset('vhf1', (len(atmlst), 3, nao, nao), 'f8') # 2e AO integrals dot 2pdm max_memory = max(0, mycc.max_memory - lib.current_memory()[0]) blksize = max(1, int(max_memory * .9e6 / 8 / (nao**3 * 2.5))) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] ip1 = p0 vhf = numpy.zeros((3, nao, nao)) for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize): ip0, ip1 = ip1, ip1 + nf dm2buf = _load_block_tril(fdm2['dm2'], ip0, ip1, nao) dm2buf[:, :, diagidx] *= .5 shls_slice = (b0, b1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas) eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice) Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf, nao, -1), dm2buf) eri0 = None eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=shls_slice).reshape(3, nf, nao, -1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 dm2buf = None # HF part for i in range(3): eri1tmp = lib.unpack_tril(eri1[i].reshape(nf * nao, -1)) eri1tmp = eri1tmp.reshape(nf, nao, nao, nao) vhf[i] += numpy.einsum('ijkl,ij->kl', eri1tmp, hf_dm1[ip0:ip1]) vhf[i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1[ip0:ip1]) * .5 vhf[i, ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1) vhf[i, ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1) * .5 eri1 = eri1tmp = None vhf1[k] = vhf log.debug('2e-part grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer_debug1('2e-part grad of atom %d' % ia, *time1) Imat = reduce(numpy.dot, (mo_coeff.T, Imat, mycc._scf.get_ovlp(), mo_coeff)) * -1 dm1mo = numpy.zeros((nmo, nmo)) if with_frozen: dco = Imat[OF[:, None], OA] / (mo_energy[OF, None] - mo_energy[OA]) dfv = Imat[VF[:, None], VA] / (mo_energy[VF, None] - mo_energy[VA]) dm1mo[OA[:, None], OA] = doo + doo.T dm1mo[OF[:, None], OA] = dco dm1mo[OA[:, None], OF] = dco.T dm1mo[VA[:, None], VA] = dvv + dvv.T dm1mo[VF[:, None], VA] = dfv dm1mo[VA[:, None], VF] = dfv.T else: dm1mo[:nocc, :nocc] = doo + doo.T dm1mo[nocc:, nocc:] = dvv + dvv.T dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) vhf = mycc._scf.get_veff(mycc.mol, dm1) * 2 Xvo = reduce(numpy.dot, (mo_coeff[:, nocc:].T, vhf, mo_coeff[:, :nocc])) Xvo += Imat[:nocc, nocc:].T - Imat[nocc:, :nocc] dm1mo += _response_dm1(mycc, Xvo, eris) time1 = log.timer_debug1('response_rdm1 intermediates', *time1) Imat[nocc:, :nocc] = Imat[:nocc, nocc:].T im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T)) time1 = log.timer_debug1('response_rdm1', *time1) log.debug('h1 and JK1') hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[:nocc].reshape(-1, 1) zeta = reduce(numpy.dot, (mo_coeff, zeta * dm1mo, mo_coeff.T)) dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf_s1occ = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1 + dm1.T), p1)) time1 = log.timer_debug1('h1 and JK1', *time1) # Hartree-Fock part contribution dm1p = hf_dm1 + dm1 * 2 dm1 += hf_dm1 zeta += mf_grad.make_rdm1e(mo_energy, mo_coeff, mycc.mo_occ) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] += numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1]) de[k] += numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1]) # h[1] \dot DM, contribute to f1 h1ao = hcore_deriv(ia) de[k] += numpy.einsum('xij,ji->x', h1ao, dm1) # -s[1]*e \dot DM, contribute to f1 de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) de[k] -= numpy.einsum('xji,ij->x', s1[:, p0:p1], zeta[:, p0:p1]) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf_s1occ[p0:p1]) * 2 de[k] -= numpy.einsum('xij,ij->x', vhf1[k], dm1p) de += mf_grad.grad_nuc(mol, atmlst) log.timer('%s gradients' % mycc.__class__.__name__, *time0) return de
def kernel(mp, t2, atmlst=None, mf_grad=None, verbose=logger.INFO): if mf_grad is None: mf_grad = mp._scf.nuc_grad_method() log = logger.new_logger(mp, verbose) time0 = time.clock(), time.time() log.debug('Build ump2 rdm1 intermediates') d1 = ump2._gamma1_intermediates(mp, t2) time1 = log.timer_debug1('rdm1 intermediates', *time0) log.debug('Build ump2 rdm2 intermediates') mol = mp.mol with_frozen = not (mp.frozen is None or mp.frozen is 0) moidx = mp.get_frozen_mask() OA_a, VA_a, OF_a, VF_a = mp2_grad._index_frozen_active(moidx[0], mp.mo_occ[0]) OA_b, VA_b, OF_b, VF_b = mp2_grad._index_frozen_active(moidx[1], mp.mo_occ[1]) orboa = mp.mo_coeff[0][:,OA_a] orbva = mp.mo_coeff[0][:,VA_a] orbob = mp.mo_coeff[1][:,OA_b] orbvb = mp.mo_coeff[1][:,VA_b] nao, nocca = orboa.shape nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] # Partially transform MP2 density matrix and hold it in memory # The rest transformation are applied during the contraction to ERI integrals t2aa, t2ab, t2bb = t2 part_dm2aa = _ao2mo.nr_e2(t2aa.reshape(nocca**2,nvira**2), numpy.asarray(orbva.T, order='F'), (0,nao,0,nao), 's1', 's1').reshape(nocca,nocca,nao,nao) part_dm2bb = _ao2mo.nr_e2(t2bb.reshape(noccb**2,nvirb**2), numpy.asarray(orbvb.T, order='F'), (0,nao,0,nao), 's1', 's1').reshape(noccb,noccb,nao,nao) part_dm2ab = lib.einsum('ijab,pa,qb->ipqj', t2ab, orbva, orbvb) part_dm2aa = (part_dm2aa.transpose(0,2,3,1) - part_dm2aa.transpose(0,3,2,1)) * .5 part_dm2bb = (part_dm2bb.transpose(0,2,3,1) - part_dm2bb.transpose(0,3,2,1)) * .5 hf_dm1a, hf_dm1b = mp._scf.make_rdm1(mp.mo_coeff, mp.mo_occ) hf_dm1 = hf_dm1a + hf_dm1b if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() diagidx = numpy.arange(nao) diagidx = diagidx*(diagidx+1)//2 + diagidx de = numpy.zeros((len(atmlst),3)) Imata = numpy.zeros((nao,nao)) Imatb = numpy.zeros((nao,nao)) fdm2 = lib.H5TmpFile() vhf1 = fdm2.create_dataset('vhf1', (len(atmlst),2,3,nao,nao), 'f8') # 2e AO integrals dot 2pdm max_memory = max(0, mp.max_memory - lib.current_memory()[0]) blksize = max(1, int(max_memory*.9e6/8/(nao**3*2.5))) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] ip1 = p0 vhf = numpy.zeros((2,3,nao,nao)) for b0, b1, nf in mp2_grad._shell_prange(mol, shl0, shl1, blksize): ip0, ip1 = ip1, ip1 + nf dm2bufa = lib.einsum('pi,iqrj->pqrj', orboa[ip0:ip1], part_dm2aa) dm2bufa+= lib.einsum('qi,iprj->pqrj', orboa, part_dm2aa[:,ip0:ip1]) dm2bufa = lib.einsum('pqrj,sj->pqrs', dm2bufa, orboa) tmp = lib.einsum('pi,iqrj->pqrj', orboa[ip0:ip1], part_dm2ab) tmp+= lib.einsum('qi,iprj->pqrj', orboa, part_dm2ab[:,ip0:ip1]) dm2bufa+= lib.einsum('pqrj,sj->pqrs', tmp, orbob) tmp = None dm2bufa = dm2bufa + dm2bufa.transpose(0,1,3,2) dm2bufa = lib.pack_tril(dm2bufa.reshape(-1,nao,nao)).reshape(nf,nao,-1) dm2bufa[:,:,diagidx] *= .5 dm2bufb = lib.einsum('pi,iqrj->pqrj', orbob[ip0:ip1], part_dm2bb) dm2bufb+= lib.einsum('qi,iprj->pqrj', orbob, part_dm2bb[:,ip0:ip1]) dm2bufb = lib.einsum('pqrj,sj->pqrs', dm2bufb, orbob) tmp = lib.einsum('iqrj,sj->iqrs', part_dm2ab, orbob[ip0:ip1]) tmp+= lib.einsum('iqrj,sj->iqsr', part_dm2ab[:,:,ip0:ip1], orbob) dm2bufb+= lib.einsum('pi,iqrs->srpq', orboa, tmp) tmp = None dm2bufb = dm2bufb + dm2bufb.transpose(0,1,3,2) dm2bufb = lib.pack_tril(dm2bufb.reshape(-1,nao,nao)).reshape(nf,nao,-1) dm2bufb[:,:,diagidx] *= .5 shls_slice = (b0,b1,0,mol.nbas,0,mol.nbas,0,mol.nbas) eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice) Imata += lib.einsum('ipx,iqx->pq', eri0.reshape(nf,nao,-1), dm2bufa) Imatb += lib.einsum('ipx,iqx->pq', eri0.reshape(nf,nao,-1), dm2bufb) eri0 = None eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=shls_slice).reshape(3,nf,nao,-1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2bufa) * 2 de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2bufb) * 2 dm2bufa = dm2bufb = None # HF part for i in range(3): eri1tmp = lib.unpack_tril(eri1[i].reshape(nf*nao,-1)) eri1tmp = eri1tmp.reshape(nf,nao,nao,nao) vhf[:,i] += numpy.einsum('ijkl,ij->kl', eri1tmp, hf_dm1[ip0:ip1]) vhf[0,i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1a[ip0:ip1]) vhf[1,i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1b[ip0:ip1]) vhf[:,i,ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1) vhf[0,i,ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1a) vhf[1,i,ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1b) eri1 = eri1tmp = None vhf1[k] = vhf log.debug('2e-part grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer_debug1('2e-part grad of atom %d'%ia, *time1) # Recompute nocc, nvir to include the frozen orbitals and make contraction for # the 1-particle quantities, see also the kernel function in uccsd_grad module. mo_a, mo_b = mp.mo_coeff mo_ea, mo_eb = mp._scf.mo_energy nao, nmoa = mo_a.shape nmob = mo_b.shape[1] nocca = numpy.count_nonzero(mp.mo_occ[0] > 0) noccb = numpy.count_nonzero(mp.mo_occ[1] > 0) s0 = mp._scf.get_ovlp() Imata = reduce(numpy.dot, (mo_a.T, Imata, s0, mo_a)) * -1 Imatb = reduce(numpy.dot, (mo_b.T, Imatb, s0, mo_b)) * -1 dm1a = numpy.zeros((nmoa,nmoa)) dm1b = numpy.zeros((nmob,nmob)) doo, dOO = d1[0] dvv, dVV = d1[1] if with_frozen: dco = Imata[OF_a[:,None],OA_a] / (mo_ea[OF_a,None] - mo_ea[OA_a]) dfv = Imata[VF_a[:,None],VA_a] / (mo_ea[VF_a,None] - mo_ea[VA_a]) dm1a[OA_a[:,None],OA_a] = (doo + doo.T) * .5 dm1a[OF_a[:,None],OA_a] = dco dm1a[OA_a[:,None],OF_a] = dco.T dm1a[VA_a[:,None],VA_a] = (dvv + dvv.T) * .5 dm1a[VF_a[:,None],VA_a] = dfv dm1a[VA_a[:,None],VF_a] = dfv.T dco = Imatb[OF_b[:,None],OA_b] / (mo_eb[OF_b,None] - mo_eb[OA_b]) dfv = Imatb[VF_b[:,None],VA_b] / (mo_eb[VF_b,None] - mo_eb[VA_b]) dm1b[OA_b[:,None],OA_b] = (dOO + dOO.T) * .5 dm1b[OF_b[:,None],OA_b] = dco dm1b[OA_b[:,None],OF_b] = dco.T dm1b[VA_b[:,None],VA_b] = (dVV + dVV.T) * .5 dm1b[VF_b[:,None],VA_b] = dfv dm1b[VA_b[:,None],VF_b] = dfv.T else: dm1a[:nocca,:nocca] = (doo + doo.T) * .5 dm1a[nocca:,nocca:] = (dvv + dvv.T) * .5 dm1b[:noccb,:noccb] = (dOO + dOO.T) * .5 dm1b[noccb:,noccb:] = (dVV + dVV.T) * .5 dm1 = (reduce(numpy.dot, (mo_a, dm1a, mo_a.T)), reduce(numpy.dot, (mo_b, dm1b, mo_b.T))) vhf = mp._scf.get_veff(mp.mol, dm1) Xvo = reduce(numpy.dot, (mo_a[:,nocca:].T, vhf[0], mo_a[:,:nocca])) XVO = reduce(numpy.dot, (mo_b[:,noccb:].T, vhf[1], mo_b[:,:noccb])) Xvo+= Imata[:nocca,nocca:].T - Imata[nocca:,:nocca] XVO+= Imatb[:noccb,noccb:].T - Imatb[noccb:,:noccb] dm1_resp = _response_dm1(mp, (Xvo,XVO)) dm1a += dm1_resp[0] dm1b += dm1_resp[1] time1 = log.timer_debug1('response_rdm1 intermediates', *time1) Imata[nocca:,:nocca] = Imata[:nocca,nocca:].T Imatb[noccb:,:noccb] = Imatb[:noccb,noccb:].T im1 = reduce(numpy.dot, (mo_a, Imata, mo_a.T)) im1+= reduce(numpy.dot, (mo_b, Imatb, mo_b.T)) time1 = log.timer_debug1('response_rdm1', *time1) log.debug('h1 and JK1') hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) zeta = (mo_ea[:,None] + mo_ea) * .5 zeta[nocca:,:nocca] = mo_ea[:nocca] zeta[:nocca,nocca:] = mo_ea[:nocca].reshape(-1,1) zeta_a = reduce(numpy.dot, (mo_a, zeta*dm1a, mo_a.T)) zeta = (mo_eb[:,None] + mo_eb) * .5 zeta[noccb:,:noccb] = mo_eb[:noccb] zeta[:noccb,noccb:] = mo_eb[:noccb].reshape(-1,1) zeta_b = reduce(numpy.dot, (mo_b, zeta*dm1b, mo_b.T)) dm1 = (reduce(numpy.dot, (mo_a, dm1a, mo_a.T)), reduce(numpy.dot, (mo_b, dm1b, mo_b.T))) vhf_s1occ = mp._scf.get_veff(mol, (dm1[0]+dm1[0].T, dm1[1]+dm1[1].T)) p1a = numpy.dot(mo_a[:,:nocca], mo_a[:,:nocca].T) p1b = numpy.dot(mo_b[:,:noccb], mo_b[:,:noccb].T) vhf_s1occ = (reduce(numpy.dot, (p1a, vhf_s1occ[0], p1a)) + reduce(numpy.dot, (p1b, vhf_s1occ[1], p1b))) * .5 time1 = log.timer_debug1('h1 and JK1', *time1) # Hartree-Fock part contribution dm1pa = hf_dm1a + dm1[0]*2 dm1pb = hf_dm1b + dm1[1]*2 dm1 = dm1[0] + dm1[1] + hf_dm1 zeta_a += rhf_grad.make_rdm1e(mo_ea, mo_a, mp.mo_occ[0]) zeta_b += rhf_grad.make_rdm1e(mo_eb, mo_b, mp.mo_occ[1]) zeta = zeta_a + zeta_b for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] += numpy.einsum('xij,ij->x', s1[:,p0:p1], im1[p0:p1]) de[k] += numpy.einsum('xji,ij->x', s1[:,p0:p1], im1[:,p0:p1]) # h[1] \dot DM, contribute to f1 h1ao = hcore_deriv(ia) de[k] += numpy.einsum('xij,ji->x', h1ao, dm1) # -s[1]*e \dot DM, contribute to f1 de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], zeta[p0:p1] ) de[k] -= numpy.einsum('xji,ij->x', s1[:,p0:p1], zeta[:,p0:p1]) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], vhf_s1occ[p0:p1]) * 2 de[k] -= numpy.einsum('xij,ij->x', vhf1[k,0], dm1pa) de[k] -= numpy.einsum('xij,ij->x', vhf1[k,1], dm1pb) de += mf_grad.grad_nuc(mol) log.timer('%s gradients' % mp.__class__.__name__, *time0) return de
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, d1=None, d2=None, verbose=logger.INFO): if eris is not None: if abs(eris.fock - numpy.diag(eris.fock.diagonal())).max() > 1e-3: raise RuntimeError('CCSD gradients does not support NHF (non-canonical HF)') if t1 is None: t1 = mycc.t1 if t2 is None: t2 = mycc.t2 if l1 is None: l1 = mycc.l1 if l2 is None: l2 = mycc.l2 if mf_grad is None: mf_grad = mycc._scf.nuc_grad_method() log = logger.new_logger(mycc, verbose) time0 = time.clock(), time.time() log.debug('Build ccsd rdm1 intermediates') if d1 is None: d1 = ccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer_debug1('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') fdm2 = lib.H5TmpFile() if d2 is None: d2 = ccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True) time1 = log.timer_debug1('rdm2 intermediates', *time1) mol = mycc.mol mo_coeff = mycc.mo_coeff mo_energy = mycc._scf.mo_energy nao, nmo = mo_coeff.shape nocc = numpy.count_nonzero(mycc.mo_occ > 0) with_frozen = not (mycc.frozen is None or mycc.frozen is 0) OA, VA, OF, VF = _index_frozen_active(mycc.get_frozen_mask(), mycc.mo_occ) log.debug('symmetrized rdm2 and MO->AO transformation') # Roughly, dm2*2 is computed in _rdm2_mo2ao mo_active = mo_coeff[:,numpy.hstack((OA,VA))] _rdm2_mo2ao(mycc, d2, mo_active, fdm2) # transform the active orbitals time1 = log.timer_debug1('MO->AO transformation', *time1) hf_dm1 = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() diagidx = numpy.arange(nao) diagidx = diagidx*(diagidx+1)//2 + diagidx de = numpy.zeros((len(atmlst),3)) Imat = numpy.zeros((nao,nao)) vhf1 = fdm2.create_dataset('vhf1', (len(atmlst),3,nao,nao), 'f8') # 2e AO integrals dot 2pdm max_memory = max(0, mycc.max_memory - lib.current_memory()[0]) blksize = max(1, int(max_memory*.9e6/8/(nao**3*2.5))) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] ip1 = p0 vhf = numpy.zeros((3,nao,nao)) for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize): ip0, ip1 = ip1, ip1 + nf dm2buf = _load_block_tril(fdm2['dm2'], ip0, ip1, nao) dm2buf[:,:,diagidx] *= .5 shls_slice = (b0,b1,0,mol.nbas,0,mol.nbas,0,mol.nbas) eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice) Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf,nao,-1), dm2buf) eri0 = None eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=shls_slice).reshape(3,nf,nao,-1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 dm2buf = None # HF part for i in range(3): eri1tmp = lib.unpack_tril(eri1[i].reshape(nf*nao,-1)) eri1tmp = eri1tmp.reshape(nf,nao,nao,nao) vhf[i] += numpy.einsum('ijkl,ij->kl', eri1tmp, hf_dm1[ip0:ip1]) vhf[i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1[ip0:ip1]) * .5 vhf[i,ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1) vhf[i,ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1) * .5 eri1 = eri1tmp = None vhf1[k] = vhf log.debug('2e-part grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer_debug1('2e-part grad of atom %d'%ia, *time1) Imat = reduce(numpy.dot, (mo_coeff.T, Imat, mycc._scf.get_ovlp(), mo_coeff)) * -1 dm1mo = numpy.zeros((nmo,nmo)) if with_frozen: dco = Imat[OF[:,None],OA] / (mo_energy[OF,None] - mo_energy[OA]) dfv = Imat[VF[:,None],VA] / (mo_energy[VF,None] - mo_energy[VA]) dm1mo[OA[:,None],OA] = doo + doo.T dm1mo[OF[:,None],OA] = dco dm1mo[OA[:,None],OF] = dco.T dm1mo[VA[:,None],VA] = dvv + dvv.T dm1mo[VF[:,None],VA] = dfv dm1mo[VA[:,None],VF] = dfv.T else: dm1mo[:nocc,:nocc] = doo + doo.T dm1mo[nocc:,nocc:] = dvv + dvv.T dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) vhf = mycc._scf.get_veff(mycc.mol, dm1) * 2 Xvo = reduce(numpy.dot, (mo_coeff[:,nocc:].T, vhf, mo_coeff[:,:nocc])) Xvo+= Imat[:nocc,nocc:].T - Imat[nocc:,:nocc] dm1mo += _response_dm1(mycc, Xvo, eris) time1 = log.timer_debug1('response_rdm1 intermediates', *time1) Imat[nocc:,:nocc] = Imat[:nocc,nocc:].T im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T)) time1 = log.timer_debug1('response_rdm1', *time1) log.debug('h1 and JK1') hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:,:nocc] = mo_energy[:nocc] zeta[:nocc,nocc:] = mo_energy[:nocc].reshape(-1,1) zeta = reduce(numpy.dot, (mo_coeff, zeta*dm1mo, mo_coeff.T)) dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) p1 = numpy.dot(mo_coeff[:,:nocc], mo_coeff[:,:nocc].T) vhf_s1occ = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1+dm1.T), p1)) time1 = log.timer_debug1('h1 and JK1', *time1) # Hartree-Fock part contribution dm1p = hf_dm1 + dm1*2 dm1 += hf_dm1 zeta += mf_grad.make_rdm1e(mo_energy, mo_coeff, mycc.mo_occ) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] += numpy.einsum('xij,ij->x', s1[:,p0:p1], im1[p0:p1]) de[k] += numpy.einsum('xji,ij->x', s1[:,p0:p1], im1[:,p0:p1]) # h[1] \dot DM, contribute to f1 h1ao = hcore_deriv(ia) de[k] += numpy.einsum('xij,ji->x', h1ao, dm1) # -s[1]*e \dot DM, contribute to f1 de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], zeta[p0:p1] ) de[k] -= numpy.einsum('xji,ij->x', s1[:,p0:p1], zeta[:,p0:p1]) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], vhf_s1occ[p0:p1]) * 2 de[k] -= numpy.einsum('xij,ij->x', vhf1[k], dm1p) de += mf_grad.grad_nuc(mol, atmlst) log.timer('%s gradients' % mycc.__class__.__name__, *time0) return de
def make_rdm1_with_orbital_response(mp): import time from pyscf import lib from pyscf.grad.mp2 import _response_dm1, _index_frozen_active, _shell_prange from pyscf.mp import mp2 from pyscf.ao2mo import _ao2mo log = lib.logger.new_logger(mp) time0 = time.clock(), time.time() mol = mp.mol log.debug('Build mp2 rdm1 intermediates') d1 = mp2._gamma1_intermediates(mp, mp.t2) doo, dvv = d1 time1 = log.timer_debug1('rdm1 intermediates', *time0) with_frozen = not (mp.frozen is None or mp.frozen is 0) OA, VA, OF, VF = _index_frozen_active(mp.get_frozen_mask(), mp.mo_occ) orbo = mp.mo_coeff[:, OA] orbv = mp.mo_coeff[:, VA] nao, nocc = orbo.shape nvir = orbv.shape[1] # Partially transform MP2 density matrix and hold it in memory # The rest transformation are applied during the contraction to ERI integrals part_dm2 = _ao2mo.nr_e2(mp.t2.reshape(nocc**2, nvir**2), numpy.asarray(orbv.T, order='F'), (0, nao, 0, nao), 's1', 's1').reshape(nocc, nocc, nao, nao) part_dm2 = (part_dm2.transpose(0, 2, 3, 1) * 4 - part_dm2.transpose(0, 3, 2, 1) * 2) offsetdic = mol.offset_nr_by_atom() diagidx = numpy.arange(nao) diagidx = diagidx * (diagidx + 1) // 2 + diagidx Imat = numpy.zeros((nao, nao)) # 2e AO integrals dot 2pdm max_memory = max(0, mp.max_memory - lib.current_memory()[0]) blksize = max(1, int(max_memory * .9e6 / 8 / (nao**3 * 2.5))) for ia in range(mol.natm): shl0, shl1, p0, p1 = offsetdic[ia] ip1 = p0 for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize): ip0, ip1 = ip1, ip1 + nf dm2buf = lib.einsum('pi,iqrj->pqrj', orbo[ip0:ip1], part_dm2) dm2buf += lib.einsum('qi,iprj->pqrj', orbo, part_dm2[:, ip0:ip1]) dm2buf = lib.einsum('pqrj,sj->pqrs', dm2buf, orbo) dm2buf = dm2buf + dm2buf.transpose(0, 1, 3, 2) dm2buf = lib.pack_tril(dm2buf.reshape(-1, nao, nao)).reshape(nf, nao, -1) dm2buf[:, :, diagidx] *= .5 shls_slice = (b0, b1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas) eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice) Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf, nao, -1), dm2buf) eri0 = None dm2buf = None time1 = log.timer_debug1('2e-part grad of atom %d' % ia, *time1) # Recompute nocc, nvir to include the frozen orbitals and make contraction for # the 1-particle quantities, see also the kernel function in ccsd_grad module. mo_coeff = mp.mo_coeff mo_energy = mp._scf.mo_energy nao, nmo = mo_coeff.shape nocc = numpy.count_nonzero(mp.mo_occ > 0) Imat = reduce(numpy.dot, (mo_coeff.T, Imat, mp._scf.get_ovlp(), mo_coeff)) * -1 dm1mo = numpy.zeros((nmo, nmo)) if with_frozen: dco = Imat[OF[:, None], OA] / (mo_energy[OF, None] - mo_energy[OA]) dfv = Imat[VF[:, None], VA] / (mo_energy[VF, None] - mo_energy[VA]) dm1mo[OA[:, None], OA] = doo + doo.T dm1mo[OF[:, None], OA] = dco dm1mo[OA[:, None], OF] = dco.T dm1mo[VA[:, None], VA] = dvv + dvv.T dm1mo[VF[:, None], VA] = dfv dm1mo[VA[:, None], VF] = dfv.T else: dm1mo[:nocc, :nocc] = doo + doo.T dm1mo[nocc:, nocc:] = dvv + dvv.T dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) vhf = mp._scf.get_veff(mp.mol, dm1) * 2 Xvo = reduce(numpy.dot, (mo_coeff[:, nocc:].T, vhf, mo_coeff[:, :nocc])) Xvo += Imat[:nocc, nocc:].T - Imat[nocc:, :nocc] dm1mo += _response_dm1(mp, Xvo) # Transform to AO basis dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) dm1 += mp._scf.make_rdm1(mp.mo_coeff, mp.mo_occ) return dm1