sunqm / libcint

general GTO integrals for quantum chemistry

Home Page:wiki.sunqm.net/libcint

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Normalized (cartesian) overlap integrals

davidsousarj opened this issue · comments

Hi. I am trying to understand the logic behind the way libcint calculates overlap integrals.

For example, I am using as test the water molecule in the cc-pVDZ basis (coordinates in Bohr below):

O           0.0 0.0          0.0
H  1.5152616654 0.0 1.0498977437
H -1.5152616654 0.0 1.0498977437

I modified the example file to calculate all overlap integrals, and I find it surprising that some diagonal elements (specifically those of the d functions) are not equal to 1.0.

Then I run a test in PySCF to see if I did something wrong, but I got the exact same result:

>>> import pyscf
>>> h2o="""O    0.000000    0.000000    0.000000
>>> H   1.515262    0.000000    1.049898
>>> H  -1.515262    0.000000    1.049898"""
>>> m = pyscf.M(atom=h2o, unit="bohr", basis="ccpvdz", cart=True)
>>> S=pyscf.gto.getints('int1e_ovlp_cart', m._atm, m._bas, m._env)
>>> import numpy
>>> numpy.diag(S)
array([1.        , 1.        , 1.        , 1.        , 1.        ,
       1.        , 1.        , 1.        , 1.        , 2.51327412,
       0.83775804, 0.83775804, 2.51327412, 0.83775804, 2.51327412,
       1.        , 1.        , 1.        , 1.        , 1.        ,
       1.        , 1.        , 1.        , 1.        , 1.        ])

After some research in the web I found some PySCF code which gives the correctly normalized integrals. It firstly runs a SCF calculation and then project the overlap integrals in the basis of the converged SCF orbitals.

...
>>> hf = m.RHF()
>>> hf.kernel()
converged SCF energy = -76.0243517047874
-76.02435170478736
>>> scf_c = hf.mo_coeff
>>> nuclear_repulsion = m.energy_nuc()
>>> constant = nuclear_repulsion
>>> S = scf_c.T @ S @ scf_c
>>> numpy.diag(S)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1.])

source

I would like to know whether libcint is able to generate the properly normalized integrals without the need of running a SCF calculation. The old method for integrals in my program is able to do so, but it is a very old and cryptic Fortran-77 code and it is limited only to s, p and d functions (this is why I want to use libcint).

scf_c.T @ S @ scf_c is the MO overlap, so not surprisingly it is normalized. It's not the AO overlap.

For AO overlap, if you use spheric integral instead of cartesian, you will get the desired 1.0 diagonal. For some reason Libcint's cartesian integral may have different normalization convention from other programs.

For AO overlap, if you use spheric integral instead of cartesian, you will get the desired 1.0 diagonal.

I realized that after I opened the issue.

For some reason Libcint's cartesian integral may have different normalization convention from other programs.

It seems libcint works with spherical harmonics by default, so the overlap integrals will be normalized if calculated as spherical harmonics, but not if calculated as cartesian. Unfortunately my program works with cartesian functions by default.

It seems I might have two options: either forking the libcint code to change the normalization convention (which I didn't want to, I was hoping to use an already ready-to-use package), or looking for some other integral library.

I hope to hear for the developers whether it is really the case.

Well, the cartesian integral provided by libcint does not prevent you building a program on it, as the PySCF developers do. Maybe those diagonals look weird but it's ok to use those integrals to produce some results comparable with your old program, like energy.
The MO coefficients will be not comparable. But you can do a transformation, i.e. dividing each row of MO by a factor, to achieve that.

I will close this issue as hebrewsnabla' suggestion should work for most scenarios.