Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/enable_openmp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
set(INTEGRALS_ENABLE_OPENMP ON)
6 changes: 6 additions & 0 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ jobs:
with:
compilers: '["gcc-11", "clang-14"]'
repo_toolchain: ".github/enable_sigma.cmake"

test_enable_openmp:
uses: NWChemEx/.github/.github/workflows/test_nwx_library.yaml@master
with:
compilers: '["gcc-11", "clang-14"]'
repo_toolchain: ".github/enable_openmp.cmake"
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ cmaize_option_list(
BUILD_TESTING OFF "Should we build the tests?"
BUILD_PYBIND11_PYBINDINGS ON "Build pybind11 python3 bindings?"
ENABLE_SIGMA OFF "Should we enable Sigma for uncertainty tracking?"
INTEGRALS_ENABLE_OPENMP OFF "Should we enable OpenMP for threading?"
)

# Can't build from github due to Libint setup.
Expand All @@ -60,11 +61,18 @@ cmaize_find_or_build_dependency(
ENABLE_SIGMA=${ENABLE_SIGMA}
)

set(project_depends Libint2 simde)

if("${INTEGRALS_ENABLE_OPENMP}")
find_package( OpenMP REQUIRED )
list(APPEND project_depends OpenMP::OpenMP_CXX)
endif()

cmaize_add_library(
${PROJECT_NAME}
SOURCE_DIR "${INTEGRALS_SOURCE_DIR}/${PROJECT_NAME}"
INCLUDE_DIRS "${INTEGRALS_INCLUDE_DIR}/${PROJECT_NAME}"
DEPENDS Libint2 simde
DEPENDS "${project_depends}"
)

include(nwx_pybind11)
Expand Down
73 changes: 52 additions & 21 deletions src/integrals/libint/libint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,30 @@
#include "libint_visitor.hpp"
#include <type_traits>

#ifdef _OPENMP
#include <omp.h>
#endif

namespace integrals::libint {
namespace {

#ifdef _OPENMP
int get_num_threads() {
int num_threads;
#pragma omp parallel
{ num_threads = omp_get_num_threads(); }
return num_threads;
}

int get_thread_num() { return omp_get_thread_num(); }
#else

int get_num_threads() { return 1; }

int get_thread_num() { return 0; }

#endif

template<typename FloatType>
auto build_eigen_buffer(const std::vector<libint2::BasisSet>& basis_sets,
parallelzone::runtime::RuntimeView& rv, double thresh) {
Expand All @@ -52,25 +73,46 @@ template<std::size_t N, typename FloatType>
auto fill_tensor(const std::vector<libint2::BasisSet>& basis_sets,
const chemist::qm_operator::OperatorBase& op,
parallelzone::runtime::RuntimeView& rv, double thresh) {
using size_type = decltype(N);

// Dimensional information
std::vector<std::size_t> dims_shells(N);
for(decltype(N) i = 0; i < N; ++i) dims_shells[i] = basis_sets[i].size();
std::vector<size_type> dim_stepsizes(N, 1);
size_type num_shell_combinations = 1;

auto pbuffer = build_eigen_buffer<FloatType>(basis_sets, rv, thresh);
for(size_type i = 0; i < N; ++i) {
num_shell_combinations *= basis_sets[i].size();
for(size_type j = i; j < N - 1; ++j) {
dim_stepsizes[i] *= basis_sets[j].size();
}
}

// Make libint engine
// Make an engine for each thread
int num_threads = get_num_threads();
std::vector<libint2::Engine> engines(num_threads);
LibintVisitor visitor(basis_sets, thresh);
op.visit(visitor);
auto engine = visitor.engine();
const auto& buf = engine.results();
for(int i = 0; i != num_threads; ++i) { engines[i] = visitor.engine(); }

// Fill in values
std::vector<std::size_t> shells(N, 0);
while(shells[0] < dims_shells[0]) {
detail_::run_engine_(engine, basis_sets, shells,
auto pbuffer = build_eigen_buffer<FloatType>(basis_sets, rv, thresh);
#ifdef _OPENMP
#pragma omp parallel for
#endif
for(size_type i_pair = 0; i_pair != num_shell_combinations; ++i_pair) {
auto thread_id = get_thread_num();

std::vector<size_type> shells(N);
auto shell_ord = i_pair;
for(size_type i = 0; i < N; ++i) {
shells[i] = shell_ord / dim_stepsizes[i];
shell_ord = shell_ord % dim_stepsizes[i];
}

detail_::run_engine_(engines[thread_id], basis_sets, shells,
std::make_index_sequence<N>());

auto vals = buf[0];
const auto& buf = engines[thread_id].results();
auto vals = buf[0];
if(vals) {
auto ord = detail_::shells2ord(basis_sets, shells);
auto n_ord = ord.size();
Expand All @@ -79,17 +121,6 @@ auto fill_tensor(const std::vector<libint2::BasisSet>& basis_sets,
pbuffer->set_data(ord[i_ord], update);
}
}

// Increment index
shells[N - 1] += 1;
for(decltype(N) i = 1; i < N; ++i) {
if(shells[N - i] >= dims_shells[N - i]) {
// Reset this dimension and increment the next one
// shells[0] accumulates until we reach the end
shells[N - i] = 0;
shells[N - i - 1] += 1;
}
}
}

auto pshape = pbuffer->layout().shape().clone();
Expand Down