From 212fe4fbe3e29f78c03e06a3fe3fe8dd1b332c83 Mon Sep 17 00:00:00 2001 From: "Ryan M. Richard" Date: Tue, 23 Sep 2025 22:26:52 -0500 Subject: [PATCH 1/2] g2g seems to work --- CMakeLists.txt | 12 +++- src/scf/xc/gau2grid.cpp | 104 +++++++++++++++++++++++++++ src/scf/xc/xc.cpp | 1 + src/scf/xc/xc.hpp | 1 + tests/cxx/unit_tests/xc/gau2grid.cpp | 86 ++++++++++++++++++++++ 5 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 src/scf/xc/gau2grid.cpp create mode 100644 tests/cxx/unit_tests/xc/gau2grid.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9234844..d7128d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,11 +59,21 @@ cmaize_find_or_build_dependency( CMAKE_ARGS EIGEN_BUILD_TESTING=OFF ) +cmaize_find_or_build_dependency( + gau2grid + NAME Gau2grid + URL https://github.com/psi4/gau2grid + VERSION master + BUILD_TARGET gg + FIND_TARGET gg + +) + cmaize_add_library( scf SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/src/scf" INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include/scf" - DEPENDS "${DEPENDENCIES}" eigen + DEPENDS "${DEPENDENCIES}" eigen gau2grid ) if("${BUILD_TAMM_SCF}") diff --git a/src/scf/xc/gau2grid.cpp b/src/scf/xc/gau2grid.cpp new file mode 100644 index 0000000..389287a --- /dev/null +++ b/src/scf/xc/gau2grid.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2025 NWChemEx-Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "xc.hpp" +#include +#include + +namespace scf::xc { +namespace { +const auto desc = R"( + +CollocationMatrix +----------------- +)"; + +template +std::vector flatten_grid(const chemist::Grid& grid) { + std::vector flattened_grid; + flattened_grid.reserve(grid.size() * 3); + for(const auto& point : grid) { + flattened_grid.push_back(static_cast(point.point().x())); + flattened_grid.push_back(static_cast(point.point().y())); + flattened_grid.push_back(static_cast(point.point().z())); + } + return flattened_grid; +} + +} // namespace + +using pt = simde::CollocationMatrix; + +MODULE_CTOR(Gau2Grid) { + satisfies_property_type(); + + description(desc); +} + +MODULE_RUN(Gau2Grid) { + const auto& [grid, ao_basis] = pt::unwrap_inputs(inputs); + auto n_points = grid.size(); + + using float_type = double; + auto flattened_grid = flatten_grid(grid); + + tensorwrapper::allocator::Eigen allocator(get_runtime()); + tensorwrapper::shape::Smooth matrix_shape{ao_basis.n_aos(), n_points}; + tensorwrapper::layout::Physical layout(matrix_shape); + auto matrix_buffer = allocator.allocate(layout); + auto matrix_data = matrix_buffer->get_mutable_data(); + + std::size_t ao_i = 0; + for(const auto& atomic_basis : ao_basis) { + for(const auto& shell_i : atomic_basis) { + const auto& cg = shell_i.contracted_gaussian(); + const auto L = shell_i.l(); + const auto n_primitives = cg.size(); + const auto n_aos = shell_i.size(); + + // TODO: Expose exponent_data/coefficient_data methods for Shells + std::vector exponents(n_primitives); + std::vector coefficients(n_primitives); + std::vector center(3); + for(std::size_t i = 0; i < n_primitives; ++i) { + exponents[i] = cg.at(i).exponent(); + coefficients[i] = cg.at(i).coefficient(); + } + center[0] = shell_i.center().x(); + center[1] = shell_i.center().y(); + center[2] = shell_i.center().z(); + + auto is_pure = shell_i.pure() == chemist::ShellType::pure; + auto order = is_pure ? GG_SPHERICAL_CCA : GG_CARTESIAN_CCA; + + auto offset = ao_i * n_points; + + auto shell_i_data = matrix_data + offset; + gg_collocation(L, n_points, flattened_grid.data(), 3, n_primitives, + coefficients.data(), exponents.data(), center.data(), + order, shell_i_data); + ao_i += n_aos; + } + } + + simde::type::tensor collocation_matrix(matrix_shape, + std::move(matrix_buffer)); + + auto rv = results(); + return pt::wrap_results(rv, std::move(collocation_matrix)); +} + +} // namespace scf::xc diff --git a/src/scf/xc/xc.cpp b/src/scf/xc/xc.cpp index d09bf11..3378ffe 100644 --- a/src/scf/xc/xc.cpp +++ b/src/scf/xc/xc.cpp @@ -20,6 +20,7 @@ namespace scf::xc { void load_modules(pluginplay::ModuleManager& mm) { gauxc::load_modules(mm); + mm.add_module("Gau2Grid"); mm.add_module("Grid From File"); } diff --git a/src/scf/xc/xc.hpp b/src/scf/xc/xc.hpp index 9eb684e..275b806 100644 --- a/src/scf/xc/xc.hpp +++ b/src/scf/xc/xc.hpp @@ -19,6 +19,7 @@ namespace scf::xc { +DECLARE_MODULE(Gau2Grid); DECLARE_MODULE(GridFromFile); void set_defaults(pluginplay::ModuleManager& mm); diff --git a/tests/cxx/unit_tests/xc/gau2grid.cpp b/tests/cxx/unit_tests/xc/gau2grid.cpp new file mode 100644 index 0000000..d09f518 --- /dev/null +++ b/tests/cxx/unit_tests/xc/gau2grid.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2025 NWChemEx-Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../test_scf.hpp" +#include +#include + +using namespace scf; + +using pt = simde::CollocationMatrix; + +using tensorwrapper::operations::approximately_equal; + +TEST_CASE("Gau2Grid") { + pluginplay::ModuleManager mm; + scf::load_modules(mm); + auto& mod = mm.at("Gau2Grid"); + + using float_type = double; + using prim_type = chemist::basis_set::Primitive; + using cg_type = chemist::basis_set::ContractedGaussian; + using shell_type = chemist::basis_set::Shell; + using atomic_bs_type = chemist::basis_set::AtomicBasisSet; + using ao_basis_type = chemist::basis_set::AOBasisSet; + + auto cart = chemist::ShellType::cartesian; + auto pure = chemist::ShellType::pure; + + SECTION("Manual examples") { + // Taken from https://gau2grid.readthedocs.io/en/latest/c_example.html + + std::vector grid_points; + for(std::size_t i = 0; i < 5; ++i) + grid_points.push_back({1.0, 0.0, 0.0, static_cast(i)}); + chemist::Grid grid(grid_points.begin(), grid_points.end()); + + ao_basis_type ao_basis; + atomic_bs_type abs("n/a", 1, {0.0, 0.0, 0.0}); + + std::vector coefs{1.0}; + std::vector exps{1.0}; + cg_type cg(coefs.begin(), coefs.end(), exps.begin(), exps.end(), 0.0, + 0.0, 0.0); + + SECTION("Single Basis Function example") { + abs.add_shell(pure, 0, cg); + ao_basis.add_center(std::move(abs)); + auto rv = mod.run_as(grid, ao_basis); + simde::type::tensor corr{ + {1.0, 0.367879, 0.0183156, 0.00012341, 0.0}}; + REQUIRE(approximately_equal(rv, corr, 1e-6)); + } + + SECTION("Multiple Basis Function example") { + abs.add_shell(pure, 0, cg); + abs.add_shell(pure, 1, cg); + abs.add_shell(pure, 2, cg); + ao_basis.add_center(std::move(abs)); + auto rv = mod.run_as(grid, ao_basis); + simde::type::tensor corr{ + {1, 0.367879, 0.0183156, 0.00012341, 1.12535e-07}, + {0, 0, 0, 0, 0}, + {0, 0.367879, 0.0366313, 0.000370229, 4.50141e-07}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0.367879, 0.0732626, 0.00111069, 1.80056e-06}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}; + REQUIRE(approximately_equal(rv, corr, 1e-6)); + }; + } +} From 6bae5a995e4aabd62120268088cd9c4e23759ea4 Mon Sep 17 00:00:00 2001 From: "Ryan M. Richard" Date: Wed, 24 Sep 2025 09:35:53 -0500 Subject: [PATCH 2/2] remove unused variable --- tests/cxx/unit_tests/xc/gau2grid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cxx/unit_tests/xc/gau2grid.cpp b/tests/cxx/unit_tests/xc/gau2grid.cpp index d09f518..a269676 100644 --- a/tests/cxx/unit_tests/xc/gau2grid.cpp +++ b/tests/cxx/unit_tests/xc/gau2grid.cpp @@ -36,7 +36,7 @@ TEST_CASE("Gau2Grid") { using atomic_bs_type = chemist::basis_set::AtomicBasisSet; using ao_basis_type = chemist::basis_set::AOBasisSet; - auto cart = chemist::ShellType::cartesian; + // TODO: better testing auto cart = chemist::ShellType::cartesian; auto pure = chemist::ShellType::pure; SECTION("Manual examples") {