Skip to content

PR-7 — feat: add C shell-loop bindings for point_charge, moment, momentum & tests - #255

Draft
San1357 wants to merge 13 commits into
theochem:san1357-devfrom
San1357:pr-7/tests
Draft

PR-7 — feat: add C shell-loop bindings for point_charge, moment, momentum & tests#255
San1357 wants to merge 13 commits into
theochem:san1357-devfrom
San1357:pr-7/tests

Conversation

@San1357

@San1357 San1357 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Added C shell-loop binding for point_charge() — uses rinv_integral_shellloop internally per charge ~13x speedup
  • Added C shell-loop binding for moment() — uses _moments dict internally
  • Updated momentum() to return full 3-component complex array (now matches momentum_integral())

New Tests (test_libcint.py)

  • test_c_shellloop_integral — tests all C shell-loop methods against GBasis Python implementations:
    • overlap, kinetic_energy, nuclear_attraction, rinv, dipole, quadrupole, octupole, point_charge, moment, electron_repulsion
  • test_c_shellloop_matches_make_int1e — cross-checks C shell-loop directly against make_int1e/make_int2e on same CBasis instance

Related

Test verifications:

pytest tests/test_libcint.py -v
Screenshot 2026-07-02 at 9 00 56 AM

@San1357
San1357 requested a review from msricher June 27, 2026 00:07
@San1357 San1357 changed the title PR-7 — feat: add point_charge, moment, momentum (C shell-loop bindings) and test cases PR-7 — feat: add C shell-loop bindings for point_charge, moment, momentum & tests Jul 2, 2026

@msricher msricher left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, just see comments.

Comment on lines -110 to +102
DEFINE_INTEGRAL_INT1e(octupole_sph, int1e_rrr_sph)
DEFINE_INT1E_ARRAY_FN(overlap_sph, int1e_ovlp_sph)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep the name INT1E_ARRAY consistently across files instead of INT1E_SHELLOOP? Names should generally be descriptive of their purpose rather than their implementation details.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread gbasis/integrals/src/libcint_wrap.c Outdated
int *offs = (int *) PyArray_GETPTR1(offs_arr, 0);

int shls[4];
double buf[100000] = {0};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allocate this array dynamically, with whatever size you need, which you can calculate.

Instead of

double buf[1000000] = {0};
/* do work... */

have something like this:

#include <stdlib.h>;
/* ... */;
double *buf = calloc(CALCULATED_SIZE, sizeof(double));
/* do work... */;
free(buf);
return WHATEVER;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the gbasis.integrals.libcint.CBasis API with additional high-level methods and C-backed shell-loop implementations, and expands the test suite to validate the new C shell-loop pathways against existing GBasis and libcint-based reference implementations.

Changes:

  • Added new CBasis convenience methods (point_charge, moment, electron_repulsion) and updated momentum() to return the full 3-component complex result consistent with momentum_integral().
  • Added a new C extension entry point eri_shellloop for 2-electron ERI shell-loop evaluation.
  • Expanded tests/test_libcint.py with new C shell-loop correctness tests and broadened shared-library discovery.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
tests/test_libcint.py Adds new parametrized tests covering C shell-loop methods and updates shared-library detection globbing.
gbasis/integrals/src/libcint_wrap.c Introduces eri_shellloop and renames/extends C macro wrappers for libcint bindings.
gbasis/integrals/libcint.py Adds/updates CBasis methods (momentum, point_charge, moment, electron_repulsion) to expose the new functionality from Python.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gbasis/integrals/src/libcint_wrap.c Outdated
Comment on lines +255 to +257
shls[3] = lshl;
int s_off = offs[lshl];
int2e_sph(buf, NULL, shls, atm, natm, bas, nbas, env, NULL, NULL);
Comment on lines +1336 to +1347
out = np.zeros((self.nbfn, self.nbfn, len(point_charges)), dtype=c_double, order='F')
for icharge, (coord, charge) in enumerate(zip(point_coords, point_charges)):
# Set inv_origin in env for this charge
self.env[4:7] = coord
val = np.zeros((self.nbfn, self.nbfn), dtype=c_double, order='F')
libcint_bindings.rinv_integral_shellloop(
val, self.natm, self.atm, self.nbas,
self.bas, self.env, self._offs, self.nbfn
)
val *= -charge
out[:, :, icharge] = val
return out
Comment on lines +1375 to +1384
if origin is None:
origin = np.zeros(3)
out = np.zeros((self.nbfn, self.nbfn, len(orders)), dtype=np.float64)
for i, order in enumerate(orders):
self.env[1:4] = origin
if sum(order) == 0:
out[:, :, i] = self.overlap()
else:
out[:, :, i] = self._moments[tuple(order)](origin=origin)
return out
Comment on lines +1369 to +1373
Notes
-----
Uses the C shell-loop bindings for dipole, quadrupole, and octupole
integrals internally. Supports up to 3rd order moments.

Comment on lines +1403 to +1408
out = np.zeros((self.nbfn, self.nbfn, self.nbfn, self.nbfn), dtype=c_double)
libcint_bindings.eri_shellloop(
out, self.natm, self.atm, self.nbas,
self.bas, self.env, self._offs, self.nbfn
)
return out
Comment on lines +1390 to +1396
The two-electron repulsion integral between basis functions
:math:`\phi_i`, :math:`\phi_j`, :math:`\phi_k`, and :math:`\phi_l`
is defined as:

.. math::
g_{ijkl} = \langle \phi_i \phi_j | \frac{1}{r_{12}} | \phi_k \phi_l \rangle

Comment thread tests/test_libcint.py
sides here come from libcint.

"""
from gbasis.integrals.libcint import ELEMENTS, CBasis
Comment thread tests/test_libcint.py
Comment on lines +553 to +559
# 2-electron ERI: C shell-loop vs. make_int2e shell-loop
npt.assert_allclose(
lc_basis.electron_repulsion(),
lc_basis.electron_repulsion_integral(),
atol=1e-8,
rtol=1e-8,
)
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

Successfully merging this pull request may close these issues.

3 participants