def get_vxc_full_response(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): '''Full response including the response of the grids''' xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() excsum = 0 vmat = numpy.zeros((3,nao,nao)) if xctype == 'LDA': ao_deriv = 1 vtmp = numpy.empty((3,nao,nao)) for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): ngrids = weight.size mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[0], mask, 'LDA') exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[:2] vrho = vxc[0] vtmp = numpy.zeros((3,nao,nao)) aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) _d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho, weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = aow = None elif xctype == 'GGA': ao_deriv = 2 for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): ngrids = weight.size mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[:4], mask, 'GGA') exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[:2] vtmp = numpy.zeros((3,nao,nao)) wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho[0], weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = vsigma = wv = mat = None elif xctype == 'NLC': raise NotImplementedError('NLC') else: raise NotImplementedError('meta-GGA') # - sign because nabla_X = -nabla_x return excsum, -vmat
def get_vxc_full_response(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): '''Full response including the response of the grids''' xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() excsum = 0 vmat = numpy.zeros((3,nao,nao)) if xctype == 'LDA': ao_deriv = 1 vtmp = numpy.empty((3,nao,nao)) for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): ngrids = weight.size mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[0], mask, 'LDA') exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[:2] vrho = vxc[0] vtmp = numpy.zeros((3,nao,nao)) aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) _d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho, weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = aow = None elif xctype == 'GGA': ao_deriv = 2 for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): ngrids = weight.size mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[:4], mask, 'GGA') exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[:2] vtmp = numpy.zeros((3,nao,nao)) wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho[0], weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = vsigma = wv = mat = None elif xctype == 'NLC': raise NotImplementedError('NLC') else: raise NotImplementedError('meta-GGA') # - sign because nabla_X = -nabla_x return excsum, -vmat
def get_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((nset, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[0], mask, 'LDA') vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] vrho = vxc[0] aow = numpy.einsum('pi,p->pi', ao[0], weight * vrho) _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True) rho = vxc = vrho = aow = None elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[:4], mask, 'GGA') vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc) rho = vxc = vrho = vsigma = wv = None elif xctype == 'NLC': raise NotImplementedError('NLC') else: raise NotImplementedError('meta-GGA') exc = None if nset == 1: vmat = vmat.reshape(3, nao, nao) # - sign because nabla_X = -nabla_x return exc, -vmat
def test_gga_deriv1(self): ng = 7 xctype = 'GGA' np.random.seed(8) rho = np.random.rand(2, 4, ng) weight = 1 exc, vxc, fxc, kxc = eval_xc(f'R-{xctype}', ng) ref = numint._rks_gga_wv0(rho[0], vxc, weight) ref[0] *= 2 v1 = xc_deriv.transform_vxc(rho[0], vxc, xctype, spin=0) self.assertAlmostEqual(abs(v1 - ref).max(), 0, 12) exc, vxc, fxc, kxc = eval_xc(f'U-{xctype}', ng) ref = np.array(numint._uks_gga_wv0(rho, vxc, weight)) ref[:, 0] *= 2 v1 = xc_deriv.transform_vxc(rho, vxc, xctype, spin=1) self.assertAlmostEqual(abs(v1 - ref).max(), 0, 12)
def get_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((nset,3,nao,nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[0], mask, 'LDA') vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[1] vrho = vxc[0] aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True) rho = vxc = vrho = aow = None elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[:4], mask, 'GGA') vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc) rho = vxc = vrho = vsigma = wv = None elif xctype == 'NLC': raise NotImplementedError('NLC') else: raise NotImplementedError('meta-GGA') exc = None if nset == 1: vmat = vmat.reshape(3,nao,nao) # - sign because nabla_X = -nabla_x return exc, -vmat
def _contract_xc_kernel(td_grad, xc_code, dmvo, dmoo=None, with_vxc=True, with_kxc=True, singlet=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, nmo = mo_coeff.shape shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() # dmvo ~ reduce(numpy.dot, (orbv, Xai, orbo.T)) dmvo = (dmvo + dmvo.T) * .5 # because K_{ia,jb} == K_{ia,jb} f1vo = numpy.zeros((4, nao, nao)) # 0th-order, d/dx, d/dy, d/dz deriv = 2 if dmoo is not None: f1oo = numpy.zeros((4, nao, nao)) else: f1oo = None if with_vxc: v1ao = numpy.zeros((4, nao, nao)) else: v1ao = None if with_kxc: k1ao = numpy.zeros((4, nao, nao)) deriv = 3 else: k1ao = None if xctype == 'LDA': ao_deriv = 1 if singlet: 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, mo_occ, mask, 'LDA') vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:] wfxc = fxc[0] * weight * 2 # *2 for alpha+beta rho1 = ni.eval_rho(mol, ao[0], dmvo, mask, 'LDA') aow = numpy.einsum('pi,p,p->pi', ao[0], wfxc, rho1) for k in range(4): f1vo[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) if dmoo is not None: rho2 = ni.eval_rho(mol, ao[0], dmoo, mask, 'LDA') aow = numpy.einsum('pi,p,p->pi', ao[0], wfxc, rho2) for k in range(4): f1oo[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) if with_vxc: aow = numpy.einsum('pi,p,p->pi', ao[0], vxc[0], weight) for k in range(4): v1ao[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) if with_kxc: aow = numpy.einsum('pi,p,p,p->pi', ao[0], kxc[0], weight, rho1**2) for k in range(4): k1ao[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) vxc = fxc = kxc = aow = rho = rho1 = rho2 = None if with_kxc: # for (rho1*2)^2, *2 for alpha+beta in singlet k1ao *= 4 else: raise NotImplementedError('LDA triplet') elif xctype == 'GGA': if singlet: 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, mo_occ, mask, 'GGA') vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:] rho1 = ni.eval_rho(mol, ao, dmvo, mask, 'GGA') * 2 # *2 for alpha + beta wv = numint._rks_gga_wv1(rho, rho1, vxc, fxc, weight) gga_sum_(f1vo, ao, wv, mask) if dmoo is not None: rho2 = ni.eval_rho(mol, ao, dmoo, mask, 'GGA') * 2 wv = numint._rks_gga_wv1(rho, rho2, vxc, fxc, weight) gga_sum_(f1oo, ao, wv, mask) if with_vxc: wv = numint._rks_gga_wv0(rho, vxc, weight) gga_sum_(v1ao, ao, wv, mask) if with_kxc: wv = numint._rks_gga_wv2(rho, rho1, fxc, kxc, weight) gga_sum_(k1ao, ao, wv, mask) vxc = fxc = kxc = rho = rho1 = None else: raise NotImplementedError('GGA triplet') 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 _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = numpy.zeros((mol.natm, 3, nao, nao)) max_memory = max(2000, max_memory - vmat.size * 8 / 1e6) 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, mo_occ, mask, 'LDA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) aow1 = numpy.einsum('xpi,p->xpi', ao[1:], weight * vrho) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # First order density = rho1 * 2. *2 is not applied because + c.c. in the end rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0[:, p0:p1]) aow = numpy.einsum('pi,xp->xpi', ao[0], weight * frr * rho1) aow[:, :, p0:p1] += aow1[:, :, p0:p1] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = aow1 = None for ia in range(mol.natm): vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1) elif xctype == 'GGA': ao_deriv = 2 v_ip = numpy.zeros((3, nao, nao)) for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv) rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, p0:p1] += v_ip[:, p0:p1] vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1) elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') return vmat
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = numpy.zeros((mol.natm, 3, 3, nao, nao)) ipip = numpy.zeros((3, 3, nao, nao)) 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, mo_occ, mask, 'LDA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight * vrho) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # *2 for \nabla|ket> in rho1 rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0[:, p0:p1]) * 2 # aow ~ rho1 ~ d/dR1 aow = numpy.einsum('pi,xp->xpi', ao[0], weight * frr * rho1) _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] elif xctype == 'GGA': 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[:4], mo_coeff, mo_occ, mask, 'GGA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv[0]) rks_grad._d1_dot_(vmat[ia, 0], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wv[1]) rks_grad._d1_dot_(vmat[ia, 1], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wv[2]) rks_grad._d1_dot_(vmat[ia, 2], mol, aow, ao[0], mask, ao_loc, True) aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv) _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2) elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') return vmat
def _get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((6, nao, nao)) if xctype == 'LDA': 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[0], mo_coeff, mo_occ, mask, 'LDA') vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] vrho = vxc[0] aow = numpy.einsum('pi,p->pi', ao[0], weight * vrho) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask, shls_slice, ao_loc) aow = None elif xctype == 'GGA': def contract_(mat, ao, aoidx, wv, mask): aow = numpy.einsum('pi,p->pi', ao[aoidx[0]], wv[1]) aow += numpy.einsum('pi,p->pi', ao[aoidx[1]], wv[2]) aow += numpy.einsum('pi,p->pi', ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) ao_deriv = 3 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA') vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao wv[0] *= 2 aow = numpy.einsum('npi,np->pi', ao[:4], wv) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask, shls_slice, ao_loc) contract_(vmat[0], ao, [XXX, XXY, XXZ], wv, mask) contract_(vmat[1], ao, [XXY, XYY, XYZ], wv, mask) contract_(vmat[2], ao, [XXZ, XYZ, XZZ], wv, mask) contract_(vmat[3], ao, [XYY, YYY, YYZ], wv, mask) contract_(vmat[4], ao, [XYZ, YYZ, YZZ], wv, mask) contract_(vmat[5], ao, [XZZ, YZZ, ZZZ], wv, mask) rho = vxc = wv = aow = None elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') vmat = vmat[[0, 1, 2, 1, 3, 4, 2, 4, 5]] return vmat.reshape(3, 3, nao, nao)
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = numpy.zeros((mol.natm,3,nao,nao)) max_memory = max(2000, max_memory-vmat.size*8/1e6) 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, mo_occ, mask, 'LDA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) aow1 = numpy.einsum('xpi,p->xpi', ao[1:], weight*vrho) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # First order density = rho1 * 2. *2 is not applied because + c.c. in the end rho1 = numpy.einsum('xpi,pi->xp', ao[1:,:,p0:p1], ao_dm0[:,p0:p1]) aow = numpy.einsum('pi,xp->xpi', ao[0], weight*frr*rho1) aow[:,:,p0:p1] += aow1[:,:,p0:p1] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = aow1 = None for ia in range(mol.natm): vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1) elif xctype == 'GGA': ao_deriv = 2 v_ip = numpy.zeros((3,nao,nao)) for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) ao_dm0 = [numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4)] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv) rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia,:,p0:p1] += v_ip[:,p0:p1] vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1) elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') return vmat
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = numpy.zeros((mol.natm,3,3,nao,nao)) ipip = numpy.zeros((3,3,nao,nao)) 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, mo_occ, mask, 'LDA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight*vrho) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # *2 for \nabla|ket> in rho1 rho1 = numpy.einsum('xpi,pi->xp', ao[1:,:,p0:p1], ao_dm0[:,p0:p1]) * 2 # aow ~ rho1 ~ d/dR1 aow = numpy.einsum('pi,xp->xpi', ao[0], weight*frr*rho1) _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia,:,:,:,p0:p1] += ipip[:,:,:,p0:p1] elif xctype == 'GGA': 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[:4], mo_coeff, mo_occ, mask, 'GGA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = [numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4)] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv[0]) rks_grad._d1_dot_(vmat[ia,0], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wv[1]) rks_grad._d1_dot_(vmat[ia,1], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wv[2]) rks_grad._d1_dot_(vmat[ia,2], mol, aow, ao[0], mask, ao_loc, True) aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv) _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia,:,:,:,p0:p1] += ipip[:,:,:,p0:p1] vmat[ia,:,:,:,p0:p1] += ipip[:,:,p0:p1].transpose(1,0,3,2) elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') return vmat
def _get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((6,nao,nao)) if xctype == 'LDA': 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[0], mo_coeff, mo_occ, mask, 'LDA') vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] vrho = vxc[0] aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i+4], aow, mask, shls_slice, ao_loc) aow = None elif xctype == 'GGA': def contract_(mat, ao, aoidx, wv, mask): aow = numpy.einsum('pi,p->pi', ao[aoidx[0]], wv[1]) aow+= numpy.einsum('pi,p->pi', ao[aoidx[1]], wv[2]) aow+= numpy.einsum('pi,p->pi', ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) ao_deriv = 3 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA') vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao wv[0] *= 2 aow = numpy.einsum('npi,np->pi', ao[:4], wv) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i+4], aow, mask, shls_slice, ao_loc) contract_(vmat[0], ao, [XXX,XXY,XXZ], wv, mask) contract_(vmat[1], ao, [XXY,XYY,XYZ], wv, mask) contract_(vmat[2], ao, [XXZ,XYZ,XZZ], wv, mask) contract_(vmat[3], ao, [XYY,YYY,YYZ], wv, mask) contract_(vmat[4], ao, [XYZ,YYZ,YZZ], wv, mask) contract_(vmat[5], ao, [XZZ,YZZ,ZZZ], wv, mask) rho = vxc = wv = aow = None elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') vmat = vmat[[0,1,2, 1,3,4, 2,4,5]] return vmat.reshape(3,3,nao,nao)
def dia(magobj, gauge_orig=None): mol = magobj.mol mf = magobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ orbo = mo_coeff[:, mo_occ > 0] dm0 = numpy.dot(orbo, orbo.T) * 2 dm0 = lib.tag_array(dm0, mo_coeff=mo_coeff, mo_occ=mo_occ) dme0 = numpy.dot(orbo * mo_energy[mo_occ > 0], orbo.T) * 2 e2 = rhf_mag._get_dia_1e(magobj, gauge_orig, dm0, dme0) if gauge_orig is not None: return -e2 # Computing the 2nd order Vxc integrals from GIAO grids = mf.grids ni = mf._numint xc_code = mf.xc xctype = ni._xc_type(xc_code) omega, alpha, hyb = ni.rsh_and_hybrid_coeff(xc_code, mol.spin) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dm0, hermi=1) ngrids = len(grids.weights) mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .9 - mem_now) BLKSIZE = numint.BLKSIZE blksize = min( int(max_memory / 12 * 1e6 / 8 / nao / BLKSIZE) * BLKSIZE, ngrids) vmat = numpy.zeros((3, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 0 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, blksize=blksize): rho = make_rho(0, ao, mask, 'LDA') vxc = ni.eval_xc(xc_code, rho, 0, deriv=1)[1] vrho = vxc[0] r_ao = numpy.einsum('pi,px->pxi', ao, coords) aow = numpy.einsum('pxi,p,p->pxi', r_ao, weight, vrho) vmat += lib.einsum('pxi,pyj->xyij', r_ao, aow) rho = vxc = vrho = aow = None elif xctype == 'GGA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, blksize=blksize): rho = make_rho(0, ao, mask, 'GGA') vxc = ni.eval_xc(xc_code, rho, 0, deriv=1)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) # Computing \nabla (r * AO) = r * \nabla AO + [\nabla,r]_- * AO r_ao = numpy.einsum('npi,px->npxi', ao, coords) r_ao[1, :, 0] += ao[0] r_ao[2, :, 1] += ao[0] r_ao[3, :, 2] += ao[0] aow = numpy.einsum('npxi,np->pxi', r_ao, wv) vmat += lib.einsum('pxi,pyj->xyij', r_ao[0], aow) rho = vxc = vrho = vsigma = wv = aow = None vmat = vmat + vmat.transpose(0, 1, 3, 2) elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') vmat = _add_giao_phase(mol, vmat) e2 += numpy.einsum('qp,xypq->xy', dm0, vmat) vmat = None e2 = e2.ravel() # Handle the hybrid functional and the range-separated functional if abs(hyb) > 1e-10: vs = jk.get_jk(mol, [dm0] * 3, ['ijkl,ji->s2kl', 'ijkl,jk->s1il', 'ijkl,li->s1kj'], 'int2e_gg1', 's4', 9, hermi=1) e2 += numpy.einsum('xpq,qp->x', vs[0], dm0) e2 -= numpy.einsum('xpq,qp->x', vs[1], dm0) * .25 * hyb e2 -= numpy.einsum('xpq,qp->x', vs[2], dm0) * .25 * hyb vk = jk.get_jk(mol, dm0, 'ijkl,jk->s1il', 'int2e_g1g2', 'aa4', 9, hermi=0) e2 -= numpy.einsum('xpq,qp->x', vk, dm0) * .5 * hyb if abs(omega) > 1e-10: with mol.with_range_coulomb(omega): vs = jk.get_jk(mol, [dm0] * 2, ['ijkl,jk->s1il', 'ijkl,li->s1kj'], 'int2e_gg1', 's4', 9, hermi=1) e2 -= numpy.einsum('xpq,qp->x', vs[0], dm0) * .25 * (alpha - hyb) e2 -= numpy.einsum('xpq,qp->x', vs[1], dm0) * .25 * (alpha - hyb) vk = jk.get_jk(mol, dm0, 'ijkl,jk->s1il', 'int2e_g1g2', 'aa4', 9, hermi=0) e2 -= numpy.einsum('xpq,qp->x', vk, dm0) * .5 * (alpha - hyb) else: vj = jk.get_jk(mol, dm0, 'ijkl,ji->s2kl', 'int2e_gg1', 's4', 9, hermi=1) e2 += numpy.einsum('xpq,qp->x', vj, dm0) return -e2.reshape(3, 3)
def _contract_xc_kernel(td_grad, xc_code, dmvo, dmoo=None, with_vxc=True, with_kxc=True, singlet=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, nmo = mo_coeff.shape shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() # dmvo ~ reduce(numpy.dot, (orbv, Xai, orbo.T)) dmvo = (dmvo + dmvo.T) * .5 # because K_{ia,jb} == K_{ia,jb} f1vo = numpy.zeros((4,nao,nao)) # 0th-order, d/dx, d/dy, d/dz deriv = 2 if dmoo is not None: f1oo = numpy.zeros((4,nao,nao)) else: f1oo = None if with_vxc: v1ao = numpy.zeros((4,nao,nao)) else: v1ao = None if with_kxc: k1ao = numpy.zeros((4,nao,nao)) deriv = 3 else: k1ao = None if xctype == 'LDA': ao_deriv = 1 if singlet: 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, mo_occ, mask, 'LDA') vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:] wfxc = fxc[0] * weight * 2 # *2 for alpha+beta rho1 = ni.eval_rho(mol, ao[0], dmvo, mask, 'LDA') aow = numpy.einsum('pi,p,p->pi', ao[0], wfxc, rho1) for k in range(4): f1vo[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) if dmoo is not None: rho2 = ni.eval_rho(mol, ao[0], dmoo, mask, 'LDA') aow = numpy.einsum('pi,p,p->pi', ao[0], wfxc, rho2) for k in range(4): f1oo[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) if with_vxc: aow = numpy.einsum('pi,p,p->pi', ao[0], vxc[0], weight) for k in range(4): v1ao[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) if with_kxc: aow = numpy.einsum('pi,p,p,p->pi', ao[0], kxc[0], weight, rho1**2) for k in range(4): k1ao[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc) vxc = fxc = kxc = aow = rho = rho1 = rho2 = None if with_kxc: # for (rho1*2)^2, *2 for alpha+beta in singlet k1ao *= 4 else: raise NotImplementedError('LDA triplet') elif xctype == 'GGA': if singlet: 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, mo_occ, mask, 'GGA') vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:] rho1 = ni.eval_rho(mol, ao, dmvo, mask, 'GGA') * 2 # *2 for alpha + beta wv = numint._rks_gga_wv1(rho, rho1, vxc, fxc, weight) gga_sum_(f1vo, ao, wv, mask) if dmoo is not None: rho2 = ni.eval_rho(mol, ao, dmoo, mask, 'GGA') * 2 wv = numint._rks_gga_wv1(rho, rho2, vxc, fxc, weight) gga_sum_(f1oo, ao, wv, mask) if with_vxc: wv = numint._rks_gga_wv0(rho, vxc, weight) gga_sum_(v1ao, ao, wv, mask) if with_kxc: wv = numint._rks_gga_wv2(rho, rho1, fxc, kxc, weight) gga_sum_(k1ao, ao, wv, mask) vxc = fxc = kxc = rho = rho1 = None else: raise NotImplementedError('GGA triplet') 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 get_vxc(ni, cell, grids, xc_code, dms, kpts, kpts_band=None, relativity=0, hermi=1, max_memory=2000, verbose=None): xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(cell, dms, hermi) ao_loc = cell.ao_loc_nr() nkpts = len(kpts) vmat = np.zeros((3, nset, nkpts, nao, nao), dtype=dms.dtype) if xctype == 'LDA': ao_deriv = 1 for ao_k1, ao_k2, mask, weight, coords \ in ni.block_loop(cell, grids, nao, ao_deriv, kpts, kpts_band, max_memory): ao_k1 = np.asarray(ao_k1) ao_k2 = np.asarray(ao_k2) for i in range(nset): rho = make_rho(i, ao_k2[:, 0], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1)[1] vrho = vxc[0] aow = np.einsum('xpi,p->xpi', ao_k1[:, 0], weight * vrho) for kn in range(nkpts): rks_grad._d1_dot_(vmat[:, i, kn], cell, ao_k1[kn, 1:4], aow[kn], mask, ao_loc, True) rho = vrho = aow = None elif xctype == 'GGA': ao_deriv = 2 for ao_k1, ao_k2, mask, weight, coords \ in ni.block_loop(cell, grids, nao, ao_deriv, kpts, kpts_band, max_memory): ao_k1 = np.asarray(ao_k1) ao_k2 = np.asarray(ao_k2) for i in range(nset): rho = make_rho(i, ao_k2[:, :4], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) for kn in range(nkpts): rks_grad._gga_grad_sum_(vmat[:, i, kn], cell, ao_k1[kn], wv, mask, ao_loc) rho = vxc = wv = None elif xctype == 'NLC': raise NotImplementedError("NLC") else: raise NotImplementedError("metaGGA") if nset == 1: return -vmat[:, 0] else: return -vmat
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) v_ip = numpy.zeros((3, nao, nao)) vmat = numpy.zeros((mol.natm, 3, nao, nao)) max_memory = max(2000, max_memory - vmat.size * 8 / 1e6) 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, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] aow = numint._scale_ao(ao[0], weight * vrho) rks_grad._d1_dot_(v_ip, mol, ao[1:4], aow, mask, ao_loc, True) ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # First order density = rho1 * 2. *2 is not applied because + c.c. in the end rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0[:, p0:p1]) wv = weight * frr * rho1 aow = [numint._scale_ao(ao[0], wv[i]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None elif xctype == 'GGA': 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[:4], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None elif xctype == 'MGGA': if grids.level < 5: logger.warn(mol, 'MGGA Hessian is sensitive to dft grids.') 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[:10], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_mgga_wv0(rho, vxc, weight) rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv0 rks_grad._tau_grad_dot_(v_ip, mol, ao, wv[5] * 2, mask, ao_loc, True) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices, xctype) wv[0] = numint._rks_mgga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_mgga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_mgga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) for j in range(1, 4): aow = [numint._scale_ao(ao[j], wv[i, 5]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[j], mask, ao_loc, True) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, p0:p1] += v_ip[:, p0:p1] vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1) return vmat
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = numpy.zeros((mol.natm, 3, 3, nao, nao)) ipip = numpy.zeros((3, 3, nao, nao)) 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, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] wv = weight * vrho aow = [numint._scale_ao(ao[i], wv) for i in range(1, 4)] _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # *2 for \nabla|ket> in rho1 rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0[:, p0:p1]) * 2 # aow ~ rho1 ~ d/dR1 wv = weight * frr * rho1 aow = [numint._scale_ao(ao[0], wv[i]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] elif xctype == 'GGA': 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[:4], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) for i in range(3): wv[i] = numint._rks_gga_wv1(rho, dR_rho1[i], vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv[i]) rks_grad._d1_dot_(vmat[ia, i], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2) elif xctype == 'MGGA': XX, XY, XZ = 4, 5, 6 YX, YY, YZ = 5, 7, 8 ZX, ZY, ZZ = 6, 8, 9 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[:10], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_mgga_wv0(rho, vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) aow = [numint._scale_ao(ao[i], wv[5]) for i in range(4, 10)] _d1d2_dot_(ipip, mol, [aow[0], aow[1], aow[2]], [ao[XX], ao[XY], ao[XZ]], mask, ao_loc, False) _d1d2_dot_(ipip, mol, [aow[1], aow[3], aow[4]], [ao[YX], ao[YY], ao[YZ]], mask, ao_loc, False) _d1d2_dot_(ipip, mol, [aow[2], aow[4], aow[5]], [ao[ZX], ao[ZY], ao[ZZ]], mask, ao_loc, False) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices, xctype) for i in range(3): wv[i] = numint._rks_mgga_wv1(rho, dR_rho1[i], vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv[i]) rks_grad._d1_dot_(vmat[ia, i], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv1 wv[:, 5] *= 2 aow = [numint._scale_ao(ao[1], wv[i, 5]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, [ao[XX], ao[XY], ao[XZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[2], wv[i, 5]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, [ao[YX], ao[YY], ao[YZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[3], wv[i, 5]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, [ao[ZX], ao[ZY], ao[ZZ]], aow, mask, ao_loc, False) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2) return vmat
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory): """" This functions is slightly different from hessian.rks._get_vxc_deriv1 in that <\nabla u|Vxc|v> is removed""" mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = np.zeros((mol.natm,3,nao,nao)) max_memory = max(2000, max_memory-vmat.size*8/1e6) 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, mo_occ, mask, 'LDA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] frr = fxc[0] ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] rho1 = np.einsum('xpi,pi->xp', ao[1:,:,p0:p1], ao_dm0[:,p0:p1]) aow = np.einsum('pi,xp->xpi', ao[0], weight*frr*rho1) rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None for ia in range(mol.natm): vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1) elif xctype == 'GGA': ao_deriv = 2 # v_ip = np.zeros((3,nao,nao)) for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) # rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) ao_dm0 = [numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4)] for ia in range(mol.natm): wv = dR_rho1 = rks_hess._make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = np.einsum('npi,Xnp->Xpi', ao[:4], wv) rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None for ia in range(mol.natm): vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1) elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') return vmat
def get_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((nset, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[0], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] vrho = vxc[0] #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) aow = numint._scale_ao(ao[0], weight * vrho) _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True) elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[:4], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc) elif xctype == 'NLC': raise NotImplementedError('NLC') elif xctype == 'MGGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[:10], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] wv = numint._rks_mgga_wv0(rho, vxc, weight) _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv0 _tau_grad_dot_(vmat[idm], mol, ao, wv[5] * 2, mask, ao_loc, True) exc = None if nset == 1: vmat = vmat[0] # - sign because nabla_X = -nabla_x return exc, -vmat
def exc_rks(mf, emb_dm, dm, relativity=0, hermi=0, max_memory=2000, verbose=None): ni = mf._numint mol = mf.mol grids = mf.grids xc_code = mf.xc xctype = ni._xc_type(xc_code) make_rho_emb, nset, nao = ni._gen_rho_evaluator(mol, emb_dm, hermi) make_rho_sub, nset_2, nao_2 = ni._gen_rho_evaluator(mol, dm, hermi) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() nelec = np.zeros(nset) excsum = np.zeros(nset) vmat = np.zeros((nset, nao, nao)) aow = None if xctype == 'LDA': ao_deriv = 0 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): aow = np.ndarray(ao.shape, order='F', buffer=aow) for idm in range(nset): rho_emb = make_rho_emb(idm, ao, mask, 'LDA') rho_sub = make_rho_sub(idm, ao, mask, 'LDA') exc, vxc = ni.eval_xc(xc_code, rho_emb, 0, relativity, 1, verbose)[:2] vrho = vxc[0] den = rho_sub * weight nelec[idm] += den.sum() excsum[idm] += np.dot(den, exc) # *.5 because vmat + vmat.T aow = np.einsum('pi,p->pi', ao, .5 * weight * vrho, out=aow) vmat[idm] += numint._dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) rho_emb = rho_sub = exc = vxc = vrho = None elif xctype == 'GGA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): ngrid = weight.size aow = np.ndarray(ao[0].shape, order='F', buffer=aow) for idm in range(nset): rho_emb = make_rho_emb(idm, ao, mask, 'GGA') rho_sub = make_rho_sub(idm, ao, mask, 'GGA') exc, vxc = ni.eval_xc(xc_code, rho_emb, 0, relativity, 1, verbose)[:2] den = rho_sub[0] * weight nelec[idm] += den.sum() excsum[idm] += np.dot(den, exc) # ref eval_mat function wv = numint._rks_gga_wv0(rho_sub, vxc, weight) aow = np.einsum('npi,np->pi', ao, wv, out=aow) vmat[idm] += numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) rho_emb = rho_sub = exc = vxc = wv = None elif xctype == 'NLC': nlc_pars = ni.nlc_coeff(xc_code[:-6]) if nlc_pars == [0, 0]: raise NotImplementedError('VV10 cannot be used with %s. ' 'The supported functionals are %s' % (xc_code[:-6], ni.libxc.VV10_XC)) ao_deriv = 1 vvrho = np.empty([nset, 4, 0]) vvweight = np.empty([nset, 0]) vvcoords = np.empty([nset, 0, 3]) for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhotmp = np.empty([0, 4, weight.size]) weighttmp = np.empty([0, weight.size]) coordstmp = np.empty([0, weight.size, 3]) for idm in range(nset): rho_emb = make_rho_emb(idm, ao, mask, 'GGA') rho_sub = make_rho_sub(idm, ao, mask, 'GGA') rho_emb = np.expand_dims(rho, axis=0) rhotmp = np.concatenate((rhotmp, rho_emb), axis=0) weighttmp = np.concatenate( (weighttmp, np.expand_dims(weight, axis=0)), axis=0) coordstmp = np.concatenate( (coordstmp, np.expand_dims(coords, axis=0)), axis=0) rho = None vvrho = np.concatenate((vvrho, rhotmp), axis=2) vvweight = np.concatenate((vvweight, weighttmp), axis=1) vvcoords = np.concatenate((vvcoords, coordstmp), axis=1) rhotmp = weighttmp = coordstmp = None for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): ngrid = weight.size aow = np.ndarray(ao[0].shape, order='F', buffer=aow) for idm in range(nset): rho_emb = make_rho_emb(idm, ao, mask, 'GGA') rho_sub = make_rho_sub(idm, ao, mask, 'GGA') exc, vxc = numint._vv10nlc(rho_emb, coords, vvrho[idm], vvweight[idm], vvcoords[idm], nlc_pars) den = rho_sub[0] * weight nelec[idm] += den.sum() excsum[idm] += np.dot(den, exc) # ref eval_mat function wv = numint._rks_gga_wv0(rho_emb, vxc, weight) aow = np.einsum('npi,np->pi', ao, wv, out=aow) vmat[idm] += numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) rho = exc = vxc = wv = None vvrho = vvweight = vvcoords = None elif xctype == 'MGGA': if (any(x in xc_code.upper() for x in ('CC06', 'CS', 'BR89', 'MK00'))): raise NotImplementedError('laplacian in meta-GGA method') ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): ngrid = weight.size aow = np.ndarray(ao[0].shape, order='F', buffer=aow) for idm in range(nset): rho_emb = make_rho_emb(idm, ao, mask, 'MGGA') rho_sub = make_rho_sub(idm, ao, mask, 'MGGA') exc, vxc = ni.eval_xc(xc_code, rho_emb, 0, relativity, 1, verbose)[:2] vrho, vsigma, vlapl, vtau = vxc[:4] den = rho_sub[0] * weight nelec[idm] += den.sum() excsum[idm] += np.dot(den, exc) wv = numint._rks_gga_wv0(rho_emb, vxc, weight) aow = np.einsum('npi,np->pi', ao[:4], wv, out=aow) vmat[idm] += numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) # FIXME: .5 * .5 First 0.5 for v+v.T symmetrization. # Second 0.5 is due to the Libxc convention tau = 1/2 \nabla\phi\dot\nabla\phi wv = (.5 * .5 * weight * vtau).reshape(-1, 1) vmat[idm] += numint._dot_ao_ao(mol, ao[1], wv * ao[1], mask, shls_slice, ao_loc) vmat[idm] += numint._dot_ao_ao(mol, ao[2], wv * ao[2], mask, shls_slice, ao_loc) vmat[idm] += numint._dot_ao_ao(mol, ao[3], wv * ao[3], mask, shls_slice, ao_loc) rho_emb = rho_sub = exc = vxc = vrho = vsigma = wv = None for i in range(nset): vmat[i] = vmat[i] + vmat[i].T if nset == 1: nelec = nelec[0] excsum = excsum[0] vmat = vmat.reshape(nao, nao) return nelec, excsum, vmat