def __init__(self, cc, mo_coeff=None, method='incore', ao2mofn=ao2mo.outcore.general_iofree): cput0 = (time.clock(), time.time()) moidx = ccsd.get_moidx(cc) if mo_coeff is None: self.mo_coeff = mo_coeff = cc.mo_coeff[:, moidx] else: # If mo_coeff is not canonical orbital self.mo_coeff = mo_coeff = mo_coeff[:, moidx] dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ) fockao = cc._scf.get_hcore() + cc._scf.get_veff(cc.mol, dm) self.fock = reduce(numpy.dot, (mo_coeff.T, fockao, mo_coeff)) nocc = cc.nocc nmo = cc.nmo nvir = nmo - nocc mem_incore, mem_outcore, mem_basic = _mem_usage(nocc, nvir) mem_now = lib.current_memory()[0] log = logger.Logger(cc.stdout, cc.verbose) if (method == 'incore' and (mem_incore + mem_now < cc.max_memory) or cc.mol.incore_anyway): eri = ao2mofn(cc._scf.mol, (mo_coeff, mo_coeff, mo_coeff, mo_coeff), compact=0) if mo_coeff.dtype == np.float: eri = eri.real eri = eri.reshape((nmo, ) * 4) # <ij|kl> = (ik|jl) eri = eri.transpose(0, 2, 1, 3) self.dtype = eri.dtype self.oooo = eri[:nocc, :nocc, :nocc, :nocc].copy() self.ooov = eri[:nocc, :nocc, :nocc, nocc:].copy() self.oovv = eri[:nocc, :nocc, nocc:, nocc:].copy() self.ovov = eri[:nocc, nocc:, :nocc, nocc:].copy() self.voov = eri[nocc:, :nocc, :nocc, nocc:].copy() self.vovv = eri[nocc:, :nocc, nocc:, nocc:].copy() self.vvvv = eri[nocc:, nocc:, nocc:, nocc:].copy() else: _tmpfile1 = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR) self.feri1 = h5py.File(_tmpfile1.name) orbo = mo_coeff[:, :nocc] orbv = mo_coeff[:, nocc:] if mo_coeff.dtype == np.complex: ds_type = 'c16' else: ds_type = 'f8' self.oooo = self.feri1.create_dataset('oooo', (nocc, nocc, nocc, nocc), ds_type) self.ooov = self.feri1.create_dataset('ooov', (nocc, nocc, nocc, nvir), ds_type) self.oovv = self.feri1.create_dataset('oovv', (nocc, nocc, nvir, nvir), ds_type) self.ovov = self.feri1.create_dataset('ovov', (nocc, nvir, nocc, nvir), ds_type) self.voov = self.feri1.create_dataset('voov', (nvir, nocc, nocc, nvir), ds_type) self.vovv = self.feri1.create_dataset('vovv', (nvir, nocc, nvir, nvir), ds_type) self.vvvv = self.feri1.create_dataset('vvvv', (nvir, nvir, nvir, nvir), ds_type) cput1 = time.clock(), time.time() # <ij|pq> = (ip|jq) buf = ao2mofn(cc._scf.mol, (orbo, mo_coeff, orbo, mo_coeff), compact=0) if mo_coeff.dtype == np.float: buf = buf.real buf = buf.reshape((nocc, nmo, nocc, nmo)).transpose(0, 2, 1, 3) cput1 = log.timer_debug1('transforming oopq', *cput1) self.dtype = buf.dtype self.oooo[:, :, :, :] = buf[:, :, :nocc, :nocc] self.ooov[:, :, :, :] = buf[:, :, :nocc, nocc:] self.oovv[:, :, :, :] = buf[:, :, nocc:, nocc:] cput1 = time.clock(), time.time() # <ia|pq> = (ip|aq) buf = ao2mofn(cc._scf.mol, (orbo, mo_coeff, orbv, mo_coeff), compact=0) if mo_coeff.dtype == np.float: buf = buf.real buf = buf.reshape((nocc, nmo, nvir, nmo)).transpose(0, 2, 1, 3) cput1 = log.timer_debug1('transforming ovpq', *cput1) self.ovov[:, :, :, :] = buf[:, :, :nocc, nocc:] self.vovv[:, :, :, :] = buf[:, :, nocc:, nocc:].transpose(1, 0, 3, 2) self.voov[:, :, :, :] = buf[:, :, nocc:, :nocc].transpose(1, 0, 3, 2) _tmpfile2 = tempfile.NamedTemporaryFile() self.feri2 = h5py.File(_tmpfile2.name, 'w') ao2mo.full(cc.mol, orbv, self.feri2, max_memory=cc.max_memory, verbose=log, compact=False) vvvv_buf = self.feri2['eri_mo'] for a in range(nvir): abrange = a * nvir + np.arange(nvir) self.vvvv[a, :, :, :] = np.array(vvvv_buf[abrange, :]).reshape( (nvir, nvir, nvir)).transpose(1, 0, 2) cput1 = log.timer_debug1('transforming vvvv', *cput1) log.timer('CCSD integral transformation', *cput0)
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, verbose=logger.INFO): 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 eris is None: eris = ccsd._ERIS(mycc) if mf_grad is None: mf_grad = rhf_grad.Gradients(mycc._scf) log = logger.Logger(mycc.stdout, mycc.verbose) time0 = time.clock(), time.time() mol = mycc.mol if mycc.frozen is not 0: raise NotImplementedError('frozen orbital ccsd_grad') moidx = ccsd.get_moidx(mycc) mo_coeff = mycc.mo_coeff[:, moidx] #FIXME: ensure mycc.mo_coeff is canonical orbital mo_energy = eris.fock.diagonal() nocc, nvir = t1.shape nao, nmo = mo_coeff.shape nao_pair = nao * (nao + 1) // 2 log.debug('Build ccsd rdm1 intermediates') d1 = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') d2 = ccsd_rdm.gamma2_incore(mycc, t1, t2, l1, l2) time1 = log.timer('rdm2 intermediates', *time1) log.debug('Build ccsd response_rdm1') Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris, d1, d2) time1 = log.timer('response_rdm1 intermediates', *time1) dm1mo = response_dm1(mycc, t1, t2, l1, l2, eris, (Ioo, Ivv, Ivo, Xvo)) dm1mo[:nocc, :nocc] = doo * 2 dm1mo[nocc:, nocc:] = dvv * 2 dm1ao = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) im1 = numpy.zeros_like(dm1mo) im1[:nocc, :nocc] = Ioo im1[nocc:, nocc:] = Ivv im1[nocc:, :nocc] = Ivo im1[:nocc, nocc:] = Ivo.T im1 = reduce(numpy.dot, (mo_coeff, im1, mo_coeff.T)) time1 = log.timer('response_rdm1', *time1) log.debug('symmetrized rdm2 and MO->AO transformation') dm1_with_hf = dm1mo.copy() for i in range(nocc): dm1_with_hf[i, i] += 1 dm2ao = _rdm2_mo2ao(mycc, d2, dm1_with_hf, mo_coeff) time1 = log.timer('MO->AO transformation', *time1) log.debug('h1 and JK1') h1 = mf_grad.get_hcore(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)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf4sij = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1ao + dm1ao.T), p1)) time1 = log.timer('h1 and JK1', *time1) # Hartree-Fock part contribution hf_dm1 = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ) dm1ao += hf_dm1 zeta += mf_grad.make_rdm1e(mycc.mo_energy, mycc.mo_coeff, mycc.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst), 3)) 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]) + numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1])) # h[1] \dot DM, *2 for +c.c., contribute to f1 h1ao = mf_grad._grad_rinv(mol, ia) h1ao[:, p0:p1] += h1[:, p0:p1] de[k] += (numpy.einsum('xij,ij->x', h1ao, dm1ao) + numpy.einsum('xji,ij->x', h1ao, dm1ao)) # -s[1]*e \dot DM, contribute to f1 de[k] -= (numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) + 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], vhf4sij[p0:p1]) * 2 # 2e AO integrals dot 2pdm eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=(shl0, shl1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas)) eri1 = eri1.reshape(3, p1 - p0, nao, -1) dm2buf = _load_block_tril(dm2ao, p0, p1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 eri1 = dm2buf = None log.debug('grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer('grad of atom %d' % ia, *time1) de += rhf_grad.grad_nuc(mol) log.note('CCSD gradinets') log.note('==============') log.note(' x y z') for k, ia in enumerate(atmlst): log.note('%d %s %15.9f %15.9f %15.9f', ia, mol.atom_symbol(ia), *de[k]) log.timer('CCSD gradients', *time0) return de
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, verbose=logger.INFO): 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 eris is None: eris = ccsd._ERIS(mycc) if mf_grad is None: mf_grad = rhf_grad.Gradients(mycc._scf) log = logger.new_logger(mycc, verbose) time0 = time.clock(), time.time() mol = mycc.mol if mycc.frozen is not 0: raise NotImplementedError('frozen orbital ccsd_grad') moidx = ccsd.get_moidx(mycc) mo_coeff = mycc.mo_coeff[:, moidx] #FIXME: ensure mycc.mo_coeff is canonical orbital mo_energy = eris.fock.diagonal() nocc, nvir = t1.shape nao, nmo = mo_coeff.shape nao_pair = nao * (nao + 1) // 2 log.debug('Build ccsd rdm1 intermediates') d1 = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') fd2intermediate = lib.H5TmpFile() d2 = ccsd_rdm.gamma2_outcore(mycc, t1, t2, l1, l2, fd2intermediate) time1 = log.timer('rdm2 intermediates', *time1) log.debug('Build ccsd response_rdm1') Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris, d1, d2) time1 = log.timer('response_rdm1 intermediates', *time1) dm1mo = response_dm1(mycc, t1, t2, l1, l2, eris, (Ioo, Ivv, Ivo, Xvo)) dm1mo[:nocc, :nocc] = doo + doo.T dm1mo[nocc:, nocc:] = dvv + dvv.T dm1ao = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) im1 = numpy.zeros_like(dm1mo) im1[:nocc, :nocc] = Ioo im1[nocc:, nocc:] = Ivv im1[nocc:, :nocc] = Ivo im1[:nocc, nocc:] = Ivo.T im1 = reduce(numpy.dot, (mo_coeff, im1, mo_coeff.T)) time1 = log.timer('response_rdm1', *time1) log.debug('symmetrized rdm2 and MO->AO transformation') # Basically, 4 times of dm2 is computed. *2 in _rdm2_mo2ao, *2 in _load_block_tril fdm2 = lib.H5TmpFile() dm1_with_hf = dm1mo.copy() for i in range( nocc ): # HF 2pdm ~ 4(ij)(kl)-2(il)(jk), diagonal+1 because of 4*dm2 dm1_with_hf[i, i] += 1 _rdm2_mo2ao(mycc, d2, dm1_with_hf, mo_coeff, fdm2) time1 = log.timer('MO->AO transformation', *time1) fd2intermediate = None #TODO: pass hf_grad object to compute h1 and s1 log.debug('h1 and JK1') h1 = mf_grad.get_hcore(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)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf4sij = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1ao + dm1ao.T), p1)) time1 = log.timer('h1 and JK1', *time1) # Hartree-Fock part contribution hf_dm1 = mycc._scf.make_rdm1(mycc._scf.mo_coeff, mycc._scf.mo_occ) dm1ao += hf_dm1 zeta += mf_grad.make_rdm1e(mycc._scf.mo_energy, mycc._scf.mo_coeff, mycc._scf.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() max_memory = mycc.max_memory - lib.current_memory()[0] blksize = max(1, int(max_memory * 1e6 / 8 / (nao**3 * 2.5))) ioblksize = fdm2['dm2/0'].shape[-1] de = numpy.zeros((len(atmlst), 3)) 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]) + numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1])) # h[1] \dot DM, *2 for +c.c., contribute to f1 h1ao = mf_grad._grad_rinv(mol, ia) h1ao[:, p0:p1] += h1[:, p0:p1] de[k] += (numpy.einsum('xij,ij->x', h1ao, dm1ao) + numpy.einsum('xji,ij->x', h1ao, dm1ao)) # -s[1]*e \dot DM, contribute to f1 de[k] -= (numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) + 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], vhf4sij[p0:p1]) * 2 # 2e AO integrals dot 2pdm ip0 = p0 for b0, b1, nf in shell_prange(mol, shl0, shl1, blksize): eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=(b0, b1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas)) eri1 = eri1.reshape(3, nf, nao, -1) dm2buf = numpy.empty((nf, nao, nao_pair)) for ic, (i0, i1) in enumerate(prange(0, nao_pair, ioblksize)): _load_block_tril(fdm2['dm2/%d' % ic], ip0, ip0 + nf, dm2buf[:, :, i0:i1]) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 eri1 = dm2buf = None ip0 += nf log.debug('grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer('grad of atom %d' % ia, *time1) de += rhf_grad.grad_nuc(mol) log.note('--------------- CCSD gradients ---------------') log.note(' x y z') for k, ia in enumerate(atmlst): log.note('%d %s %15.9f %15.9f %15.9f', ia, mol.atom_symbol(ia), *de[k]) log.note('----------------------------------------------') log.timer('CCSD gradients', *time0) fdm2 = None return de