Skip to content

Commit ab5780a

Browse files
Adds building E_xc and V_xc via LibXC (#50)
* g2g seems to work * backup * density2grid works (I think) * fix warnings * it freaking works!!!! * vxc done too!!! * fix warnings * fix warning * Update CMakeLists.txt Co-authored-by: Jonathan M. Waldrop <relik107@gmail.com> * make libxc optional * jonathan's suggestions * formatting --------- Co-authored-by: Jonathan M. Waldrop <relik107@gmail.com>
1 parent c75f82b commit ab5780a

21 files changed

Lines changed: 88582 additions & 53 deletions

CMakeLists.txt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,19 @@ set(SCF_TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests")
3232
nwx_cxx_api_docs("${SCF_SOURCE_DIR}" "${SCF_INCLUDE_DIR}")
3333

3434
### Options ###
35+
3536
cmaize_option_list(
3637
BUILD_TESTING OFF "Should we build the tests?"
3738
BUILD_PYBIND11_PYBINDINGS ON "Build Python bindings with pybind11?"
3839
BUILD_TAMM_SCF OFF "Should we build modules that rely on TAMM/Exachem?"
40+
BUILD_LIBXC ON "Should we build libxc?"
3941
INTEGRATION_TESTING OFF "Should we build the integration tests?"
4042
)
43+
44+
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
45+
set(BUILD_LIBXC OFF)
46+
endif()
47+
4148
if("${BUILD_TAMM_SCF}")
4249
set(DEPENDENCIES simde gauxc tamm exachem chemcache)
4350
include(get_libint2)
@@ -69,11 +76,25 @@ cmaize_find_or_build_dependency(
6976

7077
)
7178

79+
set(BUILD_TESTING_BACKUP ${BUILD_TESTING})
80+
set(BUILD_TESTING OFF)
81+
cmaize_find_or_build_optional_dependency(
82+
libxc
83+
BUILD_LIBXC
84+
NAME libxc
85+
URL https://gitlab.com/libxc/libxc
86+
VERSION devel
87+
BUILD_TARGET xc
88+
FIND_TARGET xc
89+
CMAKE_ARGS BUILD_TESTING=OFF
90+
)
91+
set(BUILD_TESTING ${BUILD_TESTING_BACKUP})
92+
7293
cmaize_add_library(
7394
scf
7495
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/src/scf"
7596
INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include/scf"
76-
DEPENDS "${DEPENDENCIES}" eigen gau2grid
97+
DEPENDS "${DEPENDENCIES}" eigen gau2grid libxc
7798
)
7899

79100
if("${BUILD_TAMM_SCF}")

src/scf/xc/aos_on_grid.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2025 NWChemEx-Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "xc.hpp"
18+
#include <simde/integration_grids/collocation_matrix.hpp>
19+
20+
namespace scf::xc {
21+
namespace {
22+
const auto desc = R"(
23+
24+
AO CollocationMatrix
25+
-----------------
26+
)";
27+
28+
} // namespace
29+
30+
using pt = simde::AOCollocationMatrix;
31+
32+
MODULE_CTOR(AOsOnGrid) {
33+
satisfies_property_type<pt>();
34+
description(desc);
35+
}
36+
37+
MODULE_RUN(AOsOnGrid) {
38+
const auto& [grid, ao_basis] = pt::unwrap_inputs(inputs);
39+
auto n_points = grid.size();
40+
auto n_aos = ao_basis.n_aos();
41+
using float_type = double;
42+
43+
tensorwrapper::allocator::Eigen<float_type> allocator(get_runtime());
44+
tensorwrapper::shape::Smooth matrix_shape{n_aos, n_points};
45+
tensorwrapper::layout::Physical layout(matrix_shape);
46+
auto buffer = allocator.allocate(layout);
47+
48+
std::vector<std::size_t> idx{0, 0};
49+
for(const auto& atomic_basis : ao_basis) {
50+
for(const auto& shell_i : atomic_basis) {
51+
assert(shell_i.l() == 0); // only s is supported for now
52+
const auto& cg = shell_i.contracted_gaussian();
53+
for(; idx[1] < n_points; ++idx[1]) {
54+
float_type ao_value = 0.0;
55+
for(const auto& prim : cg) {
56+
// TODO: update when eval accounts for normalization
57+
const auto val = prim.evaluate(grid.at(idx[1]).point());
58+
const auto exponent = prim.exponent();
59+
auto norm = std::sqrt(std::pow(2.0 * exponent / M_PI, 1.5));
60+
ao_value += norm * val;
61+
}
62+
buffer->set_elem(idx, ao_value);
63+
}
64+
idx[0] += shell_i.size();
65+
idx[1] = 0;
66+
}
67+
}
68+
simde::type::tensor collocation_matrix(matrix_shape, std::move(buffer));
69+
auto rv = results();
70+
return pt::wrap_results(rv, std::move(collocation_matrix));
71+
};
72+
73+
} // namespace scf::xc

src/scf/xc/density2grid.cpp

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "libxc/libxc.hpp"
1718
#include "xc.hpp"
1819
#include <simde/integration_grids/collocation_matrix.hpp>
1920

@@ -25,38 +26,6 @@ DensityCollocationMatrix
2526
-----------------
2627
)";
2728

28-
struct Kernel {
29-
using buffer_base = tensorwrapper::buffer::BufferBase;
30-
31-
template<typename FloatType>
32-
auto run(const buffer_base& aos_on_grid, const buffer_base& X,
33-
parallelzone::runtime::RuntimeView& rv) {
34-
tensorwrapper::allocator::Eigen<FloatType> allocator(rv);
35-
36-
const auto& eigen_aos_on_grid = allocator.rebind(aos_on_grid);
37-
const auto* paos_on_grid = eigen_aos_on_grid.get_immutable_data();
38-
const auto& eigen_X = allocator.rebind(X);
39-
const auto* pX = eigen_X.get_immutable_data();
40-
const auto& shape_X = eigen_X.layout().shape().as_smooth();
41-
auto n_aos = shape_X.extent(0);
42-
auto n_grid = shape_X.extent(1);
43-
44-
tensorwrapper::shape::Smooth rv_shape{n_grid};
45-
tensorwrapper::layout::Physical rv_layout(rv_shape);
46-
auto rv_buffer = allocator.allocate(rv_layout);
47-
48-
// AOs on rows, grid points on columns
49-
for(std::size_t grid_i = 0; grid_i < n_grid; ++grid_i) {
50-
FloatType sum = 0;
51-
for(std::size_t ao_i = 0; ao_i < n_aos; ++ao_i) {
52-
const auto idx = ao_i * n_grid + grid_i;
53-
sum += paos_on_grid[idx] * pX[idx];
54-
}
55-
rv_buffer->set_elem(std::vector{grid_i}, sum);
56-
}
57-
return simde::type::tensor(rv_shape, std::move(rv_buffer));
58-
}
59-
};
6029
} // namespace
6130

6231
using pt = simde::EDensityCollocationMatrix;
@@ -78,16 +47,11 @@ MODULE_RUN(Density2Grid) {
7847
auto& ao2grid_mod = submods.at("AOs on a grid");
7948
auto aos_on_grid = ao2grid_mod.run_as<ao2grid_pt>(grid, aos);
8049

81-
simde::type::tensor X;
82-
X("m,i") = rho("m,n") * aos_on_grid("n,i");
50+
simde::type::tensor X, rho2;
51+
rho2("m,n") = rho("m,n") * 2.0; // Assumes restricted orbitals
52+
X("m,i") = rho2("m,n") * aos_on_grid("n,i");
8353

84-
using tensorwrapper::utilities::floating_point_dispatch;
85-
Kernel k;
86-
auto& runtime = get_runtime();
87-
const auto& aos_buffer = aos_on_grid.buffer();
88-
const auto& X_buffer = X.buffer();
89-
auto rho_on_grid =
90-
floating_point_dispatch(k, aos_buffer, X_buffer, runtime);
54+
auto rho_on_grid = libxc::batched_dot(aos_on_grid, X);
9155

9256
auto rv = results();
9357
return pt::wrap_results(rv, std::move(rho_on_grid));

src/scf/xc/gau2grid.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ const auto desc = R"(
2424
2525
CollocationMatrix
2626
-----------------
27+
28+
Warning! Gau2Grid assumes that the primitive normalization has been folded into
29+
the contraction coefficients!!!
2730
)";
2831

2932
template<typename T>
@@ -73,6 +76,7 @@ MODULE_RUN(Gau2Grid) {
7376
std::vector<double> exponents(n_primitives);
7477
std::vector<double> coefficients(n_primitives);
7578
std::vector<double> center(3);
79+
7680
for(std::size_t i = 0; i < n_primitives; ++i) {
7781
exponents[i] = cg.at(i).exponent();
7882
coefficients[i] = cg.at(i).coefficient();
@@ -84,12 +88,14 @@ MODULE_RUN(Gau2Grid) {
8488
auto is_pure = shell_i.pure() == chemist::ShellType::pure;
8589
auto order = is_pure ? GG_SPHERICAL_CCA : GG_CARTESIAN_CCA;
8690

87-
auto offset = ao_i * n_points;
88-
91+
auto offset = ao_i * n_points;
8992
auto shell_i_data = matrix_data + offset;
90-
gg_collocation(L, n_points, flattened_grid.data(), 3, n_primitives,
91-
coefficients.data(), exponents.data(), center.data(),
92-
order, shell_i_data);
93+
gg_collocation(static_cast<int>(L), static_cast<int>(n_points),
94+
flattened_grid.data(), 3,
95+
static_cast<int>(n_primitives), coefficients.data(),
96+
exponents.data(), center.data(), order,
97+
shell_i_data);
98+
9399
ao_i += n_aos;
94100
}
95101
}

0 commit comments

Comments
 (0)