diff --git a/include/integrals/property_types.hpp b/include/integrals/property_types.hpp new file mode 100644 index 00000000..67eeb5d2 --- /dev/null +++ b/include/integrals/property_types.hpp @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** @file property_types.hpp + * + * Property types defined by the Integrals library are defined here. It's likely + * that this file will be moved into a distinct subdirectory if more property + * types are added in the future. + */ +#pragma once +#include +#include + +/** @namespace integrals::property_types + * + * @brief The namespace for property types defined by the Integrals library + */ +namespace integrals::property_types { + +using decontract_basis_set = + simde::Convert; + +} // end namespace integrals::property_types diff --git a/src/integrals/integrals_mm.cpp b/src/integrals/integrals_mm.cpp index 7dd278a8..414b7923 100644 --- a/src/integrals/integrals_mm.cpp +++ b/src/integrals/integrals_mm.cpp @@ -16,6 +16,7 @@ #include "ao_integrals/ao_integrals.hpp" #include "libint/libint.hpp" +#include "utils/utils.hpp" #include namespace integrals { @@ -39,6 +40,7 @@ void set_defaults(pluginplay::ModuleManager& mm) { void load_modules(pluginplay::ModuleManager& mm) { ao_integrals::load_modules(mm); libint::load_modules(mm); + utils::load_modules(mm); set_defaults(mm); ao_integrals::set_defaults(mm); } diff --git a/src/integrals/utils/decontract_basis_set.cpp b/src/integrals/utils/decontract_basis_set.cpp new file mode 100644 index 00000000..c8f24831 --- /dev/null +++ b/src/integrals/utils/decontract_basis_set.cpp @@ -0,0 +1,61 @@ +/* + * 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 "utils.hpp" +#include + +namespace integrals::utils { + +using pt = integrals::property_types::decontract_basis_set; +using mol_basis_t = simde::type::ao_basis_set; +using abs_t = simde::type::atomic_basis_set; +using cg_t = simde::type::contracted_gaussian; +using doubles_t = std::vector; + +MODULE_CTOR(DecontractBasisSet) { + satisfies_property_type(); + description("Decontracts the input AO basis set"); +} + +MODULE_RUN(DecontractBasisSet) { + const auto& [input_bs] = pt::unwrap_inputs(inputs); + + // Decontracted primitives all have a coefficient of 1.0. + doubles_t coeffs{1.0}; + + // Loop over the shells in each atomic basis set and decontract them. + // For each primitive in a contracted Gaussian, make a new shell with + // only that primitive. + mol_basis_t output_bs; + for(const auto& abs : input_bs) { + abs_t new_abs(abs.basis_set_name(), abs.atomic_number(), + abs.center().as_point()); + for(const auto& shell : abs) { + for(const auto& prim : shell.contracted_gaussian()) { + doubles_t exponent{prim.exponent()}; + cg_t cg(coeffs.begin(), coeffs.end(), exponent.begin(), + exponent.end(), abs.center().as_point()); + new_abs.add_shell(shell.pure(), shell.l(), cg); + } + } + output_bs.add_center(new_abs); + } + + auto result = results(); + return pt::wrap_results(result, output_bs); +} + +} // end namespace integrals::utils diff --git a/src/integrals/utils/utils.hpp b/src/integrals/utils/utils.hpp new file mode 100644 index 00000000..5109d29e --- /dev/null +++ b/src/integrals/utils/utils.hpp @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/** @file utils.hpp + * + * Declaration of utility modules for the Integrals library, plus common + * infrastructural functions. + */ +#pragma once +#include +#include + +/** @namespace integrals::utils + * + * @brief The namespace for general utility modules for integrals + */ +namespace integrals::utils { + +DECLARE_MODULE(DecontractBasisSet); + +inline void set_defaults(pluginplay::ModuleManager& mm) {} + +inline void load_modules(pluginplay::ModuleManager& mm) { + mm.add_module("Decontract Basis Set"); + set_defaults(mm); +} + +} // end namespace integrals::utils diff --git a/tests/cxx/unit/integrals/testing.hpp b/tests/cxx/unit/integrals/testing.hpp index 2a5d549b..d1f4d338 100644 --- a/tests/cxx/unit/integrals/testing.hpp +++ b/tests/cxx/unit/integrals/testing.hpp @@ -112,6 +112,60 @@ inline simde::type::ao_basis_set water_sto3g_basis_set() { return bs; } +inline simde::type::ao_basis_set water_decontracted_sto3g_basis_set() { + using ao_basis_t = simde::type::ao_basis_set; + using atomic_basis_t = simde::type::atomic_basis_set; + using cg_t = simde::type::contracted_gaussian; + using point_t = simde::type::point; + using doubles_t = std::vector; + + auto mol = water_molecule(); + point_t r0 = mol[0].as_nucleus(); + point_t r1 = mol[1].as_nucleus(); + point_t r2 = mol[2].as_nucleus(); + + // This is the only coefficient needed. + doubles_t cs{1.0}; + + atomic_basis_t o("sto-3g", 8, r0); + doubles_t es0{130.7093200, 23.8088610, 6.4436083}; + doubles_t es1{5.0331513, 1.1695961, 0.3803890}; + + // Loops are ordered to match the order they would be decontracted in. + for(double e : es0) { + cg_t cg(cs.begin(), cs.end(), &e, &e + 1, r0); + o.add_shell(chemist::ShellType::pure, 0, cg); + } + for(double e : es1) { + cg_t cg(cs.begin(), cs.end(), &e, &e + 1, r0); + o.add_shell(chemist::ShellType::pure, 0, cg); + } + for(double e : es1) { + cg_t cg(cs.begin(), cs.end(), &e, &e + 1, r0); + o.add_shell(chemist::ShellType::pure, 1, cg); + } + + atomic_basis_t h0("sto-3g", 1, r1); + atomic_basis_t h1("sto-3g", 1, r2); + doubles_t es2{3.425250914, 0.6239137298, 0.1688554040}; + + // Again, the loops are to replicate the decontraction order. + for(double e : es2) { + cg_t cg(cs.begin(), cs.end(), &e, &e + 1, r1); + h0.add_shell(chemist::ShellType::pure, 0, cg); + } + for(double e : es2) { + cg_t cg(cs.begin(), cs.end(), &e, &e + 1, r2); + h1.add_shell(chemist::ShellType::pure, 0, cg); + } + + ao_basis_t bs; + bs.add_center(o); + bs.add_center(h0); + bs.add_center(h1); + return bs; +} + // Inputs for H2 tests inline simde::type::molecule h2_molecule() { using atom_t = simde::type::atom; diff --git a/tests/cxx/unit/integrals/utils/test_decontract_basis_set.cpp b/tests/cxx/unit/integrals/utils/test_decontract_basis_set.cpp new file mode 100644 index 00000000..19bdae4d --- /dev/null +++ b/tests/cxx/unit/integrals/utils/test_decontract_basis_set.cpp @@ -0,0 +1,39 @@ +/* + * 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 "../testing.hpp" +#include + +TEST_CASE("DecontractBasisSet") { + using test_pt = integrals::property_types::decontract_basis_set; + + pluginplay::ModuleManager mm; + integrals::load_modules(mm); + REQUIRE(mm.count("Decontract Basis Set")); + + // Get basis set + auto aobs = test::water_sto3g_basis_set(); + + // Get module + auto& mod = mm.at("Decontract Basis Set"); + + // Call module + auto decontracted_aobs = mod.run_as(aobs); + + // Check output + auto corr = test::water_decontracted_sto3g_basis_set(); + REQUIRE(decontracted_aobs == corr); +}