def test_gga_deriv3(self): ng = 7 xctype = 'GGA' np.random.seed(8) rho = np.random.rand(2, 4, ng) rho1 = np.random.rand(2, 4, ng) weight = 1 exc, vxc, fxc, kxc = eval_xc(f'R-{xctype}', ng) ref = numint._rks_gga_wv2(rho[0], rho1[0], fxc, kxc, weight) ref[0] *= 2 v1 = xc_deriv.transform_kxc(rho[0], fxc, kxc, xctype, spin=0) v1 = np.einsum('xg,yg,xyzg->zg', rho1[0], rho1[0], v1) self.assertAlmostEqual(abs(v1 - ref).max(), 0, 12) exc, vxc, fxc, kxc = eval_xc(f'U-{xctype}', ng) ref = np.array(numint._uks_gga_wv2(rho, rho1, fxc, kxc, weight)) ref[:, 0] *= 2 v1 = xc_deriv.transform_kxc(rho, fxc, kxc, xctype, spin=1) v1 = np.einsum('axg,byg,axbyczg->czg', rho1, rho1, v1) self.assertAlmostEqual(abs(v1 - ref).max(), 0, 12)
def _contract_xc_kernel(td_grad, xc_code, dmvo, dmoo=None, with_vxc=True, with_kxc=True, max_memory=2000): mol = td_grad.mol mf = td_grad.base._scf grids = mf.grids ni = mf._numint xctype = ni._xc_type(xc_code) mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ nao = mo_coeff[0].shape[0] shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() # dmvo ~ reduce(numpy.dot, (orbv, Xai, orbo.T)) dmvo = [(dmvo[0] + dmvo[0].T) * .5, # because K_{ia,jb} == K_{ia,jb} (dmvo[1] + dmvo[1].T) * .5] f1vo = numpy.zeros((2,4,nao,nao)) deriv = 2 if dmoo is not None: f1oo = numpy.zeros((2,4,nao,nao)) else: f1oo = None if with_vxc: v1ao = numpy.zeros((2,4,nao,nao)) else: v1ao = None if with_kxc: k1ao = numpy.zeros((2,4,nao,nao)) deriv = 3 else: k1ao = None if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask, 'LDA'), ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask, 'LDA')) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] u_u, u_d, d_d = fxc[0].T * weight rho1a = ni.eval_rho(mol, ao[0], dmvo[0], mask, 'LDA') rho1b = ni.eval_rho(mol, ao[0], dmvo[1], mask, 'LDA') aow = (numpy.einsum('pi,p,p->pi', ao[0], u_u, rho1a) + numpy.einsum('pi,p,p->pi', ao[0], u_d, rho1b), numpy.einsum('pi,p,p->pi', ao[0], u_d, rho1a) + numpy.einsum('pi,p,p->pi', ao[0], d_d, rho1b)) for k in range(4): f1vo[0,k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) f1vo[1,k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) if dmoo is not None: rho2a = ni.eval_rho(mol, ao[0], dmoo[0], mask, 'LDA') rho2b = ni.eval_rho(mol, ao[0], dmoo[1], mask, 'LDA') aow = (numpy.einsum('pi,p,p->pi', ao[0], u_u, rho2a) + numpy.einsum('pi,p,p->pi', ao[0], u_d, rho2b), numpy.einsum('pi,p,p->pi', ao[0], u_d, rho2a) + numpy.einsum('pi,p,p->pi', ao[0], d_d, rho2b)) for k in range(4): f1oo[0,k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) f1oo[1,k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) if with_vxc: vrho = vxc[0].T * weight aow = (numpy.einsum('pi,p->pi', ao[0], vrho[0]), numpy.einsum('pi,p->pi', ao[0], vrho[1])) for k in range(4): v1ao[0,k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) v1ao[1,k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) if with_kxc: u_u_u, u_u_d, u_d_d, d_d_d = kxc[0].T * weight aow = (numpy.einsum('pi,p,p,p->pi', ao[0], u_u_u, rho1a, rho1a) + numpy.einsum('pi,p,p,p->pi', ao[0], u_u_d, rho1a, rho1b)*2 + numpy.einsum('pi,p,p,p->pi', ao[0], u_d_d, rho1b, rho1b), numpy.einsum('pi,p,p,p->pi', ao[0], u_u_d, rho1a, rho1a) + numpy.einsum('pi,p,p,p->pi', ao[0], u_d_d, rho1a, rho1b)*2 + numpy.einsum('pi,p,p,p->pi', ao[0], d_d_d, rho1b, rho1b)) for k in range(4): k1ao[0,k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) k1ao[1,k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) vxc = fxc = kxc = aow = rho = rho1 = rho2 = None elif xctype == 'GGA': def gga_sum_(vmat, ao, wv, mask): aow = numpy.einsum('pi,p->pi', ao[0], wv[0]) aow += numpy.einsum('npi,np->pi', ao[1:4], wv[1:]) tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) vmat[0] += tmp + tmp.T rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv, mask, ao_loc) ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao, mo_coeff[0], mo_occ[0], mask, 'GGA'), ni.eval_rho2(mol, ao, mo_coeff[1], mo_occ[1], mask, 'GGA')) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] rho1 = (ni.eval_rho(mol, ao, dmvo[0], mask, 'GGA'), ni.eval_rho(mol, ao, dmvo[1], mask, 'GGA')) wv = numint._uks_gga_wv1(rho, rho1, vxc, fxc, weight) gga_sum_(f1vo[0], ao, wv[0], mask) gga_sum_(f1vo[1], ao, wv[1], mask) if dmoo is not None: rho2 = (ni.eval_rho(mol, ao, dmoo[0], mask, 'GGA'), ni.eval_rho(mol, ao, dmoo[1], mask, 'GGA')) wv = numint._uks_gga_wv1(rho, rho2, vxc, fxc, weight) gga_sum_(f1oo[0], ao, wv[0], mask) gga_sum_(f1oo[1], ao, wv[1], mask) if with_vxc: wv = numint._uks_gga_wv0(rho, vxc, weight) gga_sum_(v1ao[0], ao, wv[0], mask) gga_sum_(v1ao[1], ao, wv[1], mask) if with_kxc: wv = numint._uks_gga_wv2(rho, rho1, fxc, kxc, weight) gga_sum_(k1ao[0], ao, wv[0], mask) gga_sum_(k1ao[1], ao, wv[1], mask) vxc = fxc = kxc = rho = rho1 = None else: raise NotImplementedError('meta-GGA') f1vo[:,1:] *= -1 if f1oo is not None: f1oo[:,1:] *= -1 if v1ao is not None: v1ao[:,1:] *= -1 if k1ao is not None: k1ao[:,1:] *= -1 return f1vo, f1oo, v1ao, k1ao
def _contract_xc_kernel(td_grad, xc_code, dmvo, dmoo=None, with_vxc=True, with_kxc=True, max_memory=2000): mol = td_grad.mol mf = td_grad.base._scf grids = mf.grids ni = mf._numint xctype = ni._xc_type(xc_code) mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ nao = mo_coeff[0].shape[0] shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() # dmvo ~ reduce(numpy.dot, (orbv, Xai, orbo.T)) dmvo = [ (dmvo[0] + dmvo[0].T) * .5, # because K_{ia,jb} == K_{ia,jb} (dmvo[1] + dmvo[1].T) * .5 ] f1vo = numpy.zeros((2, 4, nao, nao)) deriv = 2 if dmoo is not None: f1oo = numpy.zeros((2, 4, nao, nao)) else: f1oo = None if with_vxc: v1ao = numpy.zeros((2, 4, nao, nao)) else: v1ao = None if with_kxc: k1ao = numpy.zeros((2, 4, nao, nao)) deriv = 3 else: k1ao = None if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask, 'LDA'), ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask, 'LDA')) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] u_u, u_d, d_d = fxc[0].T * weight rho1a = ni.eval_rho(mol, ao[0], dmvo[0], mask, 'LDA') rho1b = ni.eval_rho(mol, ao[0], dmvo[1], mask, 'LDA') aow = (numpy.einsum('pi,p,p->pi', ao[0], u_u, rho1a) + numpy.einsum('pi,p,p->pi', ao[0], u_d, rho1b), numpy.einsum('pi,p,p->pi', ao[0], u_d, rho1a) + numpy.einsum('pi,p,p->pi', ao[0], d_d, rho1b)) for k in range(4): f1vo[0, k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) f1vo[1, k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) if dmoo is not None: rho2a = ni.eval_rho(mol, ao[0], dmoo[0], mask, 'LDA') rho2b = ni.eval_rho(mol, ao[0], dmoo[1], mask, 'LDA') aow = (numpy.einsum('pi,p,p->pi', ao[0], u_u, rho2a) + numpy.einsum('pi,p,p->pi', ao[0], u_d, rho2b), numpy.einsum('pi,p,p->pi', ao[0], u_d, rho2a) + numpy.einsum('pi,p,p->pi', ao[0], d_d, rho2b)) for k in range(4): f1oo[0, k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) f1oo[1, k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) if with_vxc: vrho = vxc[0].T * weight aow = (numpy.einsum('pi,p->pi', ao[0], vrho[0]), numpy.einsum('pi,p->pi', ao[0], vrho[1])) for k in range(4): v1ao[0, k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) v1ao[1, k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) if with_kxc: u_u_u, u_u_d, u_d_d, d_d_d = kxc[0].T * weight aow = ( numpy.einsum('pi,p,p,p->pi', ao[0], u_u_u, rho1a, rho1a) + numpy.einsum('pi,p,p,p->pi', ao[0], u_u_d, rho1a, rho1b) * 2 + numpy.einsum('pi,p,p,p->pi', ao[0], u_d_d, rho1b, rho1b), numpy.einsum('pi,p,p,p->pi', ao[0], u_u_d, rho1a, rho1a) + numpy.einsum('pi,p,p,p->pi', ao[0], u_d_d, rho1a, rho1b) * 2 + numpy.einsum('pi,p,p,p->pi', ao[0], d_d_d, rho1b, rho1b)) for k in range(4): k1ao[0, k] += numint._dot_ao_ao(mol, ao[k], aow[0], mask, shls_slice, ao_loc) k1ao[1, k] += numint._dot_ao_ao(mol, ao[k], aow[1], mask, shls_slice, ao_loc) vxc = fxc = kxc = aow = rho = rho1 = rho2 = None elif xctype == 'GGA': def gga_sum_(vmat, ao, wv, mask): aow = numpy.einsum('pi,p->pi', ao[0], wv[0]) aow += numpy.einsum('npi,np->pi', ao[1:4], wv[1:]) tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) vmat[0] += tmp + tmp.T rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv, mask, ao_loc) ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao, mo_coeff[0], mo_occ[0], mask, 'GGA'), ni.eval_rho2(mol, ao, mo_coeff[1], mo_occ[1], mask, 'GGA')) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] rho1 = (ni.eval_rho(mol, ao, dmvo[0], mask, 'GGA'), ni.eval_rho(mol, ao, dmvo[1], mask, 'GGA')) wv = numint._uks_gga_wv1(rho, rho1, vxc, fxc, weight) gga_sum_(f1vo[0], ao, wv[0], mask) gga_sum_(f1vo[1], ao, wv[1], mask) if dmoo is not None: rho2 = (ni.eval_rho(mol, ao, dmoo[0], mask, 'GGA'), ni.eval_rho(mol, ao, dmoo[1], mask, 'GGA')) wv = numint._uks_gga_wv1(rho, rho2, vxc, fxc, weight) gga_sum_(f1oo[0], ao, wv[0], mask) gga_sum_(f1oo[1], ao, wv[1], mask) if with_vxc: wv = numint._uks_gga_wv0(rho, vxc, weight) gga_sum_(v1ao[0], ao, wv[0], mask) gga_sum_(v1ao[1], ao, wv[1], mask) if with_kxc: wv = numint._uks_gga_wv2(rho, rho1, fxc, kxc, weight) gga_sum_(k1ao[0], ao, wv[0], mask) gga_sum_(k1ao[1], ao, wv[1], mask) vxc = fxc = kxc = rho = rho1 = None else: raise NotImplementedError('meta-GGA') f1vo[:, 1:] *= -1 if f1oo is not None: f1oo[:, 1:] *= -1 if v1ao is not None: v1ao[:, 1:] *= -1 if k1ao is not None: k1ao[:, 1:] *= -1 return f1vo, f1oo, v1ao, k1ao
def _contract_xc_kernel(td_grad, xc_code, dmvo, dmoo=None, with_vxc=True, with_kxc=True, max_memory=2000): mol = td_grad.mol mf = td_grad.base._scf grids = mf.grids ni = mf._numint xctype = ni._xc_type(xc_code) mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ nao = mo_coeff[0].shape[0] shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() # dmvo ~ reduce(numpy.dot, (orbv, Xai, orbo.T)) dmvo = [ (dmvo[0] + dmvo[0].T) * .5, # because K_{ia,jb} == K_{ia,jb} (dmvo[1] + dmvo[1].T) * .5 ] f1vo = numpy.zeros((2, 4, nao, nao)) deriv = 2 if dmoo is not None: f1oo = numpy.zeros((2, 4, nao, nao)) else: f1oo = None if with_vxc: v1ao = numpy.zeros((2, 4, nao, nao)) else: v1ao = None if with_kxc: k1ao = numpy.zeros((2, 4, nao, nao)) deriv = 3 else: k1ao = None if xctype == 'LDA': def lda_sum_(vmat, ao, wv, mask): aow = numint._scale_ao(ao[0], wv) for k in range(4): vmat[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask, xctype), ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask, xctype)) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] u_u, u_d, d_d = fxc[0].T * weight rho1a = ni.eval_rho(mol, ao[0], dmvo[0], mask, xctype) rho1b = ni.eval_rho(mol, ao[0], dmvo[1], mask, xctype) lda_sum_(f1vo[0], ao, u_u * rho1a + u_d * rho1b, mask) lda_sum_(f1vo[1], ao, u_d * rho1a + d_d * rho1b, mask) if dmoo is not None: rho2a = ni.eval_rho(mol, ao[0], dmoo[0], mask, xctype) rho2b = ni.eval_rho(mol, ao[0], dmoo[1], mask, xctype) lda_sum_(f1oo[0], ao, u_u * rho2a + u_d * rho2b, mask) lda_sum_(f1oo[1], ao, u_d * rho2a + d_d * rho2b, mask) if with_vxc: vrho = vxc[0].T * weight lda_sum_(v1ao[0], ao, vrho[0], mask) lda_sum_(v1ao[1], ao, vrho[1], mask) if with_kxc: u_u_u, u_u_d, u_d_d, d_d_d = kxc[0].T * weight lda_sum_( k1ao[0], ao, u_u_u * rho1a * rho1a + u_u_d * rho1a * rho1b * 2 + u_d_d * rho1b * rho1b, mask) lda_sum_( k1ao[1], ao, u_u_d * rho1a * rho1a + u_d_d * rho1a * rho1b * 2 + d_d_d * rho1b * rho1b, mask) elif xctype == 'GGA': def gga_sum_(vmat, ao, wv, mask): aow = numint._scale_ao(ao[:4], wv[:4]) tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) vmat[0] += tmp + tmp.T rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv, mask, ao_loc) ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao, mo_coeff[0], mo_occ[0], mask, xctype), ni.eval_rho2(mol, ao, mo_coeff[1], mo_occ[1], mask, xctype)) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] rho1 = (ni.eval_rho(mol, ao, dmvo[0], mask, xctype), ni.eval_rho(mol, ao, dmvo[1], mask, xctype)) wv = numint._uks_gga_wv1(rho, rho1, vxc, fxc, weight) gga_sum_(f1vo[0], ao, wv[0], mask) gga_sum_(f1vo[1], ao, wv[1], mask) if dmoo is not None: rho2 = (ni.eval_rho(mol, ao, dmoo[0], mask, xctype), ni.eval_rho(mol, ao, dmoo[1], mask, xctype)) wv = numint._uks_gga_wv1(rho, rho2, vxc, fxc, weight) gga_sum_(f1oo[0], ao, wv[0], mask) gga_sum_(f1oo[1], ao, wv[1], mask) if with_vxc: wv = numint._uks_gga_wv0(rho, vxc, weight) gga_sum_(v1ao[0], ao, wv[0], mask) gga_sum_(v1ao[1], ao, wv[1], mask) if with_kxc: wv = numint._uks_gga_wv2(rho, rho1, fxc, kxc, weight) gga_sum_(k1ao[0], ao, wv[0], mask) gga_sum_(k1ao[1], ao, wv[1], mask) vxc = fxc = kxc = rho = rho1 = None elif xctype == 'MGGA': logger.warn(mol, 'More tests are needed for TD-MGGA') def mgga_sum_(vmat, ao, wv, mask): aow = numint._scale_ao(ao[:4], wv[:4]) tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) aow = numint._scale_ao(ao[1], wv[5], aow) tmp += numint._dot_ao_ao(mol, ao[1], aow, mask, shls_slice, ao_loc) aow = numint._scale_ao(ao[2], wv[5], aow) tmp += numint._dot_ao_ao(mol, ao[2], aow, mask, shls_slice, ao_loc) aow = numint._scale_ao(ao[3], wv[5], aow) tmp += numint._dot_ao_ao(mol, ao[3], aow, mask, shls_slice, ao_loc) vmat[0] += tmp + tmp.T rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv[:4], mask, ao_loc) rks_grad._tau_grad_dot_(vmat[1:], mol, ao, wv[5] * 2, mask, ao_loc, True) ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = (ni.eval_rho2(mol, ao, mo_coeff[0], mo_occ[0], mask, xctype), ni.eval_rho2(mol, ao, mo_coeff[1], mo_occ[1], mask, xctype)) vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 1, deriv=deriv)[1:] rho1 = (ni.eval_rho(mol, ao, dmvo[0], mask, xctype), ni.eval_rho(mol, ao, dmvo[1], mask, xctype)) wv = numint._uks_mgga_wv1(rho, rho1, vxc, fxc, weight) mgga_sum_(f1vo[0], ao, wv[0], mask) mgga_sum_(f1vo[1], ao, wv[1], mask) if dmoo is not None: rho2 = (ni.eval_rho(mol, ao, dmoo[0], mask, xctype), ni.eval_rho(mol, ao, dmoo[1], mask, xctype)) wv = numint._uks_mgga_wv1(rho, rho2, vxc, fxc, weight) mgga_sum_(f1oo[0], ao, wv[0], mask) mgga_sum_(f1oo[1], ao, wv[1], mask) if with_vxc: wv = numint._uks_mgga_wv0(rho, vxc, weight) mgga_sum_(v1ao[0], ao, wv[0], mask) mgga_sum_(v1ao[1], ao, wv[1], mask) if with_kxc: wv = numint._uks_mgga_wv2(rho, rho1, fxc, kxc, weight) mgga_sum_(k1ao[0], ao, wv[0], mask) mgga_sum_(k1ao[1], ao, wv[1], mask) vxc = fxc = kxc = rho = rho1 = None elif xctype == 'HF': pass else: raise NotImplementedError(f'td-uks for functional {xc_code}') f1vo[:, 1:] *= -1 if f1oo is not None: f1oo[:, 1:] *= -1 if v1ao is not None: v1ao[:, 1:] *= -1 if k1ao is not None: k1ao[:, 1:] *= -1 return f1vo, f1oo, v1ao, k1ao