def _compute_multipole_potential_integrals(pe, site, order, moments): if order > 2: raise NotImplementedError("""Multipole potential integrals not implemented for order > 2.""") pe.mol.set_rinv_orig(site) # TODO: only calculate up to requested order! integral0 = pe.mol.intor("int1e_rinv") integral1 = pe.mol.intor("int1e_iprinv") + pe.mol.intor("int1e_iprinv").transpose(0, 2, 1) integral2 = pe.mol.intor("int1e_ipiprinv") + pe.mol.intor("int1e_ipiprinv").transpose(0, 2, 1) + 2.0 * pe.mol.intor("int1e_iprinvip") # k = 2: 0,1,2,4,5,8 = XX, XY, XZ, YY, YZ, ZZ # add the lower triangle to the upper triangle, i.e., # XY += YX : 1 + 3 # XZ += ZX : 2 + 6 # YZ += ZY : 5 + 7 # and divide by 2 integral2[1] += integral2[3] integral2[2] += integral2[6] integral2[5] += integral2[7] integral2[1] *= 0.5 integral2[2] *= 0.5 integral2[5] *= 0.5 op = integral0 * moments[0] * cppe.prefactors(0) if order > 0: op += numpy.einsum('aij,a->ij', integral1, moments[1] * cppe.prefactors(1)) if order > 1: op += numpy.einsum('aij,a->ij', integral2[[0, 1, 2, 4, 5, 8], :, :], moments[2] * cppe.prefactors(2)) return op
def _compute_multipole_potential_integrals(self, sites, orders, moments): orders = numpy.asarray(orders) if numpy.any(orders > 2): raise NotImplementedError("""Multipole potential integrals not implemented for order > 2.""") # order 0 fakemol = gto.fakemol_for_charges(sites) integral0 = df.incore.aux_e2(self.mol, fakemol, intor='int3c2e') moments_0 = numpy.array([m[0] for m in moments]) op = numpy.einsum('ijg,ga->ij', integral0, moments_0 * cppe.prefactors(0)) # order 1 if numpy.any(orders >= 1): idx = numpy.where(orders >= 1)[0] fakemol = gto.fakemol_for_charges(sites[idx]) integral1 = df.incore.aux_e2(self.mol, fakemol, intor='int3c2e_ip1') moments_1 = numpy.array([moments[i][1] for i in idx]) v = numpy.einsum('aijg,ga,a->ij', integral1, moments_1, cppe.prefactors(1)) op += v + v.T if numpy.any(orders >= 2): idx = numpy.where(orders >= 2)[0] fakemol = gto.fakemol_for_charges(sites[idx]) n_sites = idx.size # moments_2 is the lower triangler of # [[XX, XY, XZ], [YX, YY, YZ], [ZX, ZY, ZZ]] i.e. # XX, XY, XZ, YY, YZ, ZZ = 0,1,2,4,5,8 # symmetrize it to the upper triangler part # XX, YX, ZX, YY, ZY, ZZ = 0,3,6,4,7,8 m2 = numpy.einsum('ga,a->ga', [moments[i][2] for i in idx], cppe.prefactors(2)) moments_2 = numpy.zeros((n_sites, 9)) moments_2[:, [0, 1, 2, 4, 5, 8]] = m2 moments_2[:, [0, 3, 6, 4, 7, 8]] += m2 moments_2 *= .5 integral2 = df.incore.aux_e2(self.mol, fakemol, intor='int3c2e_ipip1') v = numpy.einsum('aijg,ga->ij', integral2, moments_2) op += v + v.T integral2 = df.incore.aux_e2(self.mol, fakemol, intor='int3c2e_ipvip1') op += numpy.einsum('aijg,ga->ij', integral2, moments_2) * 2 return op
def build_electrostatics_operator(self): n_bas = self.basisset.nbf() self.V_es = np.zeros((n_bas, n_bas)) for site in self.cppe_state.potentials: prefactors = [] for multipole in site.multipoles: prefactors.extend(cppe.prefactors(multipole.k) * multipole.values) integrals = self.mints.ao_multipole_potential(site.position, max_k=multipole.k) self.V_es += sum(pref * intv.np for pref, intv in zip(prefactors, integrals))
def build_electrostatics_operator(self): n_bas = self.basisset.nbf() self.V_es = np.zeros((n_bas, n_bas)) # TODO: run this in one go... for site in self.cppe_state.potentials: prefactors = [] for multipole in site.multipoles: prefactors.extend(cppe.prefactors(multipole.k) * multipole.values) integrals = self.mints.ao_multipole_potential(order=multipole.k, origin=site.position) self.V_es += sum(pref * intv.np for pref, intv in zip(prefactors, integrals))
def test_prefactors(self): for k in range(3): assert prefactors(k) == prefs[k]