Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
89 changes: 89 additions & 0 deletions src/cxx/nux/bo_approximation.cpp
Original file line number Diff line number Diff line change
@@ -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 "nux_modules.hpp"

namespace nux {

using simde::type::chemical_system;
using simde::type::hamiltonian;
using simde::type::many_electrons;
using pt = simde::Convert<hamiltonian, chemical_system>;

const auto desc = R"(
Born-Oppenheimer Hamiltonian Driver
-----------------------------------

This module defines the algorithm used throughout NWChemEx to convert a
ChemicalSystem object into a Hamiltonian object using the Born-Oppenheimer
approximation.

Specifically this driver will convert:
- ManyElectrons to a T_e and V_ee terms.
- Nuclei to a V_nn
- ManyElectrons + Nuclei to a V_en term.

The terms will be added following the "usual" ordering:

- Electronic Hamiltonian
- Electronic kinetic energy
- Electron-nucleus attraction
- Electron-electron repulsion
- Nuclear-nuclear repulsion

Terms that are zero will not appear in the Hamiltonian.
)";

MODULE_CTOR(BOApproximation) {
satisfies_property_type<pt>();
description(desc);
}

MODULE_RUN(BOApproximation) {
const auto &[sys] = pt::unwrap_inputs(inputs);

// Step 0: Decompose system into pieces
const auto electrons = sys.molecule().electrons();
const auto nuclei = sys.molecule().nuclei().as_nuclei();
bool has_electrons = electrons.size();
bool has_nuclei = nuclei.size();

using simde::type::T_e_type;
using simde::type::V_ee_type;
using simde::type::V_en_type;
using simde::type::V_nn_type;

// Step 1: Create non-zero terms and add them to the Hamiltonian
// N.b. the logic is a bit convoluted to conform to "usual" ordering (see
// module description)

hamiltonian H;
if (has_electrons) {
H.emplace_back(1.0, std::make_unique<T_e_type>(electrons));
if (has_nuclei)
H.emplace_back(1.0, std::make_unique<V_en_type>(electrons, nuclei));
if (electrons.size() > 1)
H.emplace_back(1.0, std::make_unique<V_ee_type>(electrons, electrons));
}
if (nuclei.size() > 1) {
H.emplace_back(1.0, std::make_unique<V_nn_type>(nuclei, nuclei));
}

auto rv = results();
return pt::wrap_results(rv, H);
}

} // namespace nux
5 changes: 4 additions & 1 deletion src/cxx/nux/nux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
* limitations under the License.
*/

#include "nux_modules.hpp"
#include <nux/nux.hpp>

namespace nux {

void load_modules(pluginplay::ModuleManager &mm) {}
void load_modules(pluginplay::ModuleManager &mm) {
mm.add_module<BOApproximation>("Born-Oppenheimer Approximation");
}

} // namespace nux
24 changes: 24 additions & 0 deletions src/cxx/nux/nux_modules.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 <simde/simde.hpp>

namespace nux {

DECLARE_MODULE(BOApproximation);

}
27 changes: 26 additions & 1 deletion tests/cxx/test_nux.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,30 @@
#include <catch2/catch_approx.hpp>
#include <catch2/catch_template_test_macros.hpp>
#include <catch2/catch_test_macros.hpp>
#include <simde/simde.hpp>

namespace test_nux {}
namespace test_nux {

inline auto h_nucleus(double x, double y, double z) {
return simde::type::nucleus("H", 1ul, 1836.15, x, y, z);
}

template <typename ResultType> ResultType make_h2() {
using simde::type::chemical_system;
using simde::type::molecule;
using simde::type::nuclei;
if constexpr (std::is_same_v<ResultType, nuclei>) {
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<ResultType, molecule>) {
return molecule(0, 1, make_h2<nuclei>());
} else if constexpr (std::is_same_v<ResultType, chemical_system>) {
return chemical_system(make_h2<molecule>());
} 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<ResultType, nuclei>);
}
}
} // namespace test_nux
97 changes: 97 additions & 0 deletions tests/cxx/unit_tests/bo_approximation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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_nux.hpp"
#include <nux/nux.hpp>

using namespace nux;

TEST_CASE("BOApproximation") {
pluginplay::ModuleManager mm;
load_modules(mm);

using simde::type::chemical_system;
using simde::type::hamiltonian;
using simde::type::T_e_type;
using simde::type::V_ee_type;
using simde::type::V_en_type;
using simde::type::V_nn_type;

using pt = simde::Convert<hamiltonian, chemical_system>;

auto &mod = mm.at("Born-Oppenheimer Approximation");

SECTION("Empty chemical system") {
chemical_system sys;
auto H = mod.run_as<pt>(sys);
REQUIRE(H == hamiltonian{});
}

SECTION("H2") {
auto h2 = test_nux::make_h2<chemical_system>();
auto electrons = h2.molecule().electrons();
auto nuclei = h2.molecule().nuclei().as_nuclei();

auto H = mod.run_as<pt>(h2);
hamiltonian H_corr;
H_corr.emplace_back(1.0, std::make_unique<T_e_type>(electrons));
H_corr.emplace_back(1.0, std::make_unique<V_en_type>(electrons, nuclei));
H_corr.emplace_back(1.0, std::make_unique<V_ee_type>(electrons, electrons));
H_corr.emplace_back(1.0, std::make_unique<V_nn_type>(nuclei, nuclei));
REQUIRE(H == H_corr);
}

SECTION("H atom") {
simde::type::nuclei nuclei{test_nux::h_nucleus(0.0, 0.0, 0.0)};
simde::type::chemical_system h(simde::type::molecule(0, 2, nuclei));

auto electrons = h.molecule().electrons();

auto H = mod.run_as<pt>(h);
hamiltonian H_corr;
H_corr.emplace_back(1.0, std::make_unique<T_e_type>(electrons));
H_corr.emplace_back(1.0, std::make_unique<V_en_type>(electrons, nuclei));
REQUIRE(H == H_corr);
}

SECTION("H anion") {
simde::type::nuclei nuclei{test_nux::h_nucleus(0.0, 0.0, 0.0)};
simde::type::chemical_system h(simde::type::molecule(-1, 1, nuclei));

auto electrons = h.molecule().electrons();

auto H = mod.run_as<pt>(h);
hamiltonian H_corr;
H_corr.emplace_back(1.0, std::make_unique<T_e_type>(electrons));
H_corr.emplace_back(1.0, std::make_unique<V_en_type>(electrons, nuclei));
H_corr.emplace_back(1.0, std::make_unique<V_ee_type>(electrons, electrons));
REQUIRE(H == H_corr);
}

SECTION("H2 cation") {
auto nuclei = test_nux::make_h2<simde::type::nuclei>();
simde::type::chemical_system h(simde::type::molecule(1, 2, nuclei));

auto electrons = h.molecule().electrons();

auto H = mod.run_as<pt>(h);
hamiltonian H_corr;
H_corr.emplace_back(1.0, std::make_unique<T_e_type>(electrons));
H_corr.emplace_back(1.0, std::make_unique<V_en_type>(electrons, nuclei));
H_corr.emplace_back(1.0, std::make_unique<V_nn_type>(nuclei, nuclei));
REQUIRE(H == H_corr);
}
}
2 changes: 2 additions & 0 deletions tests/cxx/unit_tests/nux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

#include "../test_nux.hpp"
#include <nux/nux.hpp>

TEST_CASE("load_plugin") {
pluginplay::ModuleManager mm;
nux::load_modules(mm);
REQUIRE(mm.size() > 0);
}
3 changes: 3 additions & 0 deletions tests/python/integration_tests/test_nux/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

class TestLoadModules(unittest.TestCase):

def test_load_modules(self):
self.assertGreater(self.mm.size(), 0)

def setUp(self):
self.mm = ModuleManager()
nux.load_modules(self.mm)
26 changes: 26 additions & 0 deletions tests/python/test_nux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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.

import chemist


def h_nucleus(x, y, z):
return chemist.Nucleus('H', 1, 1836.15, x, y, z)


def h2_nuclei():
h0 = h_nucleus(0.0, 0.0, 0.0)
h1 = h_nucleus(0.0, 0.0, 1.3984)

return chemist.Nuclei(h0, h1)
34 changes: 34 additions & 0 deletions tests/python/unit_tests/test_nux/test_bo_approximation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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.

from pluginplay import ModuleManager
import nux
import simde
import chemist
import unittest


class TestBOApproximation(unittest.TestCase):

def test_empty_chemical_system(self):
sys = chemist.ChemicalSystem()
# Hamiltonian isn't exposed to Python yet...
#H = self.mm.run_as(self.pt, 'Born-Oppenheimer Approximation', sys)
#H_corr = chemist.qm_operator.Hamiltonian()
#self.assertEqual(H, H_corr)

def setUp(self):
self.mm = ModuleManager()
nux.load_modules(self.mm)
self.pt = simde.HamiltonianFromChemicalSystem()
3 changes: 3 additions & 0 deletions tests/python/unit_tests/test_nux/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

class TestLoadModules(unittest.TestCase):

def test_load_modules(self):
self.assertGreater(self.mm.size(), 0)

def setUp(self):
self.mm = ModuleManager()
nux.load_modules(self.mm)