Skip to content
JorgeG94Public

About

A Fortran port of Qiming Sun libcint

Resources

Stars

6 stars

Watchers

0 watching

Forks

Latest commit

 

History

115 Commits

Folders and files

Repository files navigation

libfint

This is a Fortran port of Qiming Sun's libcint. The intention of the port is exploring the Fortran language for performance oriented, friendly API design for general electronic integrals over Gaussian functions used in Quantum Chemistry programs. The code was validated against the C version and a CI workflow is performed to evaluate drift from the original package.

Additional intentions are meant to provide more mature libraries to be tested with the LFortran compiler, simpler integration into the Fortran Package Manager and just me being stubborn and curious.

If using libfint please also cite libcint since it is a derivative work. Libfint will become the main integral engine for mqc and if you are developing versatile quantum chemistry codes in Fortran and wish to stick to an all Fortran environment, you can use libfint.

Validation

Bit-identical, not "equivalent to within tolerance". The suite walks every entry point of both libraries over a shared basis set and compares every double:

574 entry points, 2,751,264 values compared against libcint, 0 over tolerance

There is no tolerance at any Rys-root count. One difference is documented rather than hidden, and it is visible in the check's own output: 228 values in the r-polynomial families differ in the last bit, because the C folds a coefficient into the product where the generator materialises the product and scales afterwards. And int3c1e_ip1_r6_origk differs by rather more against an unpatched libcint, because the C reads a g block it never writes -- that one is a bug in the C, and the patch is offered upstream.

Status

620 of libcint's 635 entry points are ported -- the 15 that are not are ones libcint itself refuses -- along with all 222 optimizers, plus int2c2e_ipip2, which libcint does not have.

Performance is 1.03x to 1.18x libcint's, measured per entry point on an idle machine. doc/PERFORMANCE.md has the table, the method, and a long list of things that were tried and did not work, which is the more useful half.

A second route for the low angular momenta

int2e_rotaxis_cart and int2e_rotaxis_sph (module cint_rotaxis_2e) compute the same four-centre Coulomb integrals as int2e_cart/int2e_sph, through the same shell-quartet interface, by rotated-axis McMurchie--Davidson instead of Rys quadrature -- the GAMESS-lineage sp/d kernels, here generated from a symbolic derivation (scripts/rotaxis_mmd/, doc/ROT_AXIS_MMD.md) for every s, p and L-shell class (21 of them), an L shell being one four-component slot. d and above stay on Rys, which is faster there. It is a different algorithm and so cannot be bit-identical to anything; rotaxis_check holds it to the Rys path at 1e-12 scaled and measures 5e-14.

Building

With fpm:

fpm build
fpm test

With CMake:

cmake -S . -B build && cmake --build build -j

Requires a Fortran 2008 compiler (gfortran 11+ or ifx). Nothing else -- no LAPACK, no BLAS, no C. The undefined symbols in libfint.a are erf, erfc, exp, lgamma, log and pow, and that is the whole list.

The Wheeler quadrature needs a tridiagonal eigensolver, and libfint carries a translation of the one libcint carries -- LAPACK's DSTEMR, which libcint vendored and which its build always uses. -DWITH_EXTERNAL_LAPACK=ON swaps in a system dstemr instead, for callers who already link LAPACK and would rather have a vendor implementation. It is faster and it is not bit-identical.

Verifying the claim

libfint contains no C. Checking it against libcint therefore means fetching libcint, which the build does for you -- from sunqm/libcint master, not a fork and not a pin:

scripts/fetch_libcint.sh
cmake -S . -B build -DLIBFINT_BUILD_TESTS=ON && cmake --build build -j
cd build && ctest

Floating rather than pinned is deliberate. A pin would make this a regression test on libfint; upstream's master makes it a drift detector, and a red run says which kind of drift:

failure meaning
catalogue_check upstream changed a kernel and the Fortran generator has not been told
integral_coverage upstream added an integral; copy its description into scripts/gen_f90_all.cl
build upstream changed its build or its headers

Pass a ref to reproduce an older run: scripts/fetch_libcint.sh v6.1.3.

The catalogue is generated against whichever libcint was fetched rather than committed, so it always compares the intersection of the two libraries -- and integral_coverage is what tells you about the difference.

Relationship to libcint

This is a derivative work under the Apache 2.0 license, which libcint grants explicitly. It tracks a specific upstream version rather than diverging: when libcint adds an integral, the description is copied into the Fortran generator and the suite re-run.

One deliberate difference from stock libcint 6.1.3: a missing G1E_D_I(g76, ...) in src/cint3c1e_a.c, which is a real bug in the C. libfint has it fixed, so int3c1e_a differs from an unpatched libcint. The patch has been offered upstream.

License

Apache 2.0, the same as libcint. See LICENSE and NOTICE.

About

A Fortran port of Qiming Sun libcint

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages