Source code for pyscf.pbc.grad.kuks

#!/usr/bin/env python
# Copyright 2020-2021 The PySCF Developers. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Yang Gao <younggao1994@gmail.com>
#

'''
Non-relativistic analytical nuclear gradients for unrestricted Kohn Sham with kpoints sampling
'''

import numpy as np
from pyscf.lib import logger
from pyscf import lib
from pyscf.grad import rks as rks_grad
from pyscf.pbc.grad import kuhf as uhf_grad
from pyscf.dft import numint
from pyscf.pbc import gto


[docs] def get_veff(ks_grad, dm=None, kpts=None): mf = ks_grad.base cell = ks_grad.cell if dm is None: dm = mf.make_rdm1() if kpts is None: kpts = mf.kpts t0 = (logger.process_clock(), logger.perf_counter()) ni = mf._numint if ks_grad.grids is not None: grids = ks_grad.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) mem_now = lib.current_memory()[0] max_memory = max(2000, ks_grad.max_memory*.9-mem_now) if ks_grad.grid_response: raise NotImplementedError else: vxc = get_vxc(ni, cell, grids, mf.xc, dm, kpts, max_memory=max_memory, verbose=ks_grad.verbose) t0 = logger.timer(ks_grad, 'vxc', *t0) if not ni.libxc.is_hybrid_xc(mf.xc): vj = ks_grad.get_j(dm, kpts) vxc += vj[:,0][:,None] + vj[:,1][:,None] else: omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=cell.spin) vj, vk = ks_grad.get_jk(dm, kpts) vk *= hyb if omega != 0: with cell.with_range_coulomb(omega): vk += ks_grad.get_k(dm, kpts) * (alpha - hyb) vxc += vj[:,0][:,None] + vj[:,1][:,None] - vk return vxc
[docs] 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) rho_a = make_rho(0, ao_k2[:,0], mask, xctype) rho_b = make_rho(1, ao_k2[:,0], mask, xctype) vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1)[1] vrho = vxc[0] aowa = np.einsum('xpi,p->xpi', ao_k1[:,0], weight*vrho[:,0]) aowb = np.einsum('xpi,p->xpi', ao_k1[:,0], weight*vrho[:,1]) ao_k2 = rho_a = rho_b = vxc = None for kn in range(nkpts): rks_grad._d1_dot_(vmat[:,0,kn], cell, ao_k1[kn,1:4], aowa[kn], mask, ao_loc, True) rks_grad._d1_dot_(vmat[:,1,kn], cell, ao_k1[kn,1:4], aowb[kn], mask, ao_loc, True) ao_k1 = aowa = aowb = 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) rho_a = make_rho(0, ao_k2[:,:4], mask, xctype) rho_b = make_rho(1, ao_k2[:,:4], mask, xctype) vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1)[1] wva, wvb = numint._uks_gga_wv0((rho_a, rho_b), vxc, weight) ao_k2 = rho_a = rho_b = vxc = None for kn in range(nkpts): rks_grad._gga_grad_sum_(vmat[:,0,kn], cell, ao_k1[kn], wva, mask, ao_loc) rks_grad._gga_grad_sum_(vmat[:,1,kn], cell, ao_k1[kn], wvb, mask, ao_loc) ao_k1 = wva = wvb = None elif xctype=='NLC': raise NotImplementedError("NLC") else: raise NotImplementedError("metaGGA") return -vmat
[docs] class Gradients(uhf_grad.Gradients): '''Non-relativistic restricted Hartree-Fock gradients''' _keys = {'grid_response', 'grids'} def __init__(self, mf): uhf_grad.Gradients.__init__(self, mf) self.grids = None self.grid_response = False get_veff = get_veff
if __name__=='__main__': from pyscf.pbc import dft cell = gto.Cell() cell.atom = [['He', [0.0, 0.0, 0.0]], ['He', [1, 1.1, 1.2]]] cell.basis = 'gth-dzv' cell.a = np.eye(3) * 3 cell.mesh = [19,19,19] cell.unit='bohr' cell.pseudo='gth-pade' cell.verbose=5 cell.build() nmp = [1,1,5] kpts = cell.make_kpts(nmp) kmf = dft.KUKS(cell, kpts) kmf.exxdiv = None kmf.xc = 'b3lyp' kmf.kernel() mygrad = Gradients(kmf) mygrad.kernel()