diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 34820bf5e..2ed6f8f51 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -55,7 +55,7 @@ jobs: - name: Install prerequisite MacOS packages if: ${{ steps.skip_check.outputs.should_skip != 'true' && matrix.os == 'macos-latest' }} run: | - brew install ninja gcc@10 boost eigen bison ccache automake python3 numpy scipy + brew install ninja gcc@10 boost eigen bison ccache automake python@3.11 numpy scipy echo "FC=/usr/local/bin/gfortran-10" >> $GITHUB_ENV echo "EIGEN3_INCLUDE_DIR=/usr/local/include/eigen3" >> $GITHUB_ENV diff --git a/CHANGES b/CHANGES index 4a4d8f64a..b54d84dfa 100644 --- a/CHANGES +++ b/CHANGES @@ -4,10 +4,14 @@ Following is a brief summary of changes made in each release of Libint. - 2022-xx-yy: 2.8.0-beta.1 - - UNMERGED PR #270: For Windows, basis sets with a star have been renamed to "s" on the filesystem, + - UNMERGED PR #271: Add `libint2::configuration_accessor` and `libint2::supports` functions. If + library source is patched, these provides codes for what integrals a library instance can supply. + - UNMERGED PR #271: Small pkgconfig and cmake detection improvements. Enable unity build. + Testing of solid harmonics runtime switchable from #269. + - PR #270: For Windows, basis sets with a star have been renamed to "s" on the filesystem, so 6-31g**.g94 -> 6-31gss.g94. In code, the basis can be accessed through "6-31g**" (longstanding) or "6-31gss" (new) for all operating systems. - - UNMERGED PR #270: Adapt build system and header imports so that library and Python bindings can build on + - PR #270: Adapt build system and header imports so that library and Python bindings can build on Windows (at least with clang-cl compiler atop MSVC). Note that a Linux- or Mac-generated export builds on Windows; one cannot generate an export on Windows. Note also that only a static library build, not a shared one, works on Windows (see #237). @@ -15,6 +19,9 @@ Following is a brief summary of changes made in each release of Libint. - PR #269: Solid harmonics ordering is runtime switchable in the library. Issue `libint2::set_solid_harmonics_ordering(libint2::SHGShellOrdering_Gaussian)` or `_Standard` after initialization. Similarly, prefer new `INT_SOLIDHARMINDEX(sho, l, m)` to usual `(l, m)` version. + - PR #269: The ordering for spherical multipole integrals has been fixed at Standard, rather than + Gaussian or Standard as previously. Note that between this and the next item above, the + `--with-shgauss-ordering=standard|gaussian` has been rendered pointless for the C++ interface. - PR #268: Python detection (relevant to Python bindings, Fortran, and some tests) now uses modern `find_package(Python)`. Specify with `Python_EXECUTABLE` (note change in case) or https://cmake.org/cmake/help/latest/module/FindPython.html for details . diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 000000000..dd3d568f1 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,130 @@ +### Run-Time Compatibility + +Functions are provided to check the library configuration and solid harmonics orderings at runtime: + +Note: As of v2.8.0 (libtool-based), the configuration_accessor() function will return `(nyi)` by default. + Packagers are encouraged to patch a generated configuration string into file `configuration.cc.cmake.in` to + imitate future cmake-based behavior. See sample patch below. The string can be generated by editing + and running `export/cmake/configuration-gen.py`. + Also patch MAX_AM_ERI in `CMakeLists.txt` (of export tarball; `export/cmake/CMakeLists.txt.export` in repo src). + +``` +libint2::initialize(); +printf("SHGShell: %d\n", libint2::solid_harmonics_ordering()); +libint2::set_solid_harmonics_ordering(libint2::SHGShellOrdering_Gaussian); +printf("SHGShell: %d\n", libint2::solid_harmonics_ordering()); +// if patched as described above +printf("Configuration: %s\n", libint2::configuration_accessor().c_str()); +printf("Supports: dddd=%d mmmm=%d\n", libint2::supports("eri_dddd_d0"), libint2::supports("eri_mmmm_d0")); +libint2::finalize(); +``` +``` +SHGShell: 1 +SHGShell: 2 +Configuration: eri_dddd_d0_l2;eri_ffff_d0;ss;... +Supports: dddd=1 mmmm=0 +``` + +For the C library, a similar function is available: + +``` +printf("CMake Configuration (C) : %s\n", configuration_accessor()); +``` +``` +CMake Configuration (C) : eri_dddd_d0;eri_ffff_d0;ss;... +``` + +If you have a built libint2 library whose history you don't know, a command like this on Linux can provide the same information: + +``` +strings -n80 /a/random/L2/lying/around/libint2.so +``` +``` +ss;onebody_ii_d0;onebody_hh_d0;eri_iiI_d0;eri_iii_d0;eri_II_d0;eri_ii_d0;eri_hhhh_d0;eri_hhH_d0;eri_hhh_d0;eri_HH_d0;eri_hh_d0;eri_gggg_d1;eri_dddd_d1 +``` + +A patch like the following is suitable for an export tarball generated from the next following. +[See guide](#configuration-codes) for decoding the configuration components. + +``` +--- src/configuration.cc.cmake.in 2023-09-05 09:13:50.000000000 -0400 ++++ src/configuration.cc.cmake.in_basic 2023-09-05 23:41:00.444396591 -0400 +@@ -24,6 +24,6 @@ + @return the semicolon-separated strings from CMake components */ + const char * configuration_accessor() { + //return "@Libint2_CONFIG_COMPONENTS@"; +- return "(nyi)"; ++ return "ss;multipole_nn_d0;multipole_mm_d0;multipole_ll_d0;multipole_kk_d0;multipole_ii_d0;multipole_hh_d0;multipole_gg_d0;multipole_ff_d0;multipole_dd_d0;onebody_ii_d0;onebody_hh_d0;onebody_gg_d0;onebody_ff_d0;onebody_dd_d0;onebody_hh_d1;onebody_gg_d1;onebody_ff_d1;onebody_dd_d1;onebody_gg_d2;onebody_ff_d2;onebody_dd_d2;eri_hhhh_d0;eri_gggg_d0;eri_ffff_d0;eri_dddd_d0;eri_gggg_d1;eri_ffff_d1;eri_dddd_d1;eri_iiI_d0;eri_hhI_d0;eri_hhH_d0;eri_ggI_d0;eri_ggH_d0;eri_ggG_d0;eri_ffI_d0;eri_ffH_d0;eri_ffG_d0;eri_ffF_d0;eri_ddI_d0;eri_ddH_d0;eri_ddG_d0;eri_ddF_d0;eri_ddD_d0;eri_hhH_d1;eri_ggH_d1;eri_ggG_d1;eri_ffH_d1;eri_ffG_d1;eri_ffF_d1;eri_ddH_d1;eri_ddG_d1;eri_ddF_d1;eri_ddD_d1;eri_iii_d0;eri_hhi_d0;eri_hhh_d0;eri_ggi_d0;eri_ggh_d0;eri_ggg_d0;eri_ffi_d0;eri_ffh_d0;eri_ffg_d0;eri_fff_d0;eri_ddi_d0;eri_ddh_d0;eri_ddg_d0;eri_ddf_d0;eri_ddd_d0;eri_hhh_d1;eri_ggh_d1;eri_ggg_d1;eri_ffh_d1;eri_ffg_d1;eri_fff_d1;eri_ddh_d1;eri_ddg_d1;eri_ddf_d1;eri_ddd_d1;eri_II_d0;eri_HH_d0;eri_GG_d0;eri_FF_d0;eri_DD_d0;eri_HH_d1;eri_GG_d1;eri_FF_d1;eri_DD_d1;eri_ii_d0;eri_hh_d0;eri_gg_d0;eri_ff_d0;eri_dd_d0;eri_hh_d1;eri_gg_d1;eri_ff_d1;eri_dd_d1;g12_gggg_d0;g12_ffff_d0;g12_dddd_d0;g12_gggg_d1;g12_ffff_d1;g12_dddd_d1"; +} +``` +``` +./configure \ + --enable-eri=1 \ + --enable-eri3=1 \ + --enable-eri2=1 \ + --enable-1body=2 \ + --enable-g12=1 \ + --disable-1body-property-derivs \ + --with-multipole-max-order=10 \ + --with-g12-max-am=4 \ + --with-eri-max-am=5,4 \ + --with-eri3-max-am=6,5 \ + --with-eri2-max-am=6,5 \ + --with-max-am=6,5 +``` + + +#### Configuration Codes + +Evenually, these will be CMake Components, too. + +``` + multipole_hh_dD - library includes spherical multipole integrals with max angular momentum up to + "h" (h=spdfghikl...; s,p not enumerated) and derivative order "D" (D=0,1,2,...). + For example, the presence of "multipole_ii_d0" means mpole ints are available for L=6. + onebody_hh_dD - library includes 1-body integrals with max angular momentum up to "h" + (h=spdfghikl...; s,p not enumerated) and derivative order "D" (D=0,1,2,...). + For example, the presence of "onebody_ii_d1" means onebody gradient ints are + available for L=6. + eri_hhhh_dD - library includes 2-body integrals with 4 centers and max angular momentum up to + "h" (h=spdfghikl...; s,p not enumerated) and derivative order "D" (D=0,1,2,...). + For example, the presence of "eri_ffff_d1" means 4-center gradient ints are + available for L=3. That is, the library was configured with at least + "--enable-eri=1 --with-eri-max-am=?,>=3". + eri_hhL_dD - library includes 2-body integrals with 3 centers and max angular momentum up to + eri_hhl_dD Cartesian "h" for the two paired centers and Cartesian "l" or solid harmonics "L" + for the unpaired/fitting center, (h/l=spdfghikl..., L=SPDFGHIKL...; l>=h + enumerated; s,p,S,P not enumerated) and derivative order "D" (D=0,1,2,...). The + "eri_hhL_dD" component is always available when 3-center ints are present. When pure + solid harmonics are assumed for 3-center ints, "eri_hhl_dD" will *not be available*. + For example, the presence of "eri_ffG_d0" means 3-center energy ints are + available for L=3 (paired centers) and L=4 (fitting center). That is, the library + was configured with at least "--enable-eri3=0 --with-max-am=3 --with-eri3-max-am=4". + The presence of "eri_ffg_d0" means the library configuration did not additionally + include "--enable-eri3-pure-sh[=yes]". + eri_HH_dD - library includes 2-body integrals with 2 centers and max angular momentum up to + eri_hh_dD Cartesian "h" or solid harmonics "H", (h=spdfghikl..., H=SPDFGHIKL...; s,p,S,P not + enumerated) and derivative order "D" (D=0,1,2,...). The "eri_HH_dD" component is + always available when 2-center ints are present. When pure solid harmonics are + assumed for 2-center ints, "eri_hh_dD" will *not be available*. + For example, the presence of "eri_FF_d2" means 2-center Hessian ints are + available for L=3. That is, the library was configured with at least + "--enable-eri2=2 --with-eri2-max-am=?,?,>=3". The presence of "eri_ff_d2" means the + library configuration did not additionally include "--enable-eri2-pure-sh[=yes]". + g12_hhhh_dD - library includes F12 integrals with Gaussian factors and max angular momentum up to + "h" (h=spdfghikl...; s,p not enumerated) and derivative order "D" (D=0,1,2,...). + For example, the presence of "g12_iiii_d2" means g12 Hessian ints are available for L=6. + + cart shell_set used_by + -------- --------- ------- + ss - library integrals use ordering standard + standard = mpqc4, cp2k, psi4 (psi4 requires runtime-setting of solid harmonic ordering to Gaussian) + so - library integrals use ordering + orca + is - library integrals use ordering intv3 + standard = mpqc3 + io - library integrals use ordering + orca + gs - library integrals use ordering gamess + standard = gamess + go - library integrals use ordering + orca + os - library integrals use ordering orca + standard + oo - library integrals use ordering + orca = orca + bs - library integrals use ordering bagel + standard = bagel + bo - library integrals use ordering + orca +``` diff --git a/configure.ac b/configure.ac index f61eb2515..8523a5682 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,9 @@ esac AC_DEFINE_UNQUOTED(LIBINT_SHGSHELL_ORDERING,$libint_shgshell_ordering) AC_DEFINE_UNQUOTED(LIBINT_SHGSHELL_ORDERING_STANDARD,$LIBINT_SHGSHELL_ORDERING_STANDARD) AC_DEFINE_UNQUOTED(LIBINT_SHGSHELL_ORDERING_GAUSSIAN,$LIBINT_SHGSHELL_ORDERING_GAUSSIAN) +AC_SUBST(LIBINT_SHGSHELL_ORDERING_STANDARD) +AC_SUBST(LIBINT_SHGSHELL_ORDERING_GAUSSIAN) +AC_SUBST(LIBINT_SHGSHELL_ORDERING,$libint_shgshell_ordering) LIBINT_SHELL_SET_STANDARD=1 AC_SUBST(LIBINT_SHELL_SET_STANDARD) LIBINT_SHELL_SET_ORCA=2 AC_SUBST(LIBINT_SHELL_SET_ORCA) diff --git a/export/Makefile b/export/Makefile index 94ed14e04..64fb24d0f 100644 --- a/export/Makefile +++ b/export/Makefile @@ -34,10 +34,10 @@ strip_some_preproc_symb:: exportdir -rm $(TOPDIR)/$(EXPORTDIR)/include/libint2/config.h.cmake.tmp exportdir:: - -$(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/libint2.pc.in $(TOPDIR)/$(EXPORTDIR) -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/INSTALL.export $(TOPDIR)/$(EXPORTDIR)/INSTALL -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/LICENSE.export $(TOPDIR)/$(EXPORTDIR)/LICENSE -$(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/README.md $(TOPDIR)/$(EXPORTDIR)/README.md + -$(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/INSTALL.md $(TOPDIR)/$(EXPORTDIR)/INSTALL.md -$(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/COPYING $(TOPDIR)/$(EXPORTDIR)/COPYING -$(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/COPYING.LESSER $(TOPDIR)/$(EXPORTDIR)/COPYING.LESSER -$(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/CITATION $(TOPDIR)/$(EXPORTDIR)/CITATION @@ -98,6 +98,7 @@ exportdir:: -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/cmake/CMakeLists.txt.include.export $(TOPDIR)/$(EXPORTDIR)/include/CMakeLists.txt $(INSTALL) $(INSTALLDIROPT) $(TOPDIR)/$(EXPORTDIR)/cmake -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/cmake/libint2-config.cmake.in $(TOPDIR)/$(EXPORTDIR)/cmake/libint2-config.cmake.in + -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/cmake/libint2.pc.cmake.in $(TOPDIR)/$(EXPORTDIR)/cmake/libint2.pc.cmake.in -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/cmake/hftest.cmake $(TOPDIR)/$(EXPORTDIR)/cmake/hftest.cmake $(INSTALL) $(INSTALLDIROPT) $(TOPDIR)/$(EXPORTDIR)/cmake/modules -$(INSTALL) $(INSTALLLIBOPT) $(SRCDIR)/cmake/modules/*.cmake $(TOPDIR)/$(EXPORTDIR)/cmake/modules diff --git a/export/cmake/CMakeLists.txt.export b/export/cmake/CMakeLists.txt.export index 153f756b3..233106e44 100644 --- a/export/cmake/CMakeLists.txt.export +++ b/export/cmake/CMakeLists.txt.export @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.16) # 3.15: new Python detection; 3.16 to make the final leap +cmake_minimum_required(VERSION 3.16) # 3.16: unity build + # 3.15: new Python detection # 3.8: introduced C++ standards as features cmake_policy(SET CMP0079 NEW) @@ -15,6 +16,7 @@ if (LIBINT_BUILDID) else(LIBINT_BUILDID) set(LIBINT_EXT_VERSION ${LIBINT_VERSION}) endif(LIBINT_BUILDID) +set(MAX_AM_ERI "") # patch here in export tarball w/highest 4-center, 0-deriv ERI AM in numbers # Add module directory and modules ===================================================================================== @@ -28,6 +30,10 @@ include(RedefaultableOption) include(CMakePushCheckState) include(AddCustomTargetSubproject) +include(GNUInstallDirs) +set(L2 Libint2) # Namespace +set(pnv libint2) # projectnameversion + # Options ============================================================================================================== redefaultable_option(REQUIRE_CXX_API "C++11 Libint interface" ON) @@ -188,12 +194,17 @@ foreach(FN IN LISTS LIBINT2_LIBRARY_CXX_SRC) list(APPEND LIB_CXX_SRC "src/${FN}") endforeach() # Create object files to use for static and shared libraries -add_library(libint2_obj OBJECT ${LIB_CXX_SRC}) +add_library(libint2_obj OBJECT ${LIB_CXX_SRC} "src/configuration.cc") target_include_directories(libint2_obj PRIVATE include ${PROJECT_BINARY_DIR}/include) # Compile static library with position independent code target_compile_definitions(libint2_obj PRIVATE __COMPILING_LIBINT2) target_compile_features(libint2_obj PUBLIC "cxx_std_11") +set_target_properties( + libint2_obj + PROPERTIES + UNITY_BUILD TRUE + ) if (TARGET MPFR::GMPXX) target_link_libraries(libint2_obj PUBLIC MPFR::GMPXX) endif() @@ -404,14 +415,23 @@ if (LIBINT_HAS_CXX_API) tests/unit/test-shell-order.cc tests/unit/test-util.cc ) - add_executable(unit_tests-libint2 EXCLUDE_FROM_ALL tests/unit/test.cc ${utests_src}) - target_compile_definitions(unit_tests-libint2 PRIVATE -DNO_LIBINT_COMPILER_CODE) - target_link_libraries(unit_tests-libint2 libint2_cxx) - add_test(libint2/unit/build "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target unit_tests-libint2) - set_tests_properties(libint2/unit/build PROPERTIES FIXTURES_SETUP LIBINT2_UNIT_TESTS_EXEC) - add_test(NAME libint2/unit/run - COMMAND $) - set_tests_properties(libint2/unit/run + add_executable(unit_tests_s-libint2 EXCLUDE_FROM_ALL tests/unit/test.cc ${utests_src}) + target_compile_definitions(unit_tests_s-libint2 PRIVATE -DNO_LIBINT_COMPILER_CODE) + target_link_libraries(unit_tests_s-libint2 libint2_cxx) + add_test(libint2/unit_s/build "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target unit_tests_s-libint2) + set_tests_properties(libint2/unit_s/build PROPERTIES FIXTURES_SETUP LIBINT2_UNIT_TESTS_EXEC) + add_test(NAME libint2/unit_s/run + COMMAND $) + set_tests_properties(libint2/unit_s/run + PROPERTIES FIXTURES_REQUIRED LIBINT2_UNIT_TESTS_EXEC) + add_executable(unit_tests_g-libint2 EXCLUDE_FROM_ALL tests/unit/test_g.cc ${utests_src}) + target_compile_definitions(unit_tests_g-libint2 PRIVATE -DNO_LIBINT_COMPILER_CODE) + target_link_libraries(unit_tests_g-libint2 libint2_cxx) + add_test(libint2/unit_g/build "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target unit_tests_g-libint2) + set_tests_properties(libint2/unit_g/build PROPERTIES FIXTURES_SETUP LIBINT2_UNIT_TESTS_EXEC) + add_test(NAME libint2/unit_g/run + COMMAND $) + set_tests_properties(libint2/unit_g/run PROPERTIES FIXTURES_REQUIRED LIBINT2_UNIT_TESTS_EXEC) add_executable(hf-libint2 EXCLUDE_FROM_ALL tests/hartree-fock/hartree-fock.cc) @@ -545,6 +565,8 @@ configure_file( # In the future CMake switchover, configuration.h/cc define a string summary of capabilities. @ONLY is maximally deferred in case config2 changes the # summary (as it used to when LIBINT_SHGSHELL_ORDERING was library-config-time selected). +# Note that in the future CMake switchover, configuration.cc should be a .cmake.in in the repo. It is not, for the moment, so the libtool build +# of the library works and because there's nothing to substitute until CMake knows the build configuration. #configure_file(${PROJECT_SOURCE_DIR}/include/libint2/util/configuration.h.cmake.in ${PROJECT_BINARY_DIR}/include/libint2/util/configuration.h @ONLY) configure_file(src/configuration.cc.cmake.in ${PROJECT_BINARY_DIR}/src/configuration.cc @ONLY) @@ -554,15 +576,18 @@ configure_file( @ONLY ) -configure_file( - libint2.pc.in - ${PROJECT_BINARY_DIR}/libint2.pc - @ONLY -) +include(JoinPaths) +join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}") +join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") +configure_file(cmake/libint2.pc.cmake.in libint2.pc @ONLY) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/libint2.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/ + COMPONENT ${L2}_Development + ) # install cmake-processed files -install(FILES ${PROJECT_BINARY_DIR}/libint2.pc - DESTINATION lib/pkgconfig) install(FILES ${PROJECT_BINARY_DIR}/include/libint2/config.h DESTINATION "${LIBINT2_INSTALL_INCLUDEDIR}/libint2") install(FILES ${PROJECT_BINARY_DIR}/include/libint2/basis.h diff --git a/export/cmake/configuration-gen.py b/export/cmake/configuration-gen.py new file mode 100644 index 000000000..502cb6eb1 --- /dev/null +++ b/export/cmake/configuration-gen.py @@ -0,0 +1,151 @@ +# <<< User edit + +# * For each integrals class, supply a list with max AM for each enabled derivative level. +# * User is responsible for "distributing" defaults across classes and derivs. +# e.g., `--enable-eri2=2 --with-max-am=4` (`--with-eri2-max-am` not specified) becomes `eri2_max_am = [4, 4, 4]` +orderings = "ss" +# max am: +# * only used for paired on eri3. +# * must be same length as eri3_max_am. +# * if `--with-max-am` not given to ./configure, duplicate `eri3_max_am` as `max_am` here. +# * this script will NOT use this as default for other integrals classes. +max_am = [6, 5] +multipole = [10] +onebody = [6, 5, 4] +eri_max_am = [5, 4] +eri3_max_am = [6, 5] +eri3_pure_sh = False +eri2_max_am = [6, 5] +eri2_pure_sh = False +g12_max_am = [4, 4] + +# >>> End user edit + +amstr = "SPDFGHIKLMNOPQRTUVWXYZ" +components = [orderings] + +# multipole +for deriv in range(len(multipole)): + for am in range(multipole[deriv], 1, -1): # don't enumerate s, p + centers = amstr[am].lower() * 2 + comp = f"multipole_{centers}_d{deriv}" + components.append(comp) + +# onebody +for deriv in range(len(onebody)): + for am in range(onebody[deriv], 1, -1): + centers = amstr[am].lower() * 2 + comp = f"onebody_{centers}_d{deriv}" + components.append(comp) + +# eri (4-center) +for deriv in range(len(eri_max_am)): + for am in range(eri_max_am[deriv], 1, -1): + centers = amstr[am].lower() * 4 + comp = f"eri_{centers}_d{deriv}" + components.append(comp) + +# eri3 +no_pure_sh = [] +for deriv in range(len(eri3_max_am)): + for am_paired in range(max_am[deriv], 1, -1): + for am_fitting in range(eri3_max_am[deriv], 1, -1): + if am_fitting >= am_paired: + centers = amstr[am_paired].lower() * 2 + amstr[am_fitting].upper() + comp = f"eri_{centers}_d{deriv}" + #print(deriv, am_fitting, am_paired, centers, comp) + components.append(comp) + no_pure_sh.append(comp.lower()) +if not eri3_pure_sh: + components.extend(no_pure_sh) + +# eri2 +no_pure_sh = [] +for deriv in range(len(eri2_max_am)): + for am in range(eri2_max_am[deriv], 1, -1): + centers = amstr[am].upper() * 2 + comp = f"eri_{centers}_d{deriv}" + components.append(comp) + no_pure_sh.append(comp.lower()) +if not eri2_pure_sh: + components.extend(no_pure_sh) + +# g12 +for deriv in range(len(g12_max_am)): + for am in range(g12_max_am[deriv], 1, -1): + centers = amstr[am].lower() * 4 + comp = f"g12_{centers}_d{deriv}" + components.append(comp) + +for comp in components: + print(comp) +components = ";".join(components) +print(components) + + +# An example + +#./configure \ +# --enable-eri=1 \ +# --enable-eri3=1 \ +# --enable-eri2=1 \ +# --enable-1body=2 \ +# --enable-g12=1 \ +# --disable-1body-property-derivs \ +# --with-multipole-max-order=10 \ +# --with-g12-max-am=4 \ +# --with-eri-max-am=5,4 \ +# --with-eri3-max-am=6,5 \ +# --with-eri2-max-am=6,5 \ +# --with-max-am=6,5 + +## script headmatter +#orderings = "ss" +#max_am = [6, 5] +#multipole = [10] +#onebody = [6, 5, 4] +#eri_max_am = [5, 4] +#eri3_max_am = [6, 5] +#eri3_pure_sh = False +#eri2_max_am = [6, 5] +#eri2_pure_sh = False +#g12_max_am = [4, 4] + +#ans = "ss;multipole_nn_d0;multipole_mm_d0;multipole_ll_d0;multipole_kk_d0;multipole_ii_d0;multipole_hh_d0;multipole_gg_d0;multipole_ff_d0;multipole_dd_d0;onebody_ii_d0;onebody_hh_d0;onebody_gg_d0;onebody_ff_d0;onebody_dd_d0;onebody_hh_d1;onebody_gg_d1;onebody_ff_d1;onebody_dd_d1;onebody_gg_d2;onebody_ff_d2;onebody_dd_d2;eri_hhhh_d0;eri_gggg_d0;eri_ffff_d0;eri_dddd_d0;eri_gggg_d1;eri_ffff_d1;eri_dddd_d1;eri_iiI_d0;eri_hhI_d0;eri_hhH_d0;eri_ggI_d0;eri_ggH_d0;eri_ggG_d0;eri_ffI_d0;eri_ffH_d0;eri_ffG_d0;eri_ffF_d0;eri_ddI_d0;eri_ddH_d0;eri_ddG_d0;eri_ddF_d0;eri_ddD_d0;eri_hhH_d1;eri_ggH_d1;eri_ggG_d1;eri_ffH_d1;eri_ffG_d1;eri_ffF_d1;eri_ddH_d1;eri_ddG_d1;eri_ddF_d1;eri_ddD_d1;eri_iii_d0;eri_hhi_d0;eri_hhh_d0;eri_ggi_d0;eri_ggh_d0;eri_ggg_d0;eri_ffi_d0;eri_ffh_d0;eri_ffg_d0;eri_fff_d0;eri_ddi_d0;eri_ddh_d0;eri_ddg_d0;eri_ddf_d0;eri_ddd_d0;eri_hhh_d1;eri_ggh_d1;eri_ggg_d1;eri_ffh_d1;eri_ffg_d1;eri_fff_d1;eri_ddh_d1;eri_ddg_d1;eri_ddf_d1;eri_ddd_d1;eri_II_d0;eri_HH_d0;eri_GG_d0;eri_FF_d0;eri_DD_d0;eri_HH_d1;eri_GG_d1;eri_FF_d1;eri_DD_d1;eri_ii_d0;eri_hh_d0;eri_gg_d0;eri_ff_d0;eri_dd_d0;eri_hh_d1;eri_gg_d1;eri_ff_d1;eri_dd_d1;g12_gggg_d0;g12_ffff_d0;g12_dddd_d0;g12_gggg_d1;g12_ffff_d1;g12_dddd_d1" + +# Another example + +#./configure \ +# --with-max-am=2,2 \ +# --with-eri-max-am=2,2 \ +# --with-eri3-max-am=3,2 \ +# --enable-eri=1 \ +# --enable-eri3=1 \ +# --enable-1body=1 \ +# --disable-1body-property-derivs \ +# --with-multipole-max-order=2 \ +# --enable-eri3-pure-sh + +## script headmatter +#orderings = "ss" +#max_am = [2, 2] +#multipole = [2] +#onebody = [2, 2] +#eri_max_am = [2, 2] +#eri3_max_am = [3, 2] +#eri3_pure_sh = True +#eri2_max_am = [] +#eri2_pure_sh = False +#g12_max_am = [] + +#ans = "ss;multipole_dd_d0;onebody_dd_d0;onebody_dd_d1;eri_dddd_d0;eri_dddd_d1;eri_ddF_d0;eri_ddD_d0;eri_ddD_d1" + +# Check examples + +#ans = ans.split(";") +#for idx, comp in enumerate(components.split(";")): +# print(comp, ans[idx], comp == ans[idx]) +#ans = ";".join(ans) +# +#assert components == ans + diff --git a/export/cmake/libint2-config.cmake.in b/export/cmake/libint2-config.cmake.in index 09699c177..9989dbfc3 100644 --- a/export/cmake/libint2-config.cmake.in +++ b/export/cmake/libint2-config.cmake.in @@ -17,6 +17,8 @@ # Set package version set(LIBINT2_VERSION "@LIBINT_VERSION@") set(LIBINT2_EXT_VERSION "@LIBINT_EXT_VERSION@") +set(Libint2_EXT_VERSION "@LIBINT_EXT_VERSION@") +set(Libint2_MAX_AM_ERI "@MAX_AM_ERI@") @PACKAGE_INIT@ diff --git a/export/cmake/libint2.pc.cmake.in b/export/cmake/libint2.pc.cmake.in new file mode 100644 index 000000000..3c28adf1d --- /dev/null +++ b/export/cmake/libint2.pc.cmake.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@libdir_for_pc_file@ +includedir=@includedir_for_pc_file@ + +Name: libint2 +Description: a library for the evaluation of molecular integrals of many-body operators over Gaussian functions +Version: @LIBINT_VERSION@ +Libs: -L${libdir} -lint2 +Cflags: -I${includedir} -I${includedir}/libint2 diff --git a/export/cmake/modules/JoinPaths.cmake b/export/cmake/modules/JoinPaths.cmake new file mode 100644 index 000000000..c68d91b84 --- /dev/null +++ b/export/cmake/modules/JoinPaths.cmake @@ -0,0 +1,23 @@ +# This module provides function for joining paths +# known from most languages +# +# SPDX-License-Identifier: (MIT OR CC0-1.0) +# Copyright 2020 Jan Tojnar +# https://github.com/jtojnar/cmake-snips +# +# Modelled after Python’s os.path.join +# https://docs.python.org/3.7/library/os.path.html#os.path.join +# Windows not supported +function(join_paths joined_path first_path_segment) + set(temp_path "${first_path_segment}") + foreach(current_segment IN LISTS ARGN) + if(NOT ("${current_segment}" STREQUAL "")) + if(IS_ABSOLUTE "${current_segment}") + set(temp_path "${current_segment}") + else() + set(temp_path "${temp_path}/${current_segment}") + endif() + endif() + endforeach() + set(${joined_path} "${temp_path}" PARENT_SCOPE) +endfunction() diff --git a/include/libint2/boys.h b/include/libint2/boys.h index 8c83ef75a..79b94ebe4 100644 --- a/include/libint2/boys.h +++ b/include/libint2/boys.h @@ -258,7 +258,7 @@ namespace libint2 { static constexpr int ORDER = interpolation_order; //!, interpolation order static constexpr int ORDERp1 = ORDER+1; //!< ORDER + 1 - static constexpr Real T_crit = cheb_table_tmax; //!< critical value of T above which safe to use upward recusion + static constexpr Real T_crit = cheb_table_tmax; //!< critical value of T above which safe to use upward recursion static constexpr Real delta = cheb_table_delta; //!< interval size static constexpr Real one_over_delta = 1/delta; //! 1/delta diff --git a/include/libint2/engine.h b/include/libint2/engine.h index 179ed093b..eddb862ff 100644 --- a/include/libint2/engine.h +++ b/include/libint2/engine.h @@ -124,9 +124,9 @@ enum class Operator { //! multiply these harmonics by \f$ (-1)^m \sqrt{(2 - \delta_{m,0}) (l + |m|)! (l - |m|)!} \f$ . //! The operator set includes multipoles of order up to \f$ l_{\rm max} = \f$ MULTIPOLE_MAX_ORDER (for a total of \f$ (l_{\rm max}+1)^2 \f$ operators), //! in the order of increasing \c l , with the operators of same \c l but different \c m ordered according to the solid harmonics ordering - //! specified at configure time (see macro FOR_SOLIDHARM in shgshell_ordering.h.in). For example, for the CCA standard solid harmonics - //! ordering the operators will appear in the following order + //! CCA standard (see macro FOR_SOLIDHARM_STANDARD in shgshell_ordering.h.in). For example, the operators will appear in the following order //! \f$ \mathcal{N}^+_{0,0} , \mathcal{N}^-_{1,1}, \mathcal{N}^+_{1,0}, \mathcal{N}^+_{1,1}, \mathcal{N}^-_{2,2}, \mathcal{N}^-_{2,1}, \mathcal{N}^+_{2,0}, \mathcal{N}^+_{2,1}, \mathcal{N}^+_{2,2}. \dots \f$ . + //! Previous to cdbb9f3 released in v2.8.0, Standard -or- Gaussian ordering could be be specified at generator/compiler configure time. sphemultipole, /// \f$ \delta(\vec{r}_1 - \vec{r}_2) \f$ delta, diff --git a/include/libint2/numeric.h b/include/libint2/numeric.h index 478acf88e..b3d874099 100644 --- a/include/libint2/numeric.h +++ b/include/libint2/numeric.h @@ -10,6 +10,7 @@ #include #include #include +#include #if LIBINT_HAS_MPFR # include @@ -34,6 +35,11 @@ mpf_init2(expx, prec); mpfr_get_f(expx, expx_r, MPFR_RNDN); mpf_class result(expx, prec); + + mpfr_clear(x_r); + mpfr_clear(expx_r); + mpf_clear(expx); + return result; } /// implement pow for mpf_class using MPFR ... I do not claim to know what issues the rounding presents here @@ -48,12 +54,15 @@ mpf_class result(x_to_a, prec); if (a < 0) result = 1.0 / result; + mpf_clear(x_to_a); return result; } +#ifndef _MSC_VER /// this is needed to avoid ambiguity in pow(2.0, 2) ... the above pow competes with standard double pow(double, double) inline double pow(double x, int a) { return std::pow(x, static_cast(a)); } +#endif /// implement erf for mpf_class using MPFR ... I do not claim to know what issues the rounding presents here inline mpf_class erf(mpf_class x) { const auto prec = x.get_prec(); @@ -67,6 +76,11 @@ mpf_init2(erfx, prec); mpfr_get_f(erfx, erfx_r, MPFR_RNDN); mpf_class result(erfx, prec); + + mpfr_clear(x_r); + mpfr_clear(erfx_r); + mpf_clear(erfx); + return result; } /// implement acos for mpf_class using MPFR ... I do not claim to know what issues the rounding presents here @@ -82,6 +96,11 @@ mpf_init2(acosx, prec); mpfr_get_f(acosx, acosx_r, MPFR_RNDN); mpf_class result(acosx, prec); + + mpfr_clear(x_r); + mpfr_clear(acosx_r); + mpf_clear(acosx); + return result; } /// implement log for mpf_class using MPFR ... I do not claim to know what issues the rounding presents here @@ -97,6 +116,11 @@ mpf_init2(logx, prec); mpfr_get_f(logx, logx_r, MPFR_RNDN); mpf_class result(logx, prec); + + mpfr_clear(x_r); + mpfr_clear(logx_r); + mpf_clear(logx); + return result; } #endif diff --git a/include/libint2/util/configuration.h b/include/libint2/util/configuration.h index cfa1e119e..39a55da29 100644 --- a/include/libint2/util/configuration.h +++ b/include/libint2/util/configuration.h @@ -28,6 +28,8 @@ const char * configuration_accessor(); #ifdef _libint2_src_lib_libint_cxxapi_h_ #include +#include +#include namespace libint2 { @@ -38,6 +40,19 @@ namespace libint2 { std::string components = ::configuration_accessor(); return components; } + + /// Runtime accessor for individual library configuration components: + /// integral derivatives, AM, orderings, etc. + /// @param[in] target CMake component with maximally uniform AM + /// @return whether target component available + inline bool supports(std::string component) { + std::string segment; + std::vector seglist; + std::stringstream ca(configuration_accessor()); + while(std::getline(ca, segment, ';')) { seglist.push_back(segment); } + bool tf = (std::find(seglist.begin(), seglist.end(), component) != seglist.end()); + return tf; + } } #endif /* cxxapi guard */ diff --git a/src/bin/libint/build_libint.cc b/src/bin/libint/build_libint.cc index 448350e3b..de3bbf89b 100644 --- a/src/bin/libint/build_libint.cc +++ b/src/bin/libint/build_libint.cc @@ -578,23 +578,23 @@ BOOST_PP_LIST_FOR_EACH ( BOOST_PP_ONEBODY_MCR1, _, BOOST_PP_ONEBODY_TASK_LIST) #if defined(ONEBODY_MAX_AM_LIST) # define BOOST_PP_ONEBODY_MCR2(r,data,elem) \ - cparams->max_am( task_label(elem, d), token(ONEBODY_MAX_AM_LIST,',',d)); + cparams->max_am( task_label(BOOST_PP_STRINGIZE(elem), d), token(ONEBODY_MAX_AM_LIST,',',d)); BOOST_PP_LIST_FOR_EACH ( BOOST_PP_ONEBODY_MCR2, _, BOOST_PP_ONEBODY_TASK_LIST) # undef BOOST_PP_ONEBODY_MCR2 #elif defined(ONEBODY_MAX_AM) # define BOOST_PP_ONEBODY_MCR3(r,data,elem) \ - cparams->max_am( task_label(elem, d), ONEBODY_MAX_AM); + cparams->max_am( task_label(BOOST_PP_STRINGIZE(elem), d), ONEBODY_MAX_AM); BOOST_PP_LIST_FOR_EACH ( BOOST_PP_ONEBODY_MCR3, _, BOOST_PP_ONEBODY_TASK_LIST) # undef BOOST_PP_ONEBODY_MCR3 #endif #if defined(ONEBODY_OPT_AM_LIST) # define BOOST_PP_ONEBODY_MCR4(r,data,elem) \ - cparams->max_am_opt( task_label(elem, d) ,token(ONEBODY_OPT_AM_LIST,',',d)); + cparams->max_am_opt( task_label(BOOST_PP_STRINGIZE(elem), d) ,token(ONEBODY_OPT_AM_LIST,',',d)); BOOST_PP_LIST_FOR_EACH ( BOOST_PP_ONEBODY_MCR4, _, BOOST_PP_ONEBODY_TASK_LIST) # undef BOOST_PP_ONEBODY_MCR4 #elif defined(ONEBODY_OPT_AM) # define BOOST_PP_ONEBODY_MCR5(r,data,elem) \ - cparams->max_am_opt( task_label(elem, d) , ONEBODY_OPT_AM); + cparams->max_am_opt( task_label(BOOST_PP_STRINGIZE(elem), d) , ONEBODY_OPT_AM); BOOST_PP_LIST_FOR_EACH ( BOOST_PP_ONEBODY_MCR5, _, BOOST_PP_ONEBODY_TASK_LIST) # undef BOOST_PP_ONEBODY_MCR5 #endif diff --git a/src/lib/MakeRules.in b/src/lib/MakeRules.in index dd780bc8e..bc23359e9 100644 --- a/src/lib/MakeRules.in +++ b/src/lib/MakeRules.in @@ -14,7 +14,7 @@ export:: source for i in $(LIBSRCDIR)/*.h; do \ $(INSTALL) $(INSTALLLIBOPT) $${i} $(TOPDIR)/$(EXPORTDIR)/include; \ done - $(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/src/lib/libint/configuration.cc.cmake.in $(TOPDIR)/$(EXPORTDIR)/src/configuration.cc.cmake.in + $(INSTALL) $(INSTALLLIBOPT) $(SRCTOPDIR)/src/lib/libint/configuration.cc $(TOPDIR)/$(EXPORTDIR)/src/configuration.cc.cmake.in $(TOPDIR)/lib/$(TARGET): source cd $(LIBSRCLINK); $(MAKE) TO_TOPDIR=$(TO_TOPDIR) TOPDIR=$(TOPOBJDIR) SRCDIR=$(SRCDIR) diff --git a/src/lib/libint/MakeVars.features.in b/src/lib/libint/MakeVars.features.in index a9a117811..a71f833f1 100644 --- a/src/lib/libint/MakeVars.features.in +++ b/src/lib/libint/MakeVars.features.in @@ -5,3 +5,5 @@ LIBINT_ERI_MAX_AM = @ERI_MAX_AM@ LIBINT_ERI_DERIV = @LIBINT_ERI_DERIV@ LIBINT_CONTRACTED_INTS = @LIBINT_CONTRACTED_INTS@ LIBINT_SHELL_SET = @LIBINT_SHELL_SET@ +LIBINT_SHGSHELL_ORDERING = @LIBINT_SHGSHELL_ORDERING@ +LIBINT_SHGSHELL_ORDERING_STANDARD = @LIBINT_SHGSHELL_ORDERING_STANDARD@ diff --git a/src/lib/libint/Makefile.library b/src/lib/libint/Makefile.library index d2bffad5a..6622bb06f 100644 --- a/src/lib/libint/Makefile.library +++ b/src/lib/libint/Makefile.library @@ -9,6 +9,7 @@ TARGET_HEADERS = libint2_params.h libint2_types.h libint2_iface.h INCLUDE += -I. TRUESRC = $(shell echo `find . -name '*.cc' -exec echo -n '{} ' \;`) +TRUESRC += configuration.cc LIBOBJ = $(TRUESRC:%.cc=%.$(OBJSUF)) default:: $(TOPDIR)/lib/$(TARGET) local_install_generated_headers diff --git a/src/lib/libint/configuration.cc.cmake.in b/src/lib/libint/configuration.cc similarity index 100% rename from src/lib/libint/configuration.cc.cmake.in rename to src/lib/libint/configuration.cc diff --git a/tests/hartree-fock/hartree-fock++-validate.py b/tests/hartree-fock/hartree-fock++-validate.py index d42ae0bb6..164011303 100644 --- a/tests/hartree-fock/hartree-fock++-validate.py +++ b/tests/hartree-fock/hartree-fock++-validate.py @@ -54,12 +54,22 @@ def validate(label, data, refdata, tolerance, textline): -8.04716669024124, 0.638204907990955, -6.35134519242917 ] Qtol = 1e-8 -smuref = [-muref[1]/2, muref[2], -muref[0]/2] +# * Note that the sphemultipole order is fixed at generator build time (not influenced by +# libint2::solid_harmonics_ordering()) +# * As of https://github.com/evaleev/libint/commit/cdbb9f3, sphemultipole is hard-coded at Standard +# (and not influenced by LIBINT_SHGSHELL_ORDERING) +smuref = [-muref[1]/2, muref[2], -muref[0]/2] # [ 0.046, -0.105, 0.132] smutol = 1e-9 sQref = [Qref[1]/4, -Qref[4]/2, (2*Qref[5] - Qref[0] - Qref[3])/4, -Qref[2]/2, (Qref[0] - Qref[3])/8 ] sQtol = 1e-8 +print("Checking sphemultipole Standard\n"); + +# Reference values from LIBINT_SHGSHELL_ORDERING=Gaussian. These are no longer accessible after cdbb9f3. +# print("Checking sphemultipole Gaussian\n"); +# smuref = [ muref[2], -muref[0]/2, -muref[1]/2] # [-0.105, 0.132, 0.046] +# sQref = [(2*Qref[5] - Qref[0] - Qref[3])/4, -Qref[2]/2, -Qref[4]/2, (Qref[0] - Qref[3])/8, Qref[1]/4] F1ref = [-5.43569555903312, -1.88298017654395, -2.17427822361352, 3.47022732536532, -2.96798871167808, 2.59189820350226, diff --git a/tests/hartree-fock/hartree-fock++.cc b/tests/hartree-fock/hartree-fock++.cc index 44af2b2f9..92fcea3b8 100644 --- a/tests/hartree-fock/hartree-fock++.cc +++ b/tests/hartree-fock/hartree-fock++.cc @@ -289,6 +289,8 @@ int main(int argc, char* argv[]) { // initializes the Libint integrals library ... now ready to compute libint2::initialize(); + libint2::set_solid_harmonics_ordering(libint2::SHGShellOrdering_Gaussian); + printf("Configuration G: sho=%d components=%s\n", libint2::solid_harmonics_ordering(), libint2::configuration_accessor().c_str()); // compute OBS non-negligible shell-pair list { diff --git a/tests/hartree-fock/hartree-fock.cc b/tests/hartree-fock/hartree-fock.cc index 8fa4ec19d..fecaae546 100644 --- a/tests/hartree-fock/hartree-fock.cc +++ b/tests/hartree-fock/hartree-fock.cc @@ -118,6 +118,7 @@ int main(int argc, char *argv[]) { // initializes the Libint integrals library ... now ready to compute libint2::initialize(); + printf("Configuration S: sho=%d components=%s\n", libint2::solid_harmonics_ordering(), libint2::configuration_accessor().c_str()); // compute overlap integrals auto S = compute_1body_ints(shells, Operator::overlap); diff --git a/tests/unit/test-1body.cc b/tests/unit/test-1body.cc index a36ddc6ca..3b94040dc 100644 --- a/tests/unit/test-1body.cc +++ b/tests/unit/test-1body.cc @@ -3,8 +3,6 @@ TEST_CASE_METHOD(libint2::unit::DefaultFixture, "electrostatic potential", "[engine][1-body]") { #if defined(LIBINT2_SUPPORT_ONEBODY) - if (LIBINT_SHGSHELL_ORDERING != LIBINT_SHGSHELL_ORDERING_STANDARD) - return; std::vector obs{ Shell{{1.0, 3.0}, {{2, true, {1.0, 0.3}}}, {{0.0, 0.0, 0.0}}}, @@ -19,7 +17,7 @@ TEST_CASE_METHOD(libint2::unit::DefaultFixture, "electrostatic potential", "[eng engine.prescale_by(scale); engine.compute(obs[0], obs[0]); { - std::vector shellset_ref = { + std::vector shellset_ref_standard = { -1.238239259091998e+01, 0.000000000000000e+00, 0.000000000000000e+00, -5.775996163160049e-02, 0.000000000000000e+00, 0.000000000000000e+00, @@ -33,15 +31,27 @@ TEST_CASE_METHOD(libint2::unit::DefaultFixture, "electrostatic potential", "[eng 0.000000000000000e+00, 1.139389632827834e-01, -1.478824785355970e-02, 0.000000000000000e+00, -1.241040347301479e+01}; + std::vector shellset_ref_gaussian = { + -1.343732979153083e+01, 0.000000000000000e+00, -6.796143730068988e-02, -1.478824785355970e-02, 0.000000000000000e+00, + 0.000000000000000e+00, -1.284475452992947e+01, 0.000000000000000e+00, 0.000000000000000e+00, -5.775996163160049e-02, + -6.796143730068988e-02, 0.000000000000000e+00, -1.301230978657952e+01, 1.139389632827834e-01, 0.000000000000000e+00, + -1.478824785355970e-02, 0.000000000000000e+00, 1.139389632827834e-01, -1.241040347301479e+01, 0.000000000000000e+00, + 0.000000000000000e+00, -5.775996163160049e-02, 0.000000000000000e+00, 0.000000000000000e+00, -1.238239259091998e+01}; for (int i = 0; i != 25; ++i) { - REQUIRE(engine.results()[0][i]/scale == Approx(shellset_ref[i])); + if (libint2::solid_harmonics_ordering() == libint2::SHGShellOrdering_Standard) { + if (i == 0) printf("Checking 1-body SHO=Standard\n"); + REQUIRE(engine.results()[0][i]/scale == Approx(shellset_ref_standard[i])); + } else { + if (i == 0) printf("Checking 1-body SHO=Gaussian\n"); + REQUIRE(engine.results()[0][i]/scale == Approx(shellset_ref_gaussian[i])); + } } } engine.prescale_by(1); engine.compute(obs[0], obs[1]); { - std::vector shellset_ref = { + std::vector shellset_ref_standard = { -4.769186621041819e-01, -9.303619356400431e-01, -1.559058302243514e+00, -9.290824121864600e-01, -5.835786921473129e-04, -1.159266418436018e+00, @@ -55,8 +65,18 @@ TEST_CASE_METHOD(libint2::unit::DefaultFixture, "electrostatic potential", "[eng -1.120272634615116e-03, -1.385603731947886e+00, -2.105750177166632e-03, 1.380654897976564e+00, 2.115041199099945e+00}; + std::vector shellset_ref_gaussian = { + 2.128355904665372e+00, 1.074590109905394e+00, 1.074249956874296e+00, -3.485163651594458e-03, -2.171951144148577e+00, + 9.566621490332916e-01, -3.760919234260182e-01, -8.344173649626901e-01, 1.660514988916377e+00, -1.160865205880651e+00, + 9.572841308198474e-01, -8.291498398421207e-01, -3.770080831197964e-01, -1.663667687168316e+00, -1.159266418436018e+00, + -2.105750177166632e-03, 1.380654897976564e+00, -1.385603731947886e+00, 2.115041199099945e+00, -1.120272634615116e-03, + -1.559058302243514e+00, -9.290824121864600e-01, -9.303619356400431e-01, -5.835786921473129e-04, -4.769186621041819e-01}; for (int i = 0; i != 25; ++i) { - REQUIRE(engine.results()[0][i] == Approx(shellset_ref[i])); + if (libint2::solid_harmonics_ordering() == libint2::SHGShellOrdering_Standard) { + REQUIRE(engine.results()[0][i] == Approx(shellset_ref_standard[i])); + } else { + REQUIRE(engine.results()[0][i] == Approx(shellset_ref_gaussian[i])); + } } } } diff --git a/tests/unit/test-c-api.cc b/tests/unit/test-c-api.cc index 100c33857..a5db68941 100644 --- a/tests/unit/test-c-api.cc +++ b/tests/unit/test-c-api.cc @@ -51,6 +51,9 @@ TEST_CASE("C API", "[c-api]") { engine.compute(sh1, sh2, sh3, sh4); cpp_result = engine.results()[0]; + printf("CMake Configuration (C) : %s\n", configuration_accessor()); + printf("CMake Configuration (C++): %s\n", libint2::configuration_accessor().c_str()); + unsigned int n1, n2, n3, n4; int a, b, c, d, abcd; n1 = (am1 + 1) * (am1 + 2)/2; diff --git a/tests/unit/test-shell-order.cc b/tests/unit/test-shell-order.cc index 61d350f72..93d38b644 100644 --- a/tests/unit/test-shell-order.cc +++ b/tests/unit/test-shell-order.cc @@ -35,11 +35,11 @@ TEST_CASE_METHOD(libint2::unit::DefaultFixture, "solid harmonics", "[engine]") { FOR_CART(ix, iy, iz, 1) int lm; if (ix == 1) { - lm = libint2::INT_SOLIDHARMINDEX(1, 1); + lm = libint2::INT_SOLIDHARMINDEX(libint2::solid_harmonics_ordering(), 1, 1); } else if (iy == 1) { - lm = libint2::INT_SOLIDHARMINDEX(1, -1); + lm = libint2::INT_SOLIDHARMINDEX(libint2::solid_harmonics_ordering(), 1, -1); } else if (iz == 1) { - lm = libint2::INT_SOLIDHARMINDEX(1, 0); + lm = libint2::INT_SOLIDHARMINDEX(libint2::solid_harmonics_ordering(), 1, 0); } for (int f2 = 0; f2 != 5; ++f2) { diff --git a/tests/unit/test.cc b/tests/unit/test.cc index 7727c80c1..5b21d2769 100644 --- a/tests/unit/test.cc +++ b/tests/unit/test.cc @@ -32,6 +32,9 @@ int main( int argc, char* argv[] ) // global setup... // initializes the Libint integrals library ... now ready to compute libint2::initialize(); + libint2::set_solid_harmonics_ordering(libint2::SHGShellOrdering_Standard); // redundant + printf("Configuration S: sho=%d components=%s\n", libint2::solid_harmonics_ordering(), libint2::configuration_accessor().c_str()); + printf("Supports: dddd=%d mmmm=%d FF=%d\n", libint2::supports("eri_dddd_d0"), libint2::supports("eri_mmmm_d0"), libint2::supports("eri_FF_d0")); #ifdef LIBINT_HAS_MPFR // default to 256 bits of precision for mpf_class diff --git a/tests/unit/test_g.cc b/tests/unit/test_g.cc new file mode 100644 index 000000000..997f523ae --- /dev/null +++ b/tests/unit/test_g.cc @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018-2023 Edward F. Valeev + * + * This file is part of Libint. + * + * Libint is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Libint is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Libint. If not, see . + * + */ + +#define CATCH_CONFIG_RUNNER + +#include "catch.hpp" +#include +#if !LIBINT2_CONSTEXPR_STATICS +# include +#endif + +int main( int argc, char* argv[] ) +{ + Catch::Session session; + // global setup... + // initializes the Libint integrals library ... now ready to compute + libint2::initialize(); + libint2::set_solid_harmonics_ordering(libint2::SHGShellOrdering_Gaussian); + printf("Configuration G: sho=%d components=%s\n", libint2::solid_harmonics_ordering(), libint2::configuration_accessor().c_str()); + +#ifdef LIBINT_HAS_MPFR + // default to 256 bits of precision for mpf_class + mpf_set_default_prec(256); +#endif + + int result = session.run( argc, argv ); + + libint2::finalize(); // done with libint + + return result; +}