Repository: pyscf/pyscf — pull request #1584 (python)
Title: fix phase error for k-point symmetry

This PR fixes issue #1582.

Resolved issues:
title: KsymAdaptedRCCSD Not Converge
body: Dear developers,

I'm testing the latest CCSD with k-point symmetries for periodic systems. However, the following calculation for diamond primitive cell with 3x3x3 k-point sampling does not converge. Please see the scripts and corresponding outputs below. Thank you!

## Version information
```
Python 3.8.13
GCC 7.5.0
PySCF version: 2.1.1
GIT HEAD      7bcae2e3044bf4259f1c6e6b03829912ce0ae1a0
```

## CCSD without k-point symmetry
The calculation without symmetries ended gracefully. 

Here is the CCSD input without k-point symmetries:
```python
from pyscf.pbc import gto, df, scf, cc
from pyscf import scf as mol_scf
from time import time

start_time = time()

cell = gto.Cell()
cell.atom = "C 0.0000 0.0000 0.0000; C 0.8900 0.8900 0.8900"
cell.a = [[0.0000, 1.7800, 1.7800], [1.7800, 0.0000, 1.7800], [1.7800, 1.7800, 0.0000]]
cell.basis = "gth-szv"
cell.pseudo = "gth-pade"
cell.max_memory = 512000 
cell.verbose = 4
# cell.precision = 1e-4

cell.build()

kmesh = [3,3,3]
kpts = cell.make_kpts(kmesh)
khf = scf.KRHF(cell, kpts)
khf = mol_scf.addons.remove_linear_dep_(khf)
khf.kernel()
print(f"** HF total energy [Ha]: {khf.e_tot} **")

kcc = cc.KRCCSD(khf)
kcc.conv_tol = 1e-4
kcc.conv_tol_normt = 1e-3
kcc.kernel()

print(f"** MP2 total energy [Ha]: {kcc.emp2 + khf.e_tot} **")
print(f"** MP2 correlation [Ha]: {kcc.emp2} **")
print(f"** CCSD total energy [Ha]: {kcc.e_tot} **")
print(f"** CCSD correlation [Ha]: {kcc.e_corr} **")

end_time = time()

print(f"#####################################################")
print(f"# Finished in {end_time - start_time:10.2f} seconds. #")
print(f"#####################################################")
```

Here is the output:
```python
******** <class 'pyscf.pbc.cc.kccsd_rhf.RCCSD'> ********
CC2 = 0
CCSD nocc = 4, nmo = 8
max_cycle = 50
direct = 1
conv_tol = 0.0001
conv_tol_normt = 0.001
diis_space = 6
diis_start_cycle = 0
diis_start_energy_diff = 1e+09
max_memory 512000 MB (current use 229 MB)
using incore ERI storage
Init t2, MP2 energy (with fock eigenvalue shift) = -0.101136246587875
Init E_corr(CCSD) = -0.101136246587875
cycle = 1  E_corr(CCSD) = -0.11302371985953  dE = -0.0118874733  norm(t1,t2) = 0.199481
cycle = 2  E_corr(CCSD) = -0.116486053728869  dE = -0.00346233387  norm(t1,t2) = 0.0672819
cycle = 3  E_corr(CCSD) = -0.11809151506564  dE = -0.00160546134  norm(t1,t2) = 0.0298103
cycle = 4  E_corr(CCSD) = -0.118301235613774  dE = -0.000209720548  norm(t1,t2) = 0.00626899
cycle = 5  E_corr(CCSD) = -0.118298883933205  dE = 2.35168057e-06  norm(t1,t2) = 0.0019157
cycle = 6  E_corr(CCSD) = -0.118295531043058  dE = 3.35289015e-06  norm(t1,t2) = 0.000438101
RCCSD converged
E(RCCSD) = -11.11828707024064  E_corr = -0.1182955310430577
** MP2 total energy [Ha]: -11.101127785785454 **
** MP2 correlation [Ha]: -0.10113624658787514 **
** CCSD total energy [Ha]: -11.118287070240635 **
** CCSD correlation [Ha]: -0.11829553104305766 **
#####################################################
# Finished in    3442.58 seconds. #
#####################################################
```

## CCSD with k-point symmetries
Here is the input file
```python
from pyscf.pbc import gto, df, scf, cc
from pyscf import scf as mol_scf
from time import time

start_time = time()

cell = gto.Cell()
cell.atom = "C 0.0000 0.0000 0.0000; C 0.8900 0.8900 0.8900"
cell.a = [[0.0000, 1.7800, 1.7800], [1.7800, 0.0000, 1.7800], [1.7800, 1.7800, 0.0000]]
cell.basis = "gth-szv"
cell.pseudo = "gth-pade"
cell.max_memory = 512000
cell.verbose = 4
# cell.precision = 1e-8
cell.space_group_symmetry = True
cell.build()

kmesh = [3,3,3]
kpts = cell.make_kpts(kmesh, with_gamma_point=True, space_group_symmetry=True)
khf = scf.KRHF(cell, kpts)
khf = mol_scf.addons.remove_linear_dep_(khf)
khf.kernel()
print(f"** HF total energy [Ha]: {khf.e_tot} **")

kcc = cc.KsymAdaptedRCCSD(khf)
kcc.conv_tol = 1e-4
kcc.conv_tol_normt = 1e-3
kcc.kernel()

print(f"** MP2 total energy [Ha]: {kcc.emp2 + khf.e_tot} **")
print(f"** MP2 correlation [Ha]: {kcc.emp2} **")
print(f"** CCSD total energy [Ha]: {kcc.e_tot} **")
print(f"** CCSD correlation [Ha]: {kcc.e_corr} **")

end_time = time()

print(f"#####################################################")
print(f"# Finished in {end_time - start_time:10.2f} seconds. #")
print(f"#####################################################")
```
But unfortunately, the CCSD calculation does not converge:
```python
******** <class 'pyscf.pbc.cc.kccsd_rhf_ksymm.KsymAdaptedRCCSD'> ********
CC2 = 0
CCSD nocc = 4, nmo = 8
max_cycle = 50
direct = 1
conv_tol = 0.0001
conv_tol_normt = 0.001
diis_space = 6
diis_start_cycle = 0
diis_start_energy_diff = 1e+09
max_memory 512000 MB (current use 269 MB)
Incore memory estimation: 999.240704 MB
using incore ERI storage
Init t2, MP2 energy (with fock eigenvalue shift) = 115.220187475672
Init E_corr(CCSD) = 115.220187475672
cycle = 1  E_corr(CCSD) = 1105912122.99569  dE = 1.10591201e+09  norm(t1,t2) = 1.26556e+07

WARN: Non-zero imaginary part found in KRCCSD energy (1.6764182260999362e+23-16275017475.528364j)

cycle = 2  E_corr(CCSD) = 1.67641822609994e+23  dE = 1.67641823e+23  norm(t1,t2) = 6.48812e+21

WARN: Non-zero imaginary part found in KRCCSD energy (-7.192569978591114e+74-3.580017490652341e+62j)

cycle = 3  E_corr(CCSD) = -7.19256997859111e+74  dE = -7.19256998e+74  norm(t1,t2) = 2.42369e+51

WARN: Non-zero imaginary part found in KRCCSD energy (-1.2621487897532068e+225-1.8297827444511553e+213j)

cycle = 4  E_corr(CCSD) = -1.26214878975321e+225  dE = -1.26214879e+225  norm(t1,t2) = 1.95135e+152
cycle = 5  E_corr(CCSD) = nan  dE = nan  norm(t1,t2) = nan
...
```






Hints:

Fix patch:
diff --git a/pyscf/pbc/symm/symmetry.py b/pyscf/pbc/symm/symmetry.py
index 41d8a0606d..3618039c8f 100644
--- a/pyscf/pbc/symm/symmetry.py
+++ b/pyscf/pbc/symm/symmetry.py
@@ -235,7 +235,7 @@ def _get_phase(cell, op, kpt_scaled, ignore_phase=False, tol=SYMPREC):
         # remove numerical noise, important for symmetry adaptation
         Lshift = Lshift.round()
         if not ignore_phase:
-            phase[iatm] = np.exp(-1j * np.dot(kpt_scaled, Lshift) * 2.0 * np.pi)
+            phase[iatm] = np.exp(1j * np.dot(kpt_scaled, Lshift) * 2.0 * np.pi)
     return atm_map, phase
 
 def _get_rotation_mat(cell, kpt_scaled_ibz, mo_coeff_or_dm, op, Dmats,


Test patch:
diff --git a/pyscf/pbc/lib/test/test_kpts_ksymm.py b/pyscf/pbc/lib/test/test_kpts_ksymm.py
index 5e7a0b2ddd..9de0d07bcb 100644
--- a/pyscf/pbc/lib/test/test_kpts_ksymm.py
+++ b/pyscf/pbc/lib/test/test_kpts_ksymm.py
@@ -36,15 +36,16 @@ def setUpModule():
               [2.6935121974, 2.6935121974, 0.0]]
     cell.basis = 'gth-szv'
     cell.pseudo  = 'gth-pade'
-    cell.mesh = [24,24,24]
+    cell.mesh = [20,] * 3
     cell.space_group_symmetry = True
     cell.build()
 
     cell1 = cell.copy()
     cell1.build(symmorphic=True)
 
-    kpts0 = cell.make_kpts([2,2,2])
+    kpts0 = cell.make_kpts([3,3,3])
     kmf = scf.KRKS(cell, kpts0)
+    kmf.max_cycle=1
     kmf.kernel()
 
 def tearDownModule():
@@ -91,12 +92,12 @@ def test_transform(self):
         kpts = libkpts.make_kpts(cell, kpts0, space_group_symmetry=True, time_reversal_symmetry=True)
         dms_ibz = kmf.make_rdm1()[kpts.ibz2bz]
         dms_bz = kpts.transform_dm(dms_ibz)
-        self.assertAlmostEqual(abs(dms_bz - kmf.make_rdm1()).max(), 0, 9)
+        self.assertAlmostEqual(abs(dms_bz - kmf.make_rdm1()).max(), 0, 7)
 
         mo_coeff_ibz = np.asarray(kmf.mo_coeff)[kpts.ibz2bz]
         mo_coeff_bz = kpts.transform_mo_coeff(mo_coeff_ibz)
         dms_bz = khf.make_rdm1(mo_coeff_bz, kmf.mo_occ)
-        self.assertAlmostEqual(abs(dms_bz - kmf.make_rdm1()).max(), 0, 9)
+        self.assertAlmostEqual(abs(dms_bz - kmf.make_rdm1()).max(), 0, 7)
 
         mo_occ_ibz = kpts.check_mo_occ_symmetry(kmf.mo_occ)
         mo_occ_bz = kpts.transform_mo_occ(mo_occ_ibz)
@@ -104,17 +105,17 @@ def test_transform(self):
 
         mo_energy_ibz = np.asarray(kmf.mo_energy)[kpts.ibz2bz]
         mo_energy_bz = kpts.transform_mo_energy(mo_energy_ibz)
-        self.assertAlmostEqual(abs(mo_energy_bz - np.asarray(kmf.mo_energy)).max(), 0 , 9)
+        self.assertAlmostEqual(abs(mo_energy_bz - np.asarray(kmf.mo_energy)).max(), 0 , 7)
 
         fock_ibz = kmf.get_fock()[kpts.ibz2bz]
         fock_bz = kpts.transform_fock(fock_ibz)
-        self.assertAlmostEqual(abs(fock_bz - kmf.get_fock()).max(), 0, 9)
+        self.assertAlmostEqual(abs(fock_bz - kmf.get_fock()).max(), 0, 7)
 
         kumf = kmf.to_uhf()
         mo_coeff_ibz = np.asarray(kumf.mo_coeff)[:,kpts.ibz2bz]
         mo_coeff_bz = kpts.transform_mo_coeff(mo_coeff_ibz)
         dms_bz = kuhf.make_rdm1(mo_coeff_bz, kumf.mo_occ)
-        self.assertAlmostEqual(abs(dms_bz - kumf.make_rdm1()).max(), 0, 9)
+        self.assertAlmostEqual(abs(dms_bz - kumf.make_rdm1()).max(), 0, 7)
 
         mo_occ_ibz = np.asarray(kumf.mo_occ)[:,kpts.ibz2bz]
         mo_occ_bz = kpts.transform_mo_occ(mo_occ_ibz)
@@ -122,11 +123,11 @@ def test_transform(self):
 
         mo_energy_ibz = np.asarray(kumf.mo_energy)[:,kpts.ibz2bz]
         mo_energy_bz = kpts.transform_mo_energy(mo_energy_ibz)
-        self.assertAlmostEqual(abs(mo_energy_bz - np.asarray(kumf.mo_energy)).max(), 0 , 9)
+        self.assertAlmostEqual(abs(mo_energy_bz - np.asarray(kumf.mo_energy)).max(), 0 , 7)
 
         fock_ibz = kumf.get_fock()[:,kpts.ibz2bz]
         fock_bz = kpts.transform_fock(fock_ibz)
-        self.assertAlmostEqual(abs(fock_bz - kumf.get_fock()).max(), 0, 9)
+        self.assertAlmostEqual(abs(fock_bz - kumf.get_fock()).max(), 0, 7)
 
     def test_symmetrize_density(self):
         rho0 = kmf.get_rho()