Skip to content

Commit

Permalink
Merge pull request #324 from evaleev/308-assertion-failure-crash-whil…
Browse files Browse the repository at this point in the history
…e-computing-3-center-eri-derivatives

fix BOOST_PP-related dispatch bug that affects 3-center derivatives when configured with `--with-max-am=X --with-eri3-max-am=Y`
  • Loading branch information
evaleev authored Feb 5, 2024
2 parents dd8089a + 26aaad7 commit 1ccdad4
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ../../..
Expand Down
7 changes: 6 additions & 1 deletion export/cmake/CMakeLists.txt.export
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,13 @@ add_test(NAME libint2/eritest/run0
COMMAND $<TARGET_FILE:eritest-libint2> 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 $<TARGET_FILE:eritest-libint2> 1 1)
COMMAND $<TARGET_FILE:eritest-libint2> 1 ${LIBINT2_ERITEST_RUN1_LMAX})
set_tests_properties(libint2/eritest/run1
PROPERTIES FIXTURES_REQUIRED LIBINT2_ERITEST_EXEC)
add_test(NAME libint2/eritest/run2
Expand Down
39 changes: 31 additions & 8 deletions include/libint2/engine.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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) *
Expand All @@ -1827,13 +1837,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, _,
Expand All @@ -1843,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
Expand All @@ -1854,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)
Expand Down
54 changes: 37 additions & 17 deletions tests/unit/test-permute.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 =
Expand Down

0 comments on commit 1ccdad4

Please sign in to comment.