def tda_grad(td, z): '''ddcosmo TDA gradients''' mol = td.mol mf = td._scf mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff.shape nocc = (mo_occ > 0).sum() nvir = nmo - nocc z = z[0].reshape(nocc, nvir).T * numpy.sqrt(2) orbv = mo_coeff[:, nocc:] orbo = mo_coeff[:, :nocc] r_vdw = ddcosmo.get_atomic_radii(td.with_solvent) fi = ddcosmo.make_fi(td.with_solvent, r_vdw) ui = 1 - fi coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere( td.with_solvent.lebedev_order) ylm_1sph = numpy.vstack( sph.real_sph_vec(coords_1sph, td.with_solvent.lmax, True)) grids = td.with_solvent.grids cached_pol = ddcosmo.cache_fake_multipoles(grids, r_vdw, td.with_solvent.lmax) L = ddcosmo.make_L(td.with_solvent, r_vdw, ylm_1sph, fi) def fvind(x): v_mo = numpy.einsum('iabj,xai->xbj', g[:nocc, nocc:, nocc:, :nocc], x) v_mo += numpy.einsum('aibj,xai->xbj', g[nocc:, :nocc, nocc:, :nocc], x) return v_mo h1 = rhf_grad.get_hcore(mol) s1 = rhf_grad.get_ovlp(mol) eri1 = -mol.intor('int2e_ip1', aosym='s1', comp=3) eri1 = eri1.reshape(3, nao, nao, nao, nao) eri0 = ao2mo.kernel(mol, mo_coeff) eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo, nmo, nmo, nmo) g = eri0 * 2 - eri0.transpose(0, 3, 2, 1) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[nocc:] dielectric = td.with_solvent.eps if dielectric > 0: f_epsilon = (dielectric - 1.) / dielectric else: f_epsilon = 1 pcm_nuc = .5 * f_epsilon * nuc_part1(td.with_solvent, r_vdw, ui, ylm_1sph, cached_pol, L) B0 = .5 * f_epsilon * make_B(td.with_solvent, r_vdw, ui, ylm_1sph, cached_pol, L) B0 = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', B0, mo_coeff, mo_coeff, mo_coeff, mo_coeff) g += B0 * 2 B1 = .5 * f_epsilon * make_B1(td.with_solvent, r_vdw, ui, ylm_1sph, cached_pol, L) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((mol.natm, 3)) for ia in range(mol.natm): shl0, shl1, p0, p1 = offsetdic[ia] mol.set_rinv_origin(mol.atom_coord(ia)) h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3) h1ao[:, p0:p1] += h1[:, p0:p1] h1ao = h1ao + h1ao.transpose(0, 2, 1) h1ao += pcm_nuc[ia] h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff) s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:, p0:p1], mo_coeff) s1mo = s1mo + s1mo.transpose(0, 2, 1) f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta) f1 -= numpy.einsum('klpq,xlk->xpq', g[:nocc, :nocc], s1mo[:, :nocc, :nocc]) eri1a = eri1.copy() eri1a[:, :p0] = 0 eri1a[:, p1:] = 0 eri1a = eri1a + eri1a.transpose(0, 2, 1, 3, 4) eri1a = eri1a + eri1a.transpose(0, 3, 4, 1, 2) g1 = lib.einsum('xpqrs,pi,qj,rk,sl->xijkl', eri1a, mo_coeff, mo_coeff, mo_coeff, mo_coeff) tmp1 = lib.einsum('xpqrs,pi,qj,rk,sl->xijkl', B1[ia], mo_coeff, mo_coeff, mo_coeff, mo_coeff) g1 = g1 * 2 - g1.transpose(0, 1, 4, 3, 2) g1 += tmp1 * 2 f1 += numpy.einsum('xkkpq->xpq', g1[:, :nocc, :nocc]) f1ai = f1[:, nocc:, :nocc].copy() c1 = s1mo * -.5 c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0] c1[:, nocc:, :nocc] = c1vo c1[:, :nocc, nocc:] = -(s1mo[:, nocc:, :nocc] + c1vo).transpose(0, 2, 1) f1 += numpy.einsum('kapq,xak->xpq', g[:nocc, nocc:], c1vo) f1 += numpy.einsum('akpq,xak->xpq', g[nocc:, :nocc], c1vo) e1 = numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:], z, z) e1 += numpy.einsum('xab,ai,bi->x', f1[:, nocc:, nocc:], z, z) e1 -= numpy.einsum('xij,ai,aj->x', f1[:, :nocc, :nocc], z, z) g1 = numpy.einsum('pjkl,xpi->xijkl', g, c1) g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1) g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1) g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1) e1 += numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:], z, z) de[ia] = e1 return de
def kernel(tdgrad, z, atmlst=None, mf_grad=None, max_memory=2000, verbose=logger.INFO): mol = tdgrad.mol mf = tdgrad.base._scf mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff.shape nocc = (mo_occ > 0).sum() nvir = nmo - nocc #eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) z = z[0].reshape(nocc, nvir).T orbv = mo_coeff[:, nocc:] orbo = mo_coeff[:, :nocc] def fvind(x): dm = numpy.einsum('pi,xij,qj->xpq', orbv, x, orbo) v_ao = mf.get_veff(mol, (dm + dm.transpose(0, 2, 1))) * 2 return numpy.einsum('pi,xpq,qj->xij', orbv, v_ao, orbo).reshape(3, -1) h1 = rhf_grad.get_hcore(mol) s1 = rhf_grad.get_ovlp(mol) eri1 = -mol.intor('int2e_ip1', aosym='s1', comp=3) eri1 = eri1.reshape(3, nao, nao, nao, nao) eri0 = ao2mo.kernel(mol, mo_coeff) eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo, nmo, nmo, nmo) g = eri0 * 2 - eri0.transpose(0, 3, 2, 1) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[nocc:] 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] mol.set_rinv_origin(mol.atom_coord(ia)) h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3) h1ao[:, p0:p1] += h1[:, p0:p1] h1ao = h1ao + h1ao.transpose(0, 2, 1) h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff) s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:, p0:p1], mo_coeff) s1mo = s1mo + s1mo.transpose(0, 2, 1) f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta) f1 -= numpy.einsum('klpq,xlk->xpq', g[:nocc, :nocc], s1mo[:, :nocc, :nocc]) eri1a = eri1.copy() eri1a[:, :p0] = 0 eri1a[:, p1:] = 0 eri1a = eri1a + eri1a.transpose(0, 2, 1, 3, 4) eri1a = eri1a + eri1a.transpose(0, 3, 4, 1, 2) g1 = numpy.einsum('xpjkl,pi->xijkl', eri1a, mo_coeff) g1 = numpy.einsum('xipkl,pj->xijkl', g1, mo_coeff) g1 = numpy.einsum('xijpl,pk->xijkl', g1, mo_coeff) g1 = numpy.einsum('xijkp,pl->xijkl', g1, mo_coeff) g1 = g1 * 2 - g1.transpose(0, 1, 4, 3, 2) f1 += numpy.einsum('xkkpq->xpq', g1[:, :nocc, :nocc]) f1ai = f1[:, nocc:, :nocc].copy() c1 = s1mo * -.5 c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0] c1[:, nocc:, :nocc] = c1vo c1[:, :nocc, nocc:] = -(s1mo[:, nocc:, :nocc] + c1vo).transpose(0, 2, 1) f1 += numpy.einsum('kapq,xak->xpq', g[:nocc, nocc:], c1vo) f1 += numpy.einsum('akpq,xak->xpq', g[nocc:, :nocc], c1vo) e1 = numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:], z, z) e1 += numpy.einsum('xab,ai,bi->x', f1[:, nocc:, nocc:], z, z) e1 -= numpy.einsum('xij,ai,aj->x', f1[:, :nocc, :nocc], z, z) g1 = numpy.einsum('pjkl,xpi->xijkl', g, c1) g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1) g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1) g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1) e1 += numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:], z, z) de[k] = e1 return de
def kernel(tdgrad, z, atmlst=None, mf_grad=None, max_memory=2000, verbose=logger.INFO): mol = tdgrad.mol mf = tdgrad.base._scf mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff.shape nocc = (mo_occ>0).sum() nvir = nmo - nocc #eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) z = z[0].reshape(nocc,nvir).T orbv = mo_coeff[:,nocc:] orbo = mo_coeff[:,:nocc] def fvind(x): dm = numpy.einsum('pi,xij,qj->xpq', orbv, x, orbo) v_ao = mf.get_veff(mol, (dm+dm.transpose(0,2,1)))*2 return numpy.einsum('pi,xpq,qj->xij', orbv, v_ao, orbo).reshape(3,-1) h1 = rhf_grad.get_hcore(mol) s1 = rhf_grad.get_ovlp(mol) eri1 = -mol.intor('int2e_ip1', aosym='s1', comp=3) eri1 = eri1.reshape(3,nao,nao,nao,nao) eri0 = ao2mo.kernel(mol, mo_coeff) eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo,nmo,nmo,nmo) g = eri0 * 2 - eri0.transpose(0,3,2,1) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:,:nocc] = mo_energy[:nocc] zeta[:nocc,nocc:] = mo_energy[nocc:] 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] mol.set_rinv_origin(mol.atom_coord(ia)) h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3) h1ao[:,p0:p1] += h1[:,p0:p1] h1ao = h1ao + h1ao.transpose(0,2,1) h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff) s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:,p0:p1], mo_coeff) s1mo = s1mo + s1mo.transpose(0,2,1) f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta) f1-= numpy.einsum('klpq,xlk->xpq', g[:nocc,:nocc], s1mo[:,:nocc,:nocc]) eri1a = eri1.copy() eri1a[:,:p0] = 0 eri1a[:,p1:] = 0 eri1a = eri1a + eri1a.transpose(0,2,1,3,4) eri1a = eri1a + eri1a.transpose(0,3,4,1,2) g1 = numpy.einsum('xpjkl,pi->xijkl', eri1a, mo_coeff) g1 = numpy.einsum('xipkl,pj->xijkl', g1, mo_coeff) g1 = numpy.einsum('xijpl,pk->xijkl', g1, mo_coeff) g1 = numpy.einsum('xijkp,pl->xijkl', g1, mo_coeff) g1 = g1 * 2 - g1.transpose(0,1,4,3,2) f1 += numpy.einsum('xkkpq->xpq', g1[:,:nocc,:nocc]) f1ai = f1[:,nocc:,:nocc].copy() c1 = s1mo * -.5 c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0] c1[:,nocc:,:nocc] = c1vo c1[:,:nocc,nocc:] = -(s1mo[:,nocc:,:nocc]+c1vo).transpose(0,2,1) f1 += numpy.einsum('kapq,xak->xpq', g[:nocc,nocc:], c1vo) f1 += numpy.einsum('akpq,xak->xpq', g[nocc:,:nocc], c1vo) e1 = numpy.einsum('xaijb,ai,bj->x', g1[:,nocc:,:nocc,:nocc,nocc:], z, z) e1 += numpy.einsum('xab,ai,bi->x', f1[:,nocc:,nocc:], z, z) e1 -= numpy.einsum('xij,ai,aj->x', f1[:,:nocc,:nocc], z, z) g1 = numpy.einsum('pjkl,xpi->xijkl', g, c1) g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1) g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1) g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1) e1 += numpy.einsum('xaijb,ai,bj->x', g1[:,nocc:,:nocc,:nocc,nocc:], z, z) de[k] = e1 return de