From aed06c55e232964cf719468c9d991dedfbad3c25 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 1 Feb 2024 08:29:47 -0500 Subject: [PATCH 1/5] fix BOOST_PP-related dispatch bug that affects 3-center derivatives when configured with `--with-max-am=X --with-eri3-max-am=Y` If `AB` is `#define`d `BOOST_PP_CAT(AB,C) = BOOST_PP_CAT(BOOST_PP_CAT(A,B),C) != BOOST_PP_CAT(A,BOOST_PP_CAT(B,C))` ... else all are equivalent --- include/libint2/engine.impl.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/include/libint2/engine.impl.h b/include/libint2/engine.impl.h index 23751c666..29d7552ea 100644 --- a/include/libint2/engine.impl.h +++ b/include/libint2/engine.impl.h @@ -1827,13 +1827,16 @@ __libint2_engine_inline const Engine::target_ptr_vec& Engine::compute2( /// lmax might be center dependent int ket_lmax = hard_lmax_; switch (deriv_order_) { -#define BOOST_PP_NBODYENGINE_MCR8(r, data, i, elem) \ - case i: \ - BOOST_PP_IF( \ - BOOST_PP_IS_1(BOOST_PP_CAT( \ - LIBINT2_CENTER_DEPENDENT_MAX_AM_3eri, \ - BOOST_PP_IIF(BOOST_PP_GREATER(i, 0), i, BOOST_PP_EMPTY()))), \ - ket_lmax = hard_default_lmax_, BOOST_PP_EMPTY()); \ + // N.B. notice extra PP_CAT to avoid using + // LIBINT2_CENTER_DEPENDENT_MAX_AM_3eri as a subtoken which gets + // expanded too early ... i.e. PP_CAT is "not associative" +#define BOOST_PP_NBODYENGINE_MCR8(r, data, i, elem) \ + case i: \ + BOOST_PP_IF(BOOST_PP_IS_1(BOOST_PP_CAT( \ + LIBINT2_CENTER_DEPENDENT_MAX_AM_, \ + BOOST_PP_CAT(3eri, BOOST_PP_IIF(BOOST_PP_GREATER(i, 0), i, \ + BOOST_PP_EMPTY())))), \ + ket_lmax = hard_default_lmax_, BOOST_PP_EMPTY()); \ break; BOOST_PP_LIST_FOR_EACH_I(BOOST_PP_NBODYENGINE_MCR8, _, From 131b1802d20936e883b44c637339226565a0cfc8 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 1 Feb 2024 10:48:29 -0500 Subject: [PATCH 2/5] [ci] reduce default max l for 1st derivatives to l=1 from l=2 to be able to test issue exposed in https://github.com/evaleev/libint/pull/308 --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ce187abc9..5d5b2c4e6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -105,7 +105,7 @@ jobs: shell: bash working-directory: ${{github.workspace}}/build/compiler run: | - CPPFLAGS="-I$EIGEN3_INCLUDE_DIR" CXXFLAGS="-std=c++11 -Wno-enum-compare" ${{github.workspace}}/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 + CPPFLAGS="-I$EIGEN3_INCLUDE_DIR" CXXFLAGS="-std=c++11 -Wno-enum-compare" ${{github.workspace}}/configure --with-max-am=2,1 --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 make -j3 make check cd src/bin/test_eri && ./stdtests.pl && cd ../../.. From 2f367de3da3ab9e72589dc9811a20c37f8ab20bc Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Thu, 1 Feb 2024 10:49:44 -0500 Subject: [PATCH 3/5] eritest of exported library: increase max l for 1st-order derivative tests to 2, unless this is a Debug build --- export/cmake/CMakeLists.txt.export | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/export/cmake/CMakeLists.txt.export b/export/cmake/CMakeLists.txt.export index 6e8c0631a..b010798d2 100644 --- a/export/cmake/CMakeLists.txt.export +++ b/export/cmake/CMakeLists.txt.export @@ -395,8 +395,13 @@ add_test(NAME libint2/eritest/run0 COMMAND $ 0 2) set_tests_properties(libint2/eritest/run0 PROPERTIES FIXTURES_REQUIRED LIBINT2_ERITEST_EXEC) +if (CMAKE_BUILD_TYPE STREQUAL "Debug") # OK to run l=2 gradients with optimization + set(LIBINT2_ERITEST_RUN1_LMAX 1) +else() + set(LIBINT2_ERITEST_RUN1_LMAX 2) +endif() add_test(NAME libint2/eritest/run1 - COMMAND $ 1 1) + COMMAND $ 1 ${LIBINT2_ERITEST_RUN1_LMAX}) set_tests_properties(libint2/eritest/run1 PROPERTIES FIXTURES_REQUIRED LIBINT2_ERITEST_EXEC) add_test(NAME libint2/eritest/run2 From aa77bd53e3aef52823fd12f2373080bda4bcc136 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Mon, 5 Feb 2024 00:54:32 -0500 Subject: [PATCH 4/5] [unit] 3eri permute test needs to limit shell sets to those supported by Engine --- tests/unit/test-permute.cc | 54 ++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/tests/unit/test-permute.cc b/tests/unit/test-permute.cc index dde543c8d..06bb48720 100644 --- a/tests/unit/test-permute.cc +++ b/tests/unit/test-permute.cc @@ -231,23 +231,6 @@ void validate3(const BasisSet& obs, const BasisSet& dfbs, if (deriv_order > LIBINT2_DERIV_ERI_ORDER || deriv_order > LIBINT2_DERIV_ERI3_ORDER) return; - switch (deriv_order) { - case 0: - if (max_l > LIBINT2_MAX_AM_eri || max_l > LIBINT2_MAX_AM_3eri) return; - break; - case 1: -#if LIBINT2_DERIV_ERI_ORDER > 0 && LIBINT2_DERIV_ERI3_ORDER > 0 - if (max_l > LIBINT2_MAX_AM_eri1 || max_l > LIBINT2_MAX_AM_3eri1) return; -#endif - break; - case 2: -#if LIBINT2_DERIV_ERI_ORDER > 1 && LIBINT2_DERIV_ERI3_ORDER > 1 - if (max_l > LIBINT2_MAX_AM_eri2 || max_l > LIBINT2_MAX_AM_3eri2) return; -#endif - break; - default: - abort(); - } const auto xsxx = LIBINT_SHELL_SET == LIBINT_SHELL_SET_STANDARD; if (!xsxx) return; // not yet implemented const auto abs_precision = deriv_order == 1 ? 1e-12 : 1e-13; @@ -271,6 +254,43 @@ void validate3(const BasisSet& obs, const BasisSet& dfbs, for (auto s2 = 0; s2 != obs.size(); ++s2) { for (auto s3 = 0; s3 != obs.size(); ++s3) { assert(xsxx); + + // skip if angular momenta are too high + const auto max_orb_l = std::max(obs[s2].contr[0].l, obs[s3].contr[0].l); + const auto max_l = std::max(dfbs[s1].contr[0].l, max_orb_l); + auto max_l_exceeded = false; + switch (deriv_order) { + case 0: + if (max_l > LIBINT2_MAX_AM_eri || max_l > LIBINT2_MAX_AM_3eri) + max_l_exceeded = true; +#ifdef LIBINT2_CENTER_DEPENDENT_MAX_AM_3eri + if (max_orb_l > LIBINT2_MAX_AM_default) max_l_exceeded = true; +#endif + break; + + case 1: +#if LIBINT2_DERIV_ERI_ORDER > 0 && LIBINT2_DERIV_ERI3_ORDER > 0 + if (max_l > LIBINT2_MAX_AM_eri1 || max_l > LIBINT2_MAX_AM_3eri1) + max_l_exceeded = true; +#ifdef LIBINT2_CENTER_DEPENDENT_MAX_AM_3eri1 + if (max_orb_l > LIBINT2_MAX_AM_default1) max_l_exceeded = true; +#endif +#endif + break; + case 2: +#if LIBINT2_DERIV_ERI_ORDER > 1 && LIBINT2_DERIV_ERI3_ORDER > 1 + if (max_l > LIBINT2_MAX_AM_eri2 || max_l > LIBINT2_MAX_AM_3eri2) + max_l_exceeded = true; +#ifdef LIBINT2_CENTER_DEPENDENT_MAX_AM_3eri1 + if (max_orb_l > LIBINT2_MAX_AM_default2) max_l_exceeded = true; +#endif +#endif + break; + default: + abort(); + } + if (max_l_exceeded) continue; + engine_ref.compute(dfbs[s1], Shell::unit(), obs[s2], obs[s3]); const auto& shellset_ref = From 26aaad7e9d7684a82fa257335606aff8f87808a5 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Mon, 5 Feb 2024 00:56:04 -0500 Subject: [PATCH 5/5] Engine: ensure that angular momenta are not exceeded more carefully; for center-dependent momenta could yield (incorrect) result for angular momenta outside the supported range --- include/libint2/engine.impl.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/libint2/engine.impl.h b/include/libint2/engine.impl.h index 29d7552ea..dab49f8f4 100644 --- a/include/libint2/engine.impl.h +++ b/include/libint2/engine.impl.h @@ -1170,7 +1170,9 @@ __libint2_engine_inline const Engine::target_ptr_vec& Engine::compute2( tket2.ncontr() == 1) && "generally-contracted shells are not yet supported"); - // angular momentum limit obeyed? + // angular momentum limit obeyed? can only be fully checked in + // braket-dependent code, here only do a basic test that does not guarantee + // that the shell-set can be computed assert(tbra1.contr[0].l <= lmax_ && "the angular momentum limit is exceeded"); assert(tbra2.contr[0].l <= lmax_ && "the angular momentum limit is exceeded"); assert(tket1.contr[0].l <= lmax_ && "the angular momentum limit is exceeded"); @@ -1812,6 +1814,14 @@ __libint2_engine_inline const Engine::target_ptr_vec& Engine::compute2( size_t buildfnidx; switch (braket_) { case BraKet::xx_xx: + assert(bra1.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); + assert(bra2.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); + assert(ket1.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); + assert(ket2.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); buildfnidx = ((bra1.contr[0].l * hard_lmax_ + bra2.contr[0].l) * hard_lmax_ + ket1.contr[0].l) * @@ -1846,6 +1856,12 @@ __libint2_engine_inline const Engine::target_ptr_vec& Engine::compute2( assert(false && "missing case in switch"); abort(); } + assert(bra1.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); + assert(ket1.contr[0].l <= ket_lmax && + "the angular momentum limit is exceeded"); + assert(ket2.contr[0].l <= ket_lmax && + "the angular momentum limit is exceeded"); buildfnidx = (bra1.contr[0].l * ket_lmax + ket1.contr[0].l) * ket_lmax + ket2.contr[0].l; #ifdef ERI3_PURE_SH @@ -1857,6 +1873,10 @@ __libint2_engine_inline const Engine::target_ptr_vec& Engine::compute2( } break; case BraKet::xs_xs: + assert(bra1.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); + assert(ket1.contr[0].l <= hard_lmax_ && + "the angular momentum limit is exceeded"); buildfnidx = bra1.contr[0].l * hard_lmax_ + ket1.contr[0].l; #ifdef ERI2_PURE_SH if (bra1.contr[0].l > 1)