Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Primitive integrals/contraction coefficients #101

Open
maxscheurer opened this issue Sep 17, 2023 · 2 comments
Open

Primitive integrals/contraction coefficients #101

maxscheurer opened this issue Sep 17, 2023 · 2 comments

Comments

@maxscheurer
Copy link

maxscheurer commented Sep 17, 2023

Hi,
I'm currently experimenting with some integrals for implementing GOSTSHYP in pyscf.
For that, I need to build a custom "fakemol" and basis set, so I've been using pyscf's fakemol_for_charges to do the setup. The reason for this is that these special basis functions are not normalized.

Along the way, I've been wondering which integrals libcint actually computes under the hood, so I've tried to "manually" compute the overlap of a primitive s-function with itself, with exponent of one, contraction coefficient of one, centered at the origin.

I was wondering why the result from libcint is not identical to what I get with sympy? What am I forgetting/missing here?

import numpy as np
from pyscf import gto
from sympy import symbols, exp, integrate, oo, N


def fakemol_with_exponents(coords, exponents):
    nbas = coords.shape[0]

    fakeatm = np.zeros((nbas, gto.mole.ATM_SLOTS), dtype=np.int32)
    fakebas = np.zeros((nbas, gto.mole.BAS_SLOTS), dtype=np.int32)
    fakeenv = [0] * gto.mole.PTR_ENV_START
    ptr = gto.mole.PTR_ENV_START
    fakeatm[:, gto.mole.PTR_COORD] = np.arange(ptr, ptr + nbas * 3, 3)
    fakeenv.append(coords.ravel())
    ptr += nbas * 3
    fakebas[:, gto.mole.ATOM_OF] = np.arange(nbas)
    fakebas[:, gto.mole.NPRIM_OF] = 1
    fakebas[:, gto.mole.NCTR_OF] = 1
    # approximate point charge with gaussian distribution exp(-expnt*r^2)
    fakebas[:, gto.mole.PTR_EXP] = ptr + np.arange(nbas) * 2
    fakebas[:, gto.mole.PTR_COEFF] = ptr + np.arange(nbas) * 2 + 1
    coeff = np.ones_like(exponents)  # / (2 * np.sqrt(np.pi) * gaussian_int(2, expnt))
    fakeenv.append(np.vstack((exponents, coeff)).T.ravel())

    fakemol = gto.Mole()
    fakemol._atm = fakeatm
    fakemol._bas = fakebas
    fakemol._env = np.hstack(fakeenv)
    fakemol._built = True
    return fakemol


gmol2 = fakemol_with_exponents(
    np.array(
        [
            [0, 0, 0],
        ]
    ),
    np.array([1.0]),
)
print(gmol2.intor("int1e_ovlp")[0, 0])

x, y, z = symbols("x, y, z")
ref = integrate(
    exp(-1.0 * (x ** 2 + y ** 2 + z ** 2)) ** 2, (x, -oo, oo), (y, -oo, oo), (z, -oo, oo)
)
print(N(ref))

Output:

0.15666426716443752
1.96870124321530

Thanks for helping with this (probably stupid) question 😁

@sunqm
Copy link
Owner

sunqm commented Sep 17, 2023

  1. Overlap is defined as the product of two Gaussians. You should compare to
ref = integrate(
    exp(-2.0 * (x ** 2 + y ** 2 + z ** 2)) ** 2, (x, -oo, oo), (y, -oo, oo), (z, -oo, oo)
)
  1. for s-type orbitals, int1e_ovlp includes the normalization factor for angular part 1/4pi

@maxscheurer
Copy link
Author

Thanks, the 1/(4pi) did the trick 👍 Regarding 1., I already had a product of two Gaussians, note the ** 2 after the exp function.
I'll leave this issue open for follow-up questions during my implementation if that's okay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants