Task: Add NLC response function for GKS (pyscf/pyscf#2871)

org: pyscf
repo: pyscf
pr_number: 2871
issue_title: Add NLC response function for GKS
issue_body: fix #2863
resolved_issues: number: 2863
title: [FEATURE REQUEST] Nonlocal corrections and GKS
body: Hello! 

I would like to run GKS with the VV10 dispersion correction. However, I get the error "NotImplementedError: NLC" from the `_gen_ghf_response` function in scf/_response_functions.py. Is there any way to include VV10 for use with the GKS module? Or has VV10 only been developed for RKS and UKS thus far?

Thank you!

Reference solution:
fix_patch: diff --git a/pyscf/dft/numint2c.py b/pyscf/dft/numint2c.py
index f34bc6b892..0daadda128 100644
--- a/pyscf/dft/numint2c.py
+++ b/pyscf/dft/numint2c.py
@@ -679,8 +679,8 @@ def nr_nlc_vxc(self, mol, grids, xc_code, dm, spin=0, relativity=0, hermi=1,
         n, exc, v = ni.nr_nlc_vxc(mol, grids, xc_code, dm_a+dm_b, relativity,
                                   hermi, max_memory, verbose)
         vmat = np.zeros_like(dm)
-        vmat[:nao,:nao] = v[0]
-        vmat[nao:,nao:] = v[1]
+        vmat[:nao,:nao] = v
+        vmat[nao:,nao:] = v
         return n, exc, vmat
 
     @lib.with_doc(numint.nr_rks_fxc.__doc__)
diff --git a/pyscf/hessian/rks.py b/pyscf/hessian/rks.py
index 554bdd2f1f..b559c6d7e8 100644
--- a/pyscf/hessian/rks.py
+++ b/pyscf/hessian/rks.py
@@ -1849,19 +1849,20 @@ def get_vnlc_resp(mf, mol, mo_coeff, mo_occ, dm1s, max_memory):
 
         TODO: check the effect of different grid, using mf.nlcgrids right now
     """
-    if mo_coeff.ndim == 2:
+    if isinstance(mo_coeff, numpy.ndarray) and mo_coeff.ndim == 2:
         mocc = mo_coeff[:,mo_occ>0]
         mo_occ = mo_occ[mo_occ > 0]
         dm0 = (mocc * mo_occ) @ mocc.T
     else:
-        assert mo_coeff.ndim == 3 # unrestricted case
-        assert mo_coeff.shape[0] == 2
-        assert mo_occ.shape[0] == 2
+        assert mo_coeff[0].ndim == 2 # unrestricted case
+        assert len(mo_coeff) == 2
+        assert len(mo_occ) == 2
         mocc_a = mo_coeff[0][:, mo_occ[0] > 0]
         mocc_b = mo_coeff[1][:, mo_occ[1] > 0]
-        mo_occ_a = mo_occ[0, mo_occ[0] > 0]
-        mo_occ_b = mo_occ[1, mo_occ[1] > 0]
+        mo_occ_a = mo_occ[0][mo_occ[0] > 0]
+        mo_occ_b = mo_occ[1][mo_occ[1] > 0]
         dm0 = (mocc_a * mo_occ_a) @ mocc_a.T + (mocc_b * mo_occ_b) @ mocc_b.T
+    dm0 = numpy.asarray(dm0.real, order='C')
 
     output_in_2d = False
     if dm1s.ndim == 2:
diff --git a/pyscf/scf/_response_functions.py b/pyscf/scf/_response_functions.py
index fd7f458e48..df75029caa 100644
--- a/pyscf/scf/_response_functions.py
+++ b/pyscf/scf/_response_functions.py
@@ -267,8 +267,6 @@ def _gen_ghf_response(mf, mo_coeff=None, mo_occ=None,
         ni = mf._numint
         assert isinstance(ni, (numint2c.NumInt2C, r_numint.RNumInt))
         ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True)
-        if with_nlc and mf.do_nlc():
-            raise NotImplementedError('NLC')
         omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)
         hybrid = ni.libxc.is_hybrid_xc(mf.xc)
 
@@ -288,6 +286,20 @@ def vind(dm1):
             else:
                 v1 = ni.get_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, 0, hermi,
                                 rho0, vxc, fxc, max_memory=max_memory)
+                if with_nlc and mf.do_nlc():
+                    from pyscf.hessian.rks import get_vnlc_resp
+                    nao = mo_coeff.shape[0] // 2
+                    dm1_sf = dm1[...,:nao,:nao] + dm1[...,nao:,nao:]
+                    mo_uks = [mo_coeff[:nao], mo_coeff[nao:]]
+                    mo_occ_uks = [mo_occ, mo_occ]
+                    # The get_vnlc_resp function uses mf._numint and explicitly
+                    # calls the NumInt functions for mf._numint
+                    ni1c = mf._numint._to_numint1c()
+                    with lib.temporary_env(mf, _numint=ni1c):
+                        vxc_nlc = get_vnlc_resp(mf, mol, mo_uks, mo_occ_uks,
+                                                dm1_sf.real, max_memory)
+                        v1[...,:nao,:nao] += vxc_nlc
+                        v1[...,nao:,nao:] += vxc_nlc
             if not hybrid:
                 if with_j:
                     vj = mf.get_j(mol, dm1, hermi=hermi)