PR - [9] Bind 3-center 2-electron integrals, add cartesian support via macro type parameter - #257
PR - [9] Bind 3-center 2-electron integrals, add cartesian support via macro type parameter #257San1357 wants to merge 62 commits into
Conversation
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
PR[1]: build: migrate from setuptools to scikit-build-core
PR[2] : feat: add libcint C extension bindings for various integrals
PR[3]: feat: use PyArray_GETPTR instead of PyLong_AsVoidPtr + fix dylib rpath
PR[4]: fix: platform-aware libcint loading + moment integral libcint v6 fix
PR-5 - feat: add C shell loop for all 1-electron integrals
…clear, gradient_rinv
…als, coord_type aware calls, PySCF reference tests
msricher
left a comment
There was a problem hiding this comment.
Great, thanks for also adding the automatic selection of (cart|sph) at runtime.
There was a problem hiding this comment.
Pull request overview
This PR introduces a Python C-extension (libcint_bindings) to accelerate/extend libcint-backed integral evaluation (including new 3-center 2-electron integrals), refactors macro-based generation for spherical/cartesian variants, and updates packaging/build tooling to use a CMake/scikit-build-core workflow.
Changes:
- Added a new C-extension wrapper (
gbasis/integrals/src/libcint_wrap.c) exposing shell-loop integral array builders (plusint3c2e_sph). - Extended
gbasis.integrals.libcint.CBasiswith new C-backed shell-loop methods (andthree_center_two_electron()), including runtime_sph/_cartselection via a suffix. - Updated tests and build configuration (pyproject + CI) to support the new build and validate new bindings.
Reviewed changes
Copilot reviewed 6 out of 10 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
tests/test_libcint.py |
Expands libcint test coverage to include new C shell-loop bindings and 3c2e reference comparisons. |
pyproject.toml |
Switches build backend to scikit-build-core and updates dependency minimums. |
gbasis/integrals/src/libcint_wrap.c |
Adds the C-extension module implementing array builders and new integral bindings. |
gbasis/integrals/libcint.py |
Wires the new extension into CBasis and adds higher-level Python methods for new bindings. |
CMakeLists.txt |
Defines the CMake build for the extension and fetches/builds libcint/qcint. |
.github/workflows/pytest.yaml |
Updates minimal dependency pins used in CI (numpy/scipy). |
Comments suppressed due to low confidence (3)
gbasis/integrals/libcint.py:234
- The ctypes loader hard-codes a platform-specific
libcintfilename undergbasis/integrals/lib(e.g.libcint.soon Linux). With this PR switching to a CMake/scikit-build-core build that installslibcint_bindingsintogbasis/integrals/lib, it’s easy to end up with the extension present but nolibcint.*shared library at the expected path (and/or a different SONAME likelibcint.so.6). That will makegbasis.integrals.libcintfail to import when_LibCIntis used (sinceLIBCINTis instantiated at import time). Please ensure the build/install step also installs a compatiblelibcintshared library and the expected filename/symlink intogbasis/integrals/lib, or refactor so the ctypes path is optional/lazy whenlibcint.*is absent.
elif _system == "Windows":
_lib_name = "libcint.dll"
else:
_lib_name = "libcint.so"
_libcint: CDLL = cdll.LoadLibrary(str(_lib_dir / _lib_name))
CMakeLists.txt:55
INSTALL_RPATHis set to@loader_pathunconditionally.@loader_pathis a macOS-specific placeholder; on Linux this value is not meaningful and can lead to runtime loader issues (especially ifcintis built/linked as a shared library). Consider setting RPATH conditionally (Darwin:@loader_path, Linux:$ORIGIN).
# Set RPATH so libcint.dylib is found at runtime.
INSTALL_RPATH "@loader_path"
BUILD_WITH_INSTALL_RPATH TRUE)
CMakeLists.txt:67
- Only the Python extension module is installed into
gbasis/integrals/lib, but the Python ctypes path (_LibCInt) still expects a loadablelibcint.*shared library under the same directory. Ifcintis built as a shared library, it should also be installed next to the extension so runtime loading works; if it’s built statically, the ctypes path likely needs to be removed/disabled (since there won’t be alibcint.*to load).
# Install C extension module.
set(GBASIS_WHEEL_DIRECTORY "${SKBUILD_PLATLIB_DIR}/gbasis/integrals/lib")
install(TARGETS gbasis_ext LIBRARY DESTINATION ${GBASIS_WHEEL_DIRECTORY})
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # to Remove 1 | ||
| from ctypes import CDLL, POINTER, Structure, cdll, byref, c_int, c_double |
|
|
||
| """ | ||
|
|
||
| from gbasis.integrals.lib import libcint_bindings |
| # both are pinned to v6.1.2 for stability. | ||
| include(CheckCCompilerFlag) | ||
| set(GBASIS_CINT_REPO "https://github.com/sunqm/libcint.git") | ||
| set(GBASIS_CINT_VERSION "v6.1.2") |
| } | ||
| } | ||
| } | ||
| memset(buf, 0, buf_size * sizeof(double)); |
| } | ||
| } | ||
| } | ||
| memset(buf, 0, buf_size * sizeof(double)); |
…e three_center_two_electron
…anual libcint install
| install(TARGETS gbasis_ext LIBRARY DESTINATION ${GBASIS_WHEEL_DIRECTORY}) | ||
|
|
||
|
|
||
| # Install libcint/qcint shared library alongside the extension module. |
There was a problem hiding this comment.
You shouldn't have to do this! Last time we edited the CMakeLists.txt, we made libcint a static library that is compiled directly into the extension module.
Changes
3-center 2-electron integrals
int3c2e_sphinlibcint_wrap.cusing 3 nested shell loops withshls[3] = 0three_center_two_electron()toCBasiswith transform support.npyfiles for He, C, H+He, Be+C systems (STO-6G)Macro refactor
DEFINE_INT1E_ARRAY_FN,DEFINE_INT1E_LOOP_FN, andDEFINE_INT1E_LOOP_FN_OPTto accept atypeparameter via token pasting_sphand_cartvariants now generated from the same macro callDEFINE_INT1E_ARRAY_FN(overlap, sph, int1e_ovlp)→ generatesoverlap_sphcoord_type aware C bindings
_sphor_cartbased oncoord_typeat runtimeTests
572 passed, 4 skipped
Still in progress
int3c2e_cartbinding and cartesian reference teststest_c_shellloop_integralmake_int1e,make_int2e, old*_integral()wrappers)