Repository: pyscf/pyscf — pull request #2371 (python)
Title: Fix SGX initialization issue

 fix #2065

Resolved issues:
title: SGX Fails When PJS=True
body: This is benzene, HF/def2-SVP - 

```
import pyscf

xyz = """C                 -0.71618036    2.71883299    0.00000000
C                  0.67897964    2.71883299    0.00000000
C                  1.37651764    3.92658399    0.00000000
C                  0.67886364    5.13509299   -0.00119900
C                 -0.71596136    5.13501499   -0.00167800
C                 -1.41356236    3.92680899   -0.00068200
H                 -1.26593936    1.76651599    0.00045000
H                  1.22848764    1.76631999    0.00131500
H                  2.47619764    3.92666399    0.00063400
H                  1.22906364    6.08723599   -0.00125800
H                 -1.26608336    6.08729599   -0.00263100
H                 -2.51316636    3.92699199   -0.00086200"""


mol = pyscf.M(
    atom=xyz,
    basis="def2-SVP",
    charge=0,
    spin=0,
    symmetry=True
)

mf = pyscf.scf.HF(mol)

mf = pyscf.sgx.sgx_fit(mf, pjs=True)

energy = mf.kernel()
```

And here's what I get:

```
Traceback (most recent call last):
  File "/Users/cwagen/business_code/pyscf/sgx_fail.py", line 32, in <module>
    energy = mf.kernel()
             ^^^^^^^^^^^
  File "<string>", line 2, in kernel
  File "/opt/miniconda3/envs/aimnet2/lib/python3.11/site-packages/pyscf/scf/hf.py", line 1713, in scf
    self.build(self.mol)
  File "/opt/miniconda3/envs/aimnet2/lib/python3.11/site-packages/pyscf/sgx/sgx.py", line 141, in build
    self.with_df.build(level=self.with_df.grids_level_i)
  File "/opt/miniconda3/envs/aimnet2/lib/python3.11/site-packages/pyscf/sgx/sgx.py", line 316, in build
    self._opt = _make_opt(self.mol, pjs=self.pjs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/miniconda3/envs/aimnet2/lib/python3.11/site-packages/pyscf/sgx/sgx.py", line 239, in _make_opt
    vhfopt = _vhf.SGXOpt(mol, 'int1e_grids', 'SGXnr_ovlp_prescreen',
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: SGXOpt.__init__() got an unexpected keyword argument 'direct_scf_tol'
```

This works fine when PJS = False. 

Hints:

Fix patch:
diff --git a/pyscf/scf/_vhf.py b/pyscf/scf/_vhf.py
index 7b51aa5921..313407a957 100644
--- a/pyscf/scf/_vhf.py
+++ b/pyscf/scf/_vhf.py
@@ -79,10 +79,10 @@ def init_cvhf_direct(self, mol, intor, qcondname):
 
     @property
     def direct_scf_tol(self):
-        return self._this.contents.direct_scf_cutoff
+        return self._this.contents.direct_scf_tol
     @direct_scf_tol.setter
     def direct_scf_tol(self, v):
-        self._this.contents.direct_scf_cutoff = v
+        self._this.contents.direct_scf_tol = v
 
     @property
     def prescreen(self):
@@ -162,7 +162,7 @@ def __init__(self, mol, intor=None, prescreen='CVHFnoscreen',
         self.mol = mol
         self._this = cvhfopt = _CVHFOpt()
         cvhfopt.nbas = mol.nbas
-        cvhfopt.direct_scf_cutoff = direct_scf_tol
+        cvhfopt.direct_scf_tol = direct_scf_tol
         cvhfopt.fprescreen = _fpointer(prescreen)
         cvhfopt.r_vkscreen = _fpointer('CVHFr_vknoscreen')
         self._q_cond = None
@@ -207,10 +207,10 @@ def init_cvhf_direct(self, mol, intor, qcondname):
 
     @property
     def direct_scf_tol(self):
-        return self._this.direct_scf_cutoff
+        return self._this.direct_scf_tol
     @direct_scf_tol.setter
     def direct_scf_tol(self, v):
-        self._this.direct_scf_cutoff = v
+        self._this.direct_scf_tol = v
 
     @property
     def prescreen(self):
@@ -265,9 +265,9 @@ def dm_cond(self, dm_cond):
 
 class SGXOpt(_VHFOpt):
     def __init__(self, mol, intor=None, prescreen='CVHFnoscreen',
-                 qcondname=None, dmcondname=None, direct_scf_cutoff=1e-14):
+                 qcondname=None, dmcondname=None, direct_scf_tol=1e-14):
         _VHFOpt.__init__(self, mol, intor, prescreen, qcondname, dmcondname,
-                         direct_scf_cutoff)
+                         direct_scf_tol)
         self.ngrids = None
 
     def set_dm(self, dm, atm, bas, env):
@@ -287,18 +287,22 @@ def set_dm(self, dm, atm, bas, env):
             if self._dmcondname != 'SGXnr_dm_cond':
                 raise ValueError('SGXOpt only supports SGXnr_dm_cond')
             fdmcond = getattr(libcvhf, self._dmcondname)
-        dm_cond = numpy.empty((mol.nbas, self.ngrids))
+        if self.ngrids is None:
+            ngrids = int(env[gto.NGRIDS])
+        else:
+            ngrids = self.ngrids
+        dm_cond = numpy.empty((mol.nbas, ngrids))
         fdmcond(dm_cond.ctypes, dm.ctypes, ctypes.c_int(n_dm),
                 ao_loc.ctypes, mol._atm.ctypes, ctypes.c_int(mol.natm),
                 mol._bas.ctypes, ctypes.c_int(mol.nbas), mol._env.ctypes,
-                ctypes.c_int(self.ngrids))
+                ctypes.c_int(ngrids))
         self.dm_cond = dm_cond
 
 
 class _CVHFOpt(ctypes.Structure):
     _fields_ = [('nbas', ctypes.c_int),
                 ('ngrids', ctypes.c_int),
-                ('direct_scf_cutoff', ctypes.c_double),
+                ('direct_scf_tol', ctypes.c_double),
                 ('q_cond', ctypes.c_void_p),
                 ('dm_cond', ctypes.c_void_p),
                 ('fprescreen', ctypes.c_void_p),


Test patch:
diff --git a/pyscf/sgx/test/test_sgx.py b/pyscf/sgx/test/test_sgx.py
index bcf8fab256..b373fc2f19 100644
--- a/pyscf/sgx/test/test_sgx.py
+++ b/pyscf/sgx/test/test_sgx.py
@@ -39,11 +39,28 @@ def test_sgx_scf(self):
                     [1   , (0. , 0.757  , 0.587)] ],
             basis = 'ccpvdz',
         )
-        method = sgx.sgx_fit(scf.RHF(mol), 'weigend')
-        method.with_df.dfj = True
-        energy = method.scf()
+        mf = sgx.sgx_fit(scf.RHF(mol), 'weigend')
+        mf.with_df.dfj = True
+        energy = mf.kernel()
         self.assertAlmostEqual(energy, -76.02686422219752, 9)
 
+        mf = sgx.sgx_fit(scf.RHF(mol))
+        energy = mf.kernel()
+        self.assertAlmostEqual(energy, -76.02673747035047, 8)
+
+    def test_sgx_pjs(self):
+        mol = gto.Mole()
+        mol.build(
+            atom = [["O" , (0. , 0.     , 0.)],
+                    [1   , (0. , -0.757 , 0.587)],
+                    [1   , (0. , 0.757  , 0.587)] ],
+            basis = 'ccpvdz',
+        )
+        mf = sgx.sgx_fit(mol.RHF(), pjs=True)
+        mf.with_df.dfj = True
+        energy = mf.kernel()
+        self.assertAlmostEqual(energy, -76.0267979, 6)
+
 if __name__ == "__main__":
     print("Full Tests for SGX")
     unittest.main()