PR-[10] - feat: add Windows CI support - #258
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
There was a problem hiding this comment.
Pull request overview
Adds Windows CI, but also substantially rewrites libcint packaging and APIs.
Changes:
- Expands CI across Windows, macOS, and Ubuntu.
- Migrates builds to CMake/scikit-build-core with native bindings.
- Replaces
CBasisintegral APIs and adds extensive tests.
Reviewed changes
Copilot reviewed 7 out of 19 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/pytest.yaml |
Adds platform-specific CI setup and execution. |
CMakeLists.txt |
Builds and packages libcint bindings. |
pyproject.toml |
Migrates packaging to scikit-build-core. |
gbasis/integrals/src/libcint_wrap.c |
Implements native integral wrappers. |
gbasis/integrals/libcint.py |
Reworks the Python libcint API. |
gbasis/evals/_deriv.py |
Adds explicit Hermite argument casting. |
tests/test_libcint.py |
Expands native-binding tests. |
Suppressed comments (3)
gbasis/integrals/src/libcint_wrap.c:480
- The Cartesian gradient bindings have the same component-loss issue as the spherical variants: libcint emits three components, while the scalar macro exposes only component zero. Switch these to a three-component wrapper and propagate that shape through the Python API.
DEFINE_INT1E_LOOP_FN(ipkin_integral_array, cart, int1e_ipkin, int1e_ipkin)
DEFINE_INT1E_LOOP_FN(ipnuc_integral_array, cart, int1e_ipnuc, int1e_ipnuc)
DEFINE_INT1E_LOOP_FN(iprinv_integral_array, cart, int1e_iprinv, int1e_iprinv)
gbasis/integrals/src/libcint_wrap.c:485
- The Cartesian GIAO bindings also route three-component libcint functions through the scalar macro, silently dropping two components. Use the multi-component wrapper and expose the full result in the Cartesian Python methods.
DEFINE_INT1E_LOOP_FN(ia01p_integral_array, cart, int1e_ia01p, int1e_ia01p)
DEFINE_INT1E_LOOP_FN(ircxp_integral_array, cart, int1e_cg_irxp, int1e_cg_irxp)
DEFINE_INT1E_LOOP_FN(igkin_integral_array, cart, int1e_igkin, int1e_igkin)
DEFINE_INT1E_LOOP_FN(igovlp_integral_array, cart, int1e_igovlp, int1e_igovlp)
DEFINE_INT1E_LOOP_FN(ignuc_integral_array, cart, int1e_ignuc, int1e_ignuc)
.github/workflows/pytest.yaml:64
- MSYS2 also treats
>as shell redirection, so the Windows command does not passnumpy>=2.0to pip and writes to=2.0. Quote the requirement string.
pip install numpy>=2.0 setuptools_scm scikit-build-core cmake ninja
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| DEFINE_INT1E_LOOP_FN_OPT(overlap_integral_array, sph, int1e_ovlp, int1e_ovlp) | ||
| DEFINE_INT1E_LOOP_FN_OPT(kinetic_integral_array, sph, int1e_kin, int1e_kin) | ||
| DEFINE_INT1E_LOOP_FN_OPT(nuclear_integral_array, sph, int1e_nuc, int1e_nuc) | ||
| DEFINE_INT1E_LOOP_FN_MULTICOMP(momentum_integral_array, sph, int1e_ipovlp, int1e_ipovlp, 3) |
| DEFINE_INT1E_LOOP_FN(ipkin_integral_array, sph, int1e_ipkin, int1e_ipkin) | ||
| DEFINE_INT1E_LOOP_FN(ipnuc_integral_array, sph, int1e_ipnuc, int1e_ipnuc) | ||
| DEFINE_INT1E_LOOP_FN(iprinv_integral_array, sph, int1e_iprinv, int1e_iprinv) |
| DEFINE_INT1E_LOOP_FN(ia01p_integral_array, sph, int1e_ia01p, int1e_ia01p) | ||
| DEFINE_INT1E_LOOP_FN(ircxp_integral_array, sph, int1e_cg_irxp, int1e_cg_irxp) | ||
| DEFINE_INT1E_LOOP_FN(igkin_integral_array, sph, int1e_igkin, int1e_igkin) | ||
| DEFINE_INT1E_LOOP_FN(igovlp_integral_array, sph, int1e_igovlp, int1e_igovlp) | ||
| DEFINE_INT1E_LOOP_FN(ignuc_integral_array, sph, int1e_ignuc, int1e_ignuc) |
| self._ovlp_minhalf = None | ||
|
|
||
|
|
||
| def overlap(self, transform=None): |
| # Apply permutation | ||
| out = out[self._permutations, :][:, self._permutations] | ||
| # Apply permutation | ||
| out = out[self._permutations, :][:, self._permutations] |
| # Force MinGW compiler on Windows before project() declaration | ||
| if(WIN32) | ||
| set(CMAKE_C_COMPILER "gcc" CACHE STRING "" FORCE) | ||
| set(CMAKE_CXX_COMPILER "g++" CACHE STRING "" FORCE) | ||
| endif() |
| - name: Install development version (non-Windows) | ||
| if: ${{ runner.os != 'Windows' }} | ||
| run: | | ||
| pip install numpy>=2.0 setuptools_scm scikit-build-core cmake ninja |
| /* | ||
| * libcint_wrap.c — Python/C API bindings for libcint GTO integral library. | ||
| * |
| if integral == "gradient_kinetic": | ||
| # Compare C shell-loop against make_int1e path on same CBasis instance | ||
| lc_int = lc_basis.gradient_kinetic() | ||
| npt.assert_array_equal(lc_int.shape, (lc_basis.nbfn, lc_basis.nbfn)) | ||
| assert np.all(np.isfinite(lc_int)) |
|
|
||
| extern int int3c2e_sph(double *out, int *dims, int *shls, int *atm, int natm, | ||
| int *bas, int nbas, double *env, void *opt, double *cache); | ||
| extern void cint3c2e_sph_optimizer(CINTOpt **, int *, int, int *, int, double *); |
| py_basis = make_contractions(basis_dict, atsyms, atcoords, coord_types="spherical") | ||
| lc_basis = CBasis(py_basis, atsyms, atcoords, coord_type="spherical") | ||
|
|
There was a problem hiding this comment.
Can you make sure the arguments, keywords, etc., match, between the gbasis Python and CBasis implementation? For example, coord_type and coord_types do not match here.
There was a problem hiding this comment.
Thanks for catching this, The difference is intentional — make_contractions takes coord_types (plural) as per the standard GBasis API, while CBasis.init takes coord_type (singular) to match the libcint convention. Both are correct for their respective functions.
Summary
Add Windows CI support to the pytest workflow.
Changes
windows-latestto the OS matrix in.github/workflows/pytest.yamlpip install --no-build-isolationwithcmakeandninjapre-installedTesting
CI will verify that the build and tests pass on Windows with Python 3.9, 3.10, 3.11, and 3.12.
Related