Repository: pyscf/pyscf — pull request #1620 (python)
Title: Fix Mole.decontract_basis method (Fix issue #1609)


Resolved issues:
title: Issue with x2c and using cc-pCVXZ basis sets in at least PySCF 1.7.6 and newer
body: Hi all,

I've come across what I believe to be a bug when trying to run a relativistic exact two-component PySCF calculation using a core-valence correlation consistent basis set (cc-pCVDZ) at the SCF/mean-field level. I have included two input files that do (c6h4_load.py) and do not (c6h4_parse.py) have the bug I describe below:

When running a calculation in which I request to use the cc-pCVDZ basis set, the output file lists the correct number of primitive GTOs, and the initial energy in the SCF procedure is reasonable (approx. -230 a.u.), but then the first step of the SCF cycle has an energy that is two orders of magnitude greater (approx. -50000 a.u.) and the SCF procedure does not converge.

The issue only occurs if I load the cc-pCVDZ basis set as it is defined within PySCF. Two actions fix this problem:
1) Switching to the non-core-valence variant (cc-pCVDZ -> cc-pVDZ); SCF converges normally without any complications.

2) If I manually specify the SAME cc-pCVDZ basis set and use the 'parse' function from the 'gto' module, the same exact x2c mean-field calculation no longer produces these massive energy errors in the SCF energy and convergence is smooth and quick.

The exact same input files provided below, run in PySCF 1.5.3 (compiled) and PySCF 1.6.2 (compiled), DO NOT have this issue. So it seems like something that could have been introduced around version 1.7?

The versions of PySCF I have found to be displaying this behavior:
PySCF 1.7.6 (conda)
PySCF 2.0.0a (compiled)
PySCF 2.0.1 (conda)
PySCF 2.1.1 (conda)
PySCF 2.1.1 (compiled)
PySCF 2.1.1 (compiled w/ OMP_NUM_THREADS=1)

Please let me know if you need any additional info from me! Thanks in advance.

Best,
Ilia Mazin

[x2c_basis_set_test.zip](https://github.com/pyscf/pyscf/files/10818364/x2c_basis_set_test.zip)


Hints:

Fix patch:
diff --git a/pyscf/gto/mole.py b/pyscf/gto/mole.py
index 09253d2a59..6eff5b8a4f 100644
--- a/pyscf/gto/mole.py
+++ b/pyscf/gto/mole.py
@@ -916,11 +916,15 @@ def make_atm_env(atom, ptr=0, nuclear_model=NUC_POINT, nucprop={}):
 def make_bas_env(basis_add, atom_id=0, ptr=0):
     '''Convert :attr:`Mole.basis` to the argument ``bas`` for ``libcint`` integrals
     '''
+    # First sort basis accroding to l. This is important for method
+    # decontract_basis, which assumes that basis functions with the same angular
+    # momentum are grouped together
+    basis_add = [b for b in basis_add if b]
+    basis_add = sorted(basis_add, key=lambda b: b[0])
+
     _bas = []
     _env = []
     for b in basis_add:
-        if not b:  # == []
-            continue
         angl = b[0]
         if angl > 14:
             sys.stderr.write('Warning: integral library does not support basis '


Test patch:
diff --git a/pyscf/gto/test/test_mole.py b/pyscf/gto/test/test_mole.py
index c42151c697..294233e168 100644
--- a/pyscf/gto/test/test_mole.py
+++ b/pyscf/gto/test/test_mole.py
@@ -1034,6 +1034,13 @@ def test_decontract_basis(self):
         s = ctr_coeff.T.dot(pmol.intor('int1e_ovlp')).dot(ctr_coeff)
         self.assertAlmostEqual(abs(s - mol.intor('int1e_ovlp')).max(), 0, 12)
 
+        mol = gto.M(atom='He',
+                    basis=('ccpvdz', [[0, [5, 1]], [1, [3, 1]]]))
+        pmol, contr_coeff = mol.decontract_basis()
+        contr_coeff = scipy.linalg.block_diag(*contr_coeff)
+        s = contr_coeff.T.dot(pmol.intor('int1e_ovlp')).dot(contr_coeff)
+        self.assertAlmostEqual(abs(s - mol.intor('int1e_ovlp')).max(), 0, 12)
+
     def test_ao_rotation_matrix(self):
         mol = gto.M(atom='O 0 0 0.2; H1 0 -.8 -.5; H2 0 .8 -.5', basis='ccpvdz')
         numpy.random.seed(1)