Repository: pyscf/pyscf — pull request #1927 (python)
Title: fix get_bands with k-point symmetry

Fixes issue #1925.

Resolved issues:
title: scf.KUKS(cell, kpts).getbands() has problems with symmetry 
body: Hello, 

I am using the scf.KUKS object to accelerate my simulations. But when I want to plot the band diagram, it has a problem with the length of different arrays in the KNumInt.eval_rho2 function. ao_kpts has a length of 27 (3x3x3) while mo_coeff_kpts and mo_occ_kpts both have a length of 4 due to symmetry. Am I doing something wrong or is it a bug in the pySCF code? 

```kmesh = [3, 3, 3]
kpts = cell.make_kpts(kmesh, space_group_symmetry=True, time_reversal_symmetry=True)

run_scf = True

if run_scf:
    PBE = scf.KUKS(cell, kpts)
    PBE = scf.addons.smearing_(PBE, sigma=.1, method='fermi')
    PBE.xc = 'PBE'
    PBE.verbose = 4
    PBE.init_guess_breaksym=False
    PBE.init_guess = "1e"
    PBE.chkfile = 'SrVO3_PBE.chk'
    PBE.run();

## Calculate PBE bands non-selfconsistently
run_bands = True

# Define high-symmetry k-paths:
hspoints = {
  "G": [0.0, 0.0, 0.0],
  "X": [0.5, 0.0, 0.0],
  "M": [0.5, 0.5, 0.0],
  "R": [0.5, 0.5, 0.5]}

G = hspoints['G']
X = hspoints['X']
M = hspoints['M']
R = hspoints['R']
kpath = [G, X, M, G, R, X]
band_kpts, kpath, sp_points = get_bandpath(kpath, cell.a, npoints=50);
# band_kpts = libkpts.make_kpts(cell, band_kpts, space_group_symmetry=True, time_reversal_symmetry=True)
# band_kpts = cell.get_scaled_kpts(band_kpts, kpts_in_ibz=True)
band_kpts = cell.get_abs_kpts(band_kpts);

print(band_kpts)


# nscf along high-symmetry path:
if run_bands:
    nscf = scf.KUKS(cell, kpts)
    nscf.__dict__.update(chkfile.load("SrVO3_PBE.chk", 'scf'))
    E_nk = nscf.get_bands(np.array(band_kpts), kpts = kpts)[0] #the error occurs at this line
    E_F = nscf.get_fermi()
```

Hints:

Fix patch:
diff --git a/pyscf/pbc/dft/krks_ksymm.py b/pyscf/pbc/dft/krks_ksymm.py
index 087c0241f1..fb15bf6f40 100644
--- a/pyscf/pbc/dft/krks_ksymm.py
+++ b/pyscf/pbc/dft/krks_ksymm.py
@@ -42,14 +42,14 @@ def get_veff(ks, cell=None, dm=None, dm_last=0, vhf_last=0, hermi=1,
     ground_state = (isinstance(dm, np.ndarray) and dm.ndim == 3 and
                     kpts_band is None)
 
-    if kpts_band is None: kpts_band = kpts.kpts_ibz
-    dm_bz = dm
-    if ground_state:
-        if len(dm) != kpts.nkpts_ibz:
-            raise RuntimeError("Number of input density matrices does not \
-                               match the number of IBZ kpts: %d vs %d."
-                               % (len(dm), kpts.nkpts_ibz))
-        dm_bz = kpts.transform_dm(dm)
+    if kpts_band is None:
+        kpts_band = kpts.kpts_ibz
+
+    if len(dm) != kpts.nkpts_ibz:
+        raise KeyError('Shape of the input density matrix does not '
+                       'match the number of IBZ k-points: '
+                       f'{len(dm)} vs {kpts.nkpts_ibz}.')
+    dm_bz = kpts.transform_dm(dm)
 
     hybrid = ni.libxc.is_hybrid_xc(ks.xc)
 
diff --git a/pyscf/pbc/dft/kuks_ksymm.py b/pyscf/pbc/dft/kuks_ksymm.py
index 465b2943fb..eb02e674e9 100644
--- a/pyscf/pbc/dft/kuks_ksymm.py
+++ b/pyscf/pbc/dft/kuks_ksymm.py
@@ -41,14 +41,14 @@ def get_veff(ks, cell=None, dm=None, dm_last=0, vhf_last=0, hermi=1,
     # ndim = 4 : dm.shape = ([alpha,beta], nkpts, nao, nao)
     ground_state = (dm.ndim == 4 and dm.shape[0] == 2 and kpts_band is None)
 
-    if kpts_band is None: kpts_band = kpts.kpts_ibz
-    dm_bz = dm
-    if ground_state:
-        if len(dm[0]) != kpts.nkpts_ibz:
-            raise RuntimeError("Number of input density matrices does not \
-                               match the number of IBZ kpts: %d vs %d."
-                               % (len(dm[0]), kpts.nkpts_ibz))
-        dm_bz = kpts.transform_dm(dm)
+    if kpts_band is None:
+        kpts_band = kpts.kpts_ibz
+
+    if len(dm[0]) != kpts.nkpts_ibz:
+        raise KeyError('Shape of the input density matrix does not '
+                       'match the number of IBZ k-points: '
+                       f'{len(dm[0])} vs {kpts.nkpts_ibz}.')
+    dm_bz = kpts.transform_dm(dm)
 
     hybrid = ni.libxc.is_hybrid_xc(ks.xc)
 


Test patch:
diff --git a/pyscf/pbc/dft/test/test_krks_ksym.py b/pyscf/pbc/dft/test/test_krks_ksym.py
index d8977722d6..6c7bd46c4a 100644
--- a/pyscf/pbc/dft/test/test_krks_ksym.py
+++ b/pyscf/pbc/dft/test/test_krks_ksym.py
@@ -19,8 +19,10 @@
 import unittest
 import numpy as np
 
+from pyscf.lib import finger
 from pyscf.pbc import gto as pbcgto
 from pyscf.pbc import scf as pscf
+from pyscf.pbc.scf import chkfile
 from pyscf.pbc.dft import krks, kuks, multigrid
 
 def make_primitive_cell(mesh):
@@ -294,6 +296,33 @@ def test_convert_from(self):
         kumf.kernel(np.asarray([dm,dm]) / 2.)
         self.assertAlmostEqual(kmf.e_tot, kumf.e_tot, 7)
 
+    def test_get_bands(self):
+        kpts = cell.make_kpts(nk,
+                              space_group_symmetry=True,
+                              time_reversal_symmetry=True)
+        kumf = pscf.KUKS(cell, kpts=kpts)
+        kumf.xc = 'lda'
+        kumf.chkfile = 'test_get_bands_ksymm.chk'
+        kumf.kernel()
+
+        band_kpts = np.array([[-0.205736, 0.308604, 0.308604],
+                              [-0.25717,  0.308604, 0.308604]])
+        kumf = pscf.KUKS(cell, kpts=kpts)
+        kumf.__dict__.update(chkfile.load('test_get_bands_ksymm.chk', 'scf'))
+        E_nk = kumf.get_bands(band_kpts, kpts=kpts)[0]
+        E_F = kumf.get_fermi()
+        self.assertAlmostEqual(finger(np.asarray(E_nk[0])), 0.5575755379561839, 6)
+        self.assertAlmostEqual(finger(np.asarray(E_nk[1])), 0.5575755379561839, 6)
+        self.assertAlmostEqual(E_F[0], 0.3093399745201863, 6)
+        self.assertAlmostEqual(E_F[1], 0.3093399745201863, 6)
+
+        kmf = pscf.KRKS(cell, kpts=kpts)
+        kmf = kmf.convert_from_(kumf)
+        E_nk = kmf.get_bands(band_kpts, kpts=kpts)[0]
+        E_F = kmf.get_fermi()
+        self.assertAlmostEqual(finger(np.asarray(E_nk)), 0.5575755379561839, 6)
+        self.assertAlmostEqual(E_F, 0.3093399745201863, 6)
+
 if __name__ == '__main__':
     print("Full Tests for DFT with k-point symmetry")
     unittest.main()