Repository: pyscf/pyscf — pull request #1943 (python)
Title: Fix decontract_basis function when basis are missed on certain atoms. (Fix #1711)


Resolved issues:
title: Choice of basis sets for multi-grid density fitting (NaCl)
body: Hi all,

Can someone please shed some light on why this simple test crashes? This is pretty much based on `examples/pbc/27-multigrid.py`, but I might easily still be doing something very stupid.

```
#!/usr/bin/env python

import numpy as np
from pyscf.pbc import df, dft, gto
from pyscf.pbc.dft import multigrid

cell = gto.Cell()
cell.atom = 'Cl 0 0 1; Na 0 1 0'
cell.a = np.eye(3) * 4.
cell.basis = 'gth-dzvp'
cell.pseudo = 'gth-pbe'
cell.verbose = 4
cell.build()

mf = dft.KRKS(cell)
mf.xc = 'pbe'
mf.with_df = multigrid.MultiGridFFTDF(cell)
mf.verbose = 4
mf.kernel()
```

I'm getting the following traceback:

```
******** PBC SCF flags ********
N kpts = 1
Exchange divergence treatment (exxdiv) = ewald
    madelung (= occupied orbital energy shift) = 0.3753582916854765
    Total energy shift due to Ewald probe charge = -1/2 * Nelec*madelung = -3.00286633348
DF object = <pyscf.pbc.dft.multigrid.MultiGridFFTDF object at 0x19f261b50>
XC functionals = pbe
small_rho_cutoff = 1e-07
Uniform grid, mesh = [113 113 113]
<class 'pyscf.pbc.dft.krks.KRKS'> does not have attributes  nlcgrids nlc
Set gradient conv threshold to 0.000316228
Traceback (most recent call last):
  File "/Users/janus/calculations/pyscf/pbc/test_multigrid.py", line 19, in <module>
    mf.kernel()
  File "<string>", line 2, in kernel
  File "/Users/janus/programs/pyscf/pyscf/scf/hf.py", line 1691, in scf
    kernel(self, self.conv_tol, self.conv_tol_grad,
  File "/Users/janus/programs/pyscf/pyscf/scf/hf.py", line 127, in kernel
    h1e = mf.get_hcore(mol)
  File "/Users/janus/programs/pyscf/pyscf/pbc/scf/khf.py", line 99, in get_hcore
    nuc = lib.asarray(mf.with_df.get_pp(kpts))
  File "/Users/janus/programs/pyscf/pyscf/pbc/dft/multigrid.py", line 385, in get_pp
    vpp = _get_j_pass2(mydf, vpplocG, hermi, kpts_lst)[0]
  File "/Users/janus/programs/pyscf/pyscf/pbc/dft/multigrid.py", line 856, in _get_j_pass2
    t_cell, coeff = t_cell.to_uncontracted_cartesian_basis()
  File "/Users/janus/programs/pyscf/pyscf/gto/mole.py", line 559, in to_uncontracted_cartesian_basis
    return decontract_basis(mol, to_cart=True)
  File "/Users/janus/programs/pyscf/pyscf/gto/mole.py", line 634, in decontract_basis
    lmax = mol._bas[ib0:ib1,ANG_OF].max()
  File "/Users/janus/anaconda3/envs/my-rdkit-env/lib/python3.9/site-packages/numpy/core/_methods.py", line 39, in _amax
    return umr_maximum(a, axis, None, out, keepdims, initial, where)
ValueError: zero-size array to reduction operation maximum which has no identity
```

HEAD is at 6eb7542afc713 from yesterday. Thanks in advance.

Hints:

Fix patch:
diff --git a/pyscf/gto/mole.py b/pyscf/gto/mole.py
index 49f7fe9f34..636322d4c3 100644
--- a/pyscf/gto/mole.py
+++ b/pyscf/gto/mole.py
@@ -626,6 +626,9 @@ def _to_full_contraction(mol, bas_idx):
 
     aoslices = mol.aoslice_by_atom()
     for ia, (ib0, ib1) in enumerate(aoslices[:,:2]):
+        if ib0 == ib1: # No basis on atom ia
+            continue
+
         if atoms is not None:
             if isinstance(atoms, str):
                 to_apply = ((atoms == mol.atom_pure_symbol(ia)) or


Test patch:
diff --git a/pyscf/gto/test/test_mole.py b/pyscf/gto/test/test_mole.py
index 4adaa7e32a..1a91682db0 100644
--- a/pyscf/gto/test/test_mole.py
+++ b/pyscf/gto/test/test_mole.py
@@ -1033,6 +1033,11 @@ 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)
 
+        # discard basis on atom 2. (related to issue #1711)
+        mol._bas = mol._bas[:5]
+        pmol, c = mol.decontract_basis()
+        self.assertEqual(pmol.nbas, 14)
+
         mol = gto.M(atom='He',
                     basis=('ccpvdz', [[0, [5, 1]], [1, [3, 1]]]))
         pmol, contr_coeff = mol.decontract_basis()