diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1c27bb2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,110 @@ +# Copyright 2022 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. + +--- +Language: Cpp +# BasedOnStyle: Mozilla +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakAfterJavaFieldAnnotations: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^"' + Priority: 1 + - Regex: '^<' + Priority: 2 +IncludeIsMainRegex: '(Test)$' +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/.github/optional_modules.cmake b/.github/optional_modules.cmake index 56a3cb1..86644cb 100644 --- a/.github/optional_modules.cmake +++ b/.github/optional_modules.cmake @@ -1,2 +1,2 @@ set(INTEGRATION_TESTING FALSE) -set(BUILD_TAMM_SCF TRUE) \ No newline at end of file +set(BUILD_TAMM_SCF FALSE) \ No newline at end of file diff --git a/docs/source/scf_architecture.png b/docs/source/scf_architecture.png new file mode 100644 index 0000000..5db8b9a Binary files /dev/null and b/docs/source/scf_architecture.png differ diff --git a/tests/cxx/unit_tests/stub.cpp b/src/scf/fock_operator/fock_operator.hpp similarity index 50% rename from tests/cxx/unit_tests/stub.cpp rename to src/scf/fock_operator/fock_operator.hpp index ebcfb0b..48841b7 100644 --- a/tests/cxx/unit_tests/stub.cpp +++ b/src/scf/fock_operator/fock_operator.hpp @@ -14,8 +14,22 @@ * limitations under the License. */ -#include -#include -#include +#pragma once +#include -TEST_CASE("Stub Test") {} \ No newline at end of file +namespace scf::fock_operator { + +template +DECLARE_MODULE(Restricted); + +inline void load_modules(pluginplay::ModuleManager& mm) { + using simde::type::decomposable_e_density; + using simde::type::e_density; + mm.add_module>("AO Restricted Fock Op"); + mm.add_module>("Restricted Fock Op"); +} + +extern template class Restricted; +extern template class Restricted; + +} // namespace scf::fock_operator \ No newline at end of file diff --git a/src/scf/fock_operator/restricted.cpp b/src/scf/fock_operator/restricted.cpp new file mode 100644 index 0000000..0bb90e2 --- /dev/null +++ b/src/scf/fock_operator/restricted.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2024 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 "fock_operator.hpp" + +namespace scf::fock_operator { + +template +class RestrictedVisitor : public chemist::qm_operator::OperatorVisitor { +public: + using many_electrons = simde::type::many_electrons; + using J_type = chemist::qm_operator::Coulomb; + using K_type = chemist::qm_operator::Exchange; + + using T_e_term = simde::type::T_e_type; + using V_en_term = simde::type::V_en_type; + using V_ee_term = simde::type::V_ee_type; + using V_nn_term = simde::type::V_nn_type; + + RestrictedVisitor(simde::type::fock& F, const DensityType& rho) : + m_pF_(&F), m_prho_(&rho) {} + + void run(const T_e_term& T_e) { m_pF_->emplace_back(1.0, T_e.clone()); } + + void run(const V_en_term& V_en) { m_pF_->emplace_back(1.0, V_en.clone()); } + + void run(const V_ee_term& V_ee) { + auto es = V_ee.at<0>(); + m_pF_->emplace_back(2.0, std::make_unique(es, *m_prho_)); + m_pF_->emplace_back(-1.0, std::make_unique(es, *m_prho_)); + } + +private: + simde::type::fock* m_pF_; + const DensityType* m_prho_; +}; + +const auto desc = R"( +Restricted Fock Operator Builder +-------------------------------- + +This module builds the Fock operator given a restricted density. Under this +assumption, the Fock operator is created by mapping each term in the +electronic Hamiltonian to itself with the exception of the electron-electron +repulsion. The electron-electron repulsion is mapped to 2J-K where J is the +Coulomb operator for the electrons interacting with a density and K is the +exchange operator for the same density. +)"; + +template +TEMPLATED_MODULE_CTOR(Restricted, DensityType) { + using pt = simde::FockOperator; + satisfies_property_type(); + description(desc); +} + +template +TEMPLATED_MODULE_RUN(Restricted, DensityType) { + using pt = simde::FockOperator; + using simde::type::many_electrons; + + const auto& [H, rho] = pt::unwrap_inputs(inputs); + auto H_elec = H.electronic_hamiltonian(); + + simde::type::fock F; + RestrictedVisitor visitor(F, rho); + H_elec.visit(visitor); + + auto rv = results(); + return pt::wrap_results(rv, F); +} + +template class Restricted; +template class Restricted; + +} // namespace scf::fock_operator \ No newline at end of file diff --git a/src/scf/scf_mm.cpp b/src/scf/scf_mm.cpp index 43354f8..e43f449 100644 --- a/src/scf/scf_mm.cpp +++ b/src/scf/scf_mm.cpp @@ -14,14 +14,16 @@ * limitations under the License. */ +#include "fock_operator/fock_operator.hpp" #include "scf_modules.hpp" #include namespace scf { -void load_modules(pluginplay::ModuleManager &mm) { +void load_modules(pluginplay::ModuleManager& mm) { + fock_operator::load_modules(mm); #ifdef BUILD_TAMM_SCF - mm.add_module("SCF Energy via TAMM"); + mm.add_module("SCF Energy via TAMM"); #endif } diff --git a/tests/cxx/test_scf.hpp b/tests/cxx/test_scf.hpp new file mode 100644 index 0000000..45d0e21 --- /dev/null +++ b/tests/cxx/test_scf.hpp @@ -0,0 +1,119 @@ +/* + * Copyright 2024 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. + */ +#pragma once +#include +#include +#include +#include + +namespace test_scf { + +/// Makes a H nucleus at the point @p x, @p y, @p z +inline auto h_nucleus(double x, double y, double z) { + return simde::type::nucleus("H", 1ul, 1836.15, x, y, z); +} + +template +ResultType make_h2() { + using simde::type::chemical_system; + using simde::type::molecule; + using simde::type::nuclei; + if constexpr(std::is_same_v) { + auto h0 = h_nucleus(0.0, 0.0, 0.0); + auto h1 = h_nucleus(0.0, 0.0, 1.3984); + return nuclei{h0, h1}; + } else if constexpr(std::is_same_v) { + return molecule(0, 1, make_h2()); + } else if constexpr(std::is_same_v) { + return chemical_system(make_h2()); + } else { + // We know this assert fails if we're in the else statement + // Getting here means you provided a bad type. + static_assert(std::is_same_v); + } +} + +// Applies the STO-3G basis to a Nuclei object filled with hydrogens +template +inline auto h_basis(NucleiType& hydrogens) { + using ao_basis_type = chemist::basis_set::AOBasisSetD; + using atomic_basis_type = typename ao_basis_type::value_type; + using shell_type = typename atomic_basis_type::value_type; + using contracted_gaussian_type = typename shell_type::cg_type; + using center_type = typename atomic_basis_type::shell_traits::center_type; + + std::vector h_coefs{0.1543289673, 0.5353281423, 0.4446345422}; + std::vector h_exps{3.425250914, 0.6239137298, 0.1688554040}; + auto cartesian = shell_type::pure_type::cartesian; + shell_type::angular_momentum_type l0{0}; + + ao_basis_type rv; + for(std::size_t i = 0; i < hydrogens.size(); ++i) { + const auto& hi = hydrogens[i]; + center_type coords(hi.x(), hi.y(), hi.z()); + contracted_gaussian_type h_cg(h_coefs.begin(), h_coefs.end(), + h_exps.begin(), h_exps.end(), coords); + atomic_basis_type h_basis("STO-3G", 1, coords); + h_basis.add_shell(cartesian, l0, h_cg); + rv.add_center(h_basis); + } + + return rv; +} + +inline auto h2_hamiltonian() { + simde::type::many_electrons es(2); + auto h2 = make_h2(); + simde::type::T_e_type T_e(es); + simde::type::V_en_type V_en(es, h2); + simde::type::V_ee_type V_ee(es, es); + simde::type::V_nn_type V_nn(h2, h2); + return simde::type::hamiltonian(T_e + V_en + V_ee + V_nn); +} + +inline auto h2_aos() { + auto h2 = make_h2(); + return simde::type::aos(h_basis(h2)); +} + +inline auto h2_mos() { + using mos_type = simde::type::mos; + using tensor_type = typename mos_type::transform_type; + tensor_type c({{-0.565516, -1.07019}, {-0.565516, 1.07019}}); + return mos_type(h2_aos(), std::move(c)); +} + +inline auto h2_density() { + using density_type = simde::type::decomposable_e_density; + typename density_type::value_type rho( + {{0.92501791, -0.54009707}, {-0.28540122, 1.7505162}}); + return density_type(rho, h2_mos()); +} + +/// The Fock matrix consistent with h2_hamiltonian and h2_density +inline auto h2_fock() { + simde::type::many_electrons es(2); + auto h2 = make_h2(); + auto rho = h2_density(); + simde::type::fock F; + F.emplace_back(1.0, std::make_unique(es)); + F.emplace_back(1.0, std::make_unique(es, h2)); + F.emplace_back(2.0, std::make_unique(es, rho)); + F.emplace_back(-1.0, std::make_unique(es, rho)); + return F; +} + +} // namespace test_scf \ No newline at end of file diff --git a/tests/cxx/unit_tests/fock_operator/restricted.cpp b/tests/cxx/unit_tests/fock_operator/restricted.cpp new file mode 100644 index 0000000..fa71d66 --- /dev/null +++ b/tests/cxx/unit_tests/fock_operator/restricted.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2024 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 + +TEST_CASE("Restricted") { + pluginplay::ModuleManager mm; + scf::load_modules(mm); + + using density_type = simde::type::decomposable_e_density; + using pt = simde::FockOperator; + + auto& mod = mm.at("Restricted Fock Op"); + + SECTION("H2 Molecule") { + auto H = test_scf::h2_hamiltonian(); + auto rho = test_scf::h2_density(); + + auto F = mod.run_as(H, rho); + auto F_corr = test_scf::h2_fock(); + REQUIRE(F == F_corr); + } +} \ No newline at end of file