From ce6387b586e2eab5cd868d81f98b4f52a5e50937 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Tue, 25 Mar 2025 18:19:10 -0500 Subject: [PATCH 1/8] converging on the convergence mod --- .gitignore | 1 + include/scf/driver/convergence.hpp | 62 ++++++++++++++ src/scf/driver/convergence.cpp | 130 +++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 include/scf/driver/convergence.hpp create mode 100644 src/scf/driver/convergence.cpp diff --git a/.gitignore b/.gitignore index 6478ba2..cc414ab 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ # These are directories used by IDEs for storing settings .idea/ .vscode/ +.cache/ # These are common Python virtual enviornment directory names venv/ diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp new file mode 100644 index 0000000..b364d4b --- /dev/null +++ b/include/scf/driver/convergence.hpp @@ -0,0 +1,62 @@ +#pragma once +#include "simde/simde.hpp" +#include + +namespace scf { + +/** @brief The property type for modules that return a molecule from a string + * input. + * + * The usage of this property type can be pretty varied. Modules that satisfy + * this property type could potentially produce a molecule from a string with + * XYZ inputs, a SMILES string, or a molecule name outright. + * + */ + +using simde::type::electronic_hamiltonian; +using simde::type::hamiltonian; +using simde::type::op_base_type; + +template +using egy_pt = simde::eval_braket; + +template +using elec_egy_pt = simde::eval_braket; + +template +using pt = simde::Optimize, WfType>; + +template +using update_pt = simde::UpdateGuess; + +using density_t = simde::type::decomposable_e_density; + +using fock_pt = simde::FockOperator; + +using density_pt = simde::aos_rho_e_aos; + +using v_nn_pt = simde::charge_charge_interaction; + +using fock_matrix_pt = simde::aos_f_e_aos; +using s_pt = simde::aos_s_e_aos; + +DECLARE_PROPERTY_TYPE(ConvergenceProp); + +PROPERTY_TYPE_INPUTS(ConvergenceProp) { + using wf_type = simde::type::rscf_wf; + auto rv = pluginplay::declare_input().add_field>("Energy"); + rv.at("String").set_description( + "The string identifying the desired molecule"); + return rv; +} + +PROPERTY_TYPE_RESULTS(ConvergenceProp) { + using mol_t = type::molecule; + auto rv = pluginplay::declare_result().add_field("Molecule"); + rv.at("Molecule") + .set_description("The molecule corresponding to the input string"); + return rv; +} + +} // namespace simde + diff --git a/src/scf/driver/convergence.cpp b/src/scf/driver/convergence.cpp new file mode 100644 index 0000000..2df250c --- /dev/null +++ b/src/scf/driver/convergence.cpp @@ -0,0 +1,130 @@ +/* + * 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 "driver.hpp" + +namespace scf::driver { + +using simde::type::electronic_hamiltonian; +using simde::type::hamiltonian; +using simde::type::op_base_type; + +template +using egy_pt = simde::eval_braket; + +template +using elec_egy_pt = simde::eval_braket; + +template +using pt = simde::Optimize, WfType>; + +template +using update_pt = simde::UpdateGuess; + +using density_t = simde::type::decomposable_e_density; + +using fock_pt = simde::FockOperator; + +using density_pt = simde::aos_rho_e_aos; + +using v_nn_pt = simde::charge_charge_interaction; + +using fock_matrix_pt = simde::aos_f_e_aos; +using s_pt = simde::aos_s_e_aos; + +struct GrabNuclear : chemist::qm_operator::OperatorVisitor { + using V_nn_type = simde::type::V_nn_type; + + GrabNuclear() : chemist::qm_operator::OperatorVisitor(false) {} + + void run(const V_nn_type& V_nn) { m_pv = &V_nn; } + + const V_nn_type* m_pv; +}; + +MODULE_CTOR(SCFLoop) { + using wf_type = simde::type::rscf_wf; + description(desc); + satisfies_property_type>(); + + const unsigned int max_itr = 20; + add_input("max iterations").set_default(max_itr); + add_input("energy tolerance").set_default(1.0E-6); + add_input("density tolerance").set_default(1.0E-6); + add_input("gradient tolerance").set_default(1.0E-6); + + add_submodule>("Electronic energy"); + add_submodule("Density matrix"); + add_submodule>("Guess update"); + add_submodule("One-electron Fock operator"); + add_submodule("Fock operator"); + add_submodule("Fock matrix builder"); + add_submodule("Charge-charge"); + add_submodule("Overlap matrix builder"); +} + +MODULE_RUN(SCFLoop) { + using wf_type = simde::type::rscf_wf; + using density_op_type = simde::type::rho_e; + const auto&& [braket, psi0] = pt::unwrap_inputs(inputs); + // Step 5: Converged? + // Change in the energy + simde::type::tensor de; + de("") = e_new("") - e_old(""); + + // Change in the density + simde::type::tensor dp; + dp("m,n") = rho_new.value()("m,n") - rho_old.value()("m,n"); + auto dp_norm = tensorwrapper::operations::infinity_norm(dp); + + // Orbital gradient: FPS-SPF + // TODO: module satisfying BraKet(aos, Commutator(F,P), aos) + chemist::braket::BraKet F_mn(aos, f_new, aos); + const auto& F_matrix = F_mod.run_as(F_mn); + simde::type::tensor FPS; + FPS("m,l") = F_matrix("m,n") * P_new("n,l"); + FPS("m,l") = FPS("m,n") * S("n,l"); + + simde::type::tensor SPF; + SPF("m,l") = P_new("m,n") * F_matrix("n,l"); + SPF("m,l") = S("m,n") * SPF("n,l"); + + simde::type::tensor grad; + simde::type::tensor grad_norm; + grad("m,n") = FPS("m,n") - SPF("m,n"); + grad_norm("") = grad("m,n") * grad("n,m"); + + Kernel k(get_runtime()); + + using tensorwrapper::utilities::floating_point_dispatch; + auto e_conv = floating_point_dispatch(k, de.buffer(), e_tol); + auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); + auto dp_conv = floating_point_dispatch(k, dp_norm.buffer(), dp_tol); + + logger.log(" dE = " + de.to_string()); + logger.log(" dP = " + dp_norm.to_string()); + logger.log(" dG = " + grad_norm.to_string()); + + if(e_conv && g_conv && dp_conv) converged = true; + } + + // Step 6: Not converged so reset + e_old = e_new; + psi_old = psi_new; + rho_old = rho_new; + if(converged) break; + ++iter; + } From 217c0e96ccc242bfa7334eab314a5473ed403ecf Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Thu, 27 Mar 2025 17:09:06 -0500 Subject: [PATCH 2/8] starting to dev the property type --- include/scf/driver/convergence.hpp | 29 ++++++++++++++++++++++++----- src/scf/driver/convergence.cpp | 13 ++----------- src/scf/driver/driver.hpp | 3 ++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index b364d4b..69fe268 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -44,16 +44,35 @@ DECLARE_PROPERTY_TYPE(ConvergenceProp); PROPERTY_TYPE_INPUTS(ConvergenceProp) { using wf_type = simde::type::rscf_wf; - auto rv = pluginplay::declare_input().add_field>("Energy"); - rv.at("String").set_description( + auto rv = pluginplay::declare_input() + .add_field("New Energy") + .add_field>("Old Energy") + .add_field>("Fock Operator") + .add_field>("Wave Function") + .add_field("Energy Tolerance") + .add_field("Density Tolerance") + .add_field("Gradient Tolerance"); + + rv.at("New Energy").set_description( + "The string identifying the desired molecule"); + rv.at("Old Energy").set_description( + "The string identifying the desired molecule"); + rv.at("Fock Operator").set_description( + "The string identifying the desired molecule"); + rv.at("Wave Function").set_description( + "The string identifying the desired molecule"); + rv.at("Energy Tolerance").set_description( + "The string identifying the desired molecule"); + rv.at("Density Tolerance").set_description( + "The string identifying the desired molecule"); + rv.at("Gradient Tolerance").set_description( "The string identifying the desired molecule"); return rv; } PROPERTY_TYPE_RESULTS(ConvergenceProp) { - using mol_t = type::molecule; - auto rv = pluginplay::declare_result().add_field("Molecule"); - rv.at("Molecule") + auto rv = pluginplay::declare_result().add_field("Convergence Status"); + rv.at("Convergence Status") .set_description("The molecule corresponding to the input string"); return rv; } diff --git a/src/scf/driver/convergence.cpp b/src/scf/driver/convergence.cpp index 2df250c..57a092d 100644 --- a/src/scf/driver/convergence.cpp +++ b/src/scf/driver/convergence.cpp @@ -45,17 +45,8 @@ using v_nn_pt = simde::charge_charge_interaction; using fock_matrix_pt = simde::aos_f_e_aos; using s_pt = simde::aos_s_e_aos; -struct GrabNuclear : chemist::qm_operator::OperatorVisitor { - using V_nn_type = simde::type::V_nn_type; - GrabNuclear() : chemist::qm_operator::OperatorVisitor(false) {} - - void run(const V_nn_type& V_nn) { m_pv = &V_nn; } - - const V_nn_type* m_pv; -}; - -MODULE_CTOR(SCFLoop) { +MODULE_CTOR(ConvergenceMod) { using wf_type = simde::type::rscf_wf; description(desc); satisfies_property_type>(); @@ -76,7 +67,7 @@ MODULE_CTOR(SCFLoop) { add_submodule("Overlap matrix builder"); } -MODULE_RUN(SCFLoop) { +MODULE_RUN(ConvergenceMod) { using wf_type = simde::type::rscf_wf; using density_op_type = simde::type::rho_e; const auto&& [braket, psi0] = pt::unwrap_inputs(inputs); diff --git a/src/scf/driver/driver.hpp b/src/scf/driver/driver.hpp index e5039e6..2943e9b 100644 --- a/src/scf/driver/driver.hpp +++ b/src/scf/driver/driver.hpp @@ -21,6 +21,7 @@ namespace scf::driver { DECLARE_MODULE(SCFDriver); DECLARE_MODULE(SCFLoop); +DECLARE_MODULE(ConvergenceMod); inline void load_modules(pluginplay::ModuleManager& mm) { mm.add_module("SCF Driver"); @@ -41,4 +42,4 @@ inline void set_defaults(pluginplay::ModuleManager& mm) { mm.change_submod("SCF Driver", "Optimizer", "Loop"); } -} // namespace scf::driver \ No newline at end of file +} // namespace scf::driver From 77b493a129b57a9f2a444d3bb35cc1955ecc8155 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Fri, 28 Mar 2025 12:04:37 -0500 Subject: [PATCH 3/8] added templated property type --- include/scf/driver/convergence.hpp | 52 ++++++++---------------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index 69fe268..90e852c 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -1,5 +1,5 @@ #pragma once -#include "simde/simde.hpp" +#include #include namespace scf { @@ -13,45 +13,20 @@ namespace scf { * */ -using simde::type::electronic_hamiltonian; -using simde::type::hamiltonian; -using simde::type::op_base_type; +template +DECLARE_TEMPLATED_PROPERTY_TYPE(ConvergenceProp, EnergyProp, FockProp, WfProp); -template -using egy_pt = simde::eval_braket; - -template -using elec_egy_pt = simde::eval_braket; - -template -using pt = simde::Optimize, WfType>; - -template -using update_pt = simde::UpdateGuess; - -using density_t = simde::type::decomposable_e_density; - -using fock_pt = simde::FockOperator; - -using density_pt = simde::aos_rho_e_aos; - -using v_nn_pt = simde::charge_charge_interaction; - -using fock_matrix_pt = simde::aos_f_e_aos; -using s_pt = simde::aos_s_e_aos; - -DECLARE_PROPERTY_TYPE(ConvergenceProp); - -PROPERTY_TYPE_INPUTS(ConvergenceProp) { +template +TEMPLATED_PROPERTY_TYPE_INPUTS(ConvergenceProp, EnergyProp, FockProp, WfProp) { using wf_type = simde::type::rscf_wf; auto rv = pluginplay::declare_input() - .add_field("New Energy") - .add_field>("Old Energy") - .add_field>("Fock Operator") - .add_field>("Wave Function") - .add_field("Energy Tolerance") - .add_field("Density Tolerance") - .add_field("Gradient Tolerance"); + .add_field("New Energy") + .template add_field("Old Energy") + .template add_field("Fock Operator") + .template add_field("Wave Function") + .template add_field("Energy Tolerance") + .template add_field("Density Tolerance") + .template add_field("Gradient Tolerance"); rv.at("New Energy").set_description( "The string identifying the desired molecule"); @@ -70,7 +45,8 @@ PROPERTY_TYPE_INPUTS(ConvergenceProp) { return rv; } -PROPERTY_TYPE_RESULTS(ConvergenceProp) { +template +TEMPLATED_PROPERTY_TYPE_RESULTS(ConvergenceProp, EnergyProp, FockProp, WfProp) { auto rv = pluginplay::declare_result().add_field("Convergence Status"); rv.at("Convergence Status") .set_description("The molecule corresponding to the input string"); From b44d92478cd67f0f1d0809184c7bf489d0c2f972 Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Fri, 28 Mar 2025 12:15:58 -0500 Subject: [PATCH 4/8] started templated module --- include/scf/driver/convergence.hpp | 2 -- src/scf/driver/convergence.cpp | 36 ++++-------------------------- src/scf/driver/driver.hpp | 1 + 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index 90e852c..8b110bf 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include namespace scf { @@ -18,7 +17,6 @@ DECLARE_TEMPLATED_PROPERTY_TYPE(ConvergenceProp, EnergyProp, FockProp, WfProp); template TEMPLATED_PROPERTY_TYPE_INPUTS(ConvergenceProp, EnergyProp, FockProp, WfProp) { - using wf_type = simde::type::rscf_wf; auto rv = pluginplay::declare_input() .add_field("New Energy") .template add_field("Old Energy") diff --git a/src/scf/driver/convergence.cpp b/src/scf/driver/convergence.cpp index 57a092d..3aa5745 100644 --- a/src/scf/driver/convergence.cpp +++ b/src/scf/driver/convergence.cpp @@ -15,41 +15,13 @@ */ #include "driver.hpp" +#include namespace scf::driver { - -using simde::type::electronic_hamiltonian; -using simde::type::hamiltonian; -using simde::type::op_base_type; - -template -using egy_pt = simde::eval_braket; - -template -using elec_egy_pt = simde::eval_braket; - -template -using pt = simde::Optimize, WfType>; - -template -using update_pt = simde::UpdateGuess; - -using density_t = simde::type::decomposable_e_density; - -using fock_pt = simde::FockOperator; - -using density_pt = simde::aos_rho_e_aos; - -using v_nn_pt = simde::charge_charge_interaction; - -using fock_matrix_pt = simde::aos_f_e_aos; -using s_pt = simde::aos_s_e_aos; - - -MODULE_CTOR(ConvergenceMod) { +template +TEMPLATED_MODULE_CTOR(ConvergenceMod, EnergyProp, FockProp, WfProp) { using wf_type = simde::type::rscf_wf; - description(desc); - satisfies_property_type>(); + satisfies_property_type(); const unsigned int max_itr = 20; add_input("max iterations").set_default(max_itr); diff --git a/src/scf/driver/driver.hpp b/src/scf/driver/driver.hpp index 2943e9b..b47504b 100644 --- a/src/scf/driver/driver.hpp +++ b/src/scf/driver/driver.hpp @@ -16,6 +16,7 @@ #pragma once #include +#include namespace scf::driver { From 2070f203bf41a3f136477abe6ae31fbd54e9f79d Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Sat, 29 Mar 2025 19:37:44 -0500 Subject: [PATCH 5/8] making the move from scf_loop to convergence mod --- include/scf/driver/convergence.hpp | 32 ++++----- src/scf/driver/convergence.cpp | 102 +++++++++++++---------------- 2 files changed, 58 insertions(+), 76 deletions(-) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index 8b110bf..1dceea1 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -1,27 +1,22 @@ #pragma once #include +#include -namespace scf { -/** @brief The property type for modules that return a molecule from a string - * input. - * - * The usage of this property type can be pretty varied. Modules that satisfy - * this property type could potentially produce a molecule from a string with - * XYZ inputs, a SMILES string, or a molecule name outright. - * - */ +namespace scf { -template -DECLARE_TEMPLATED_PROPERTY_TYPE(ConvergenceProp, EnergyProp, FockProp, WfProp); +DECLARE_PROPERTY_TYPE(ConvergenceProp); -template -TEMPLATED_PROPERTY_TYPE_INPUTS(ConvergenceProp, EnergyProp, FockProp, WfProp) { +PROPERTY_TYPE_INPUTS(ConvergenceProp) { auto rv = pluginplay::declare_input() - .add_field("New Energy") - .template add_field("Old Energy") - .template add_field("Fock Operator") - .template add_field("Wave Function") + .add_field("New Energy") + .template add_field("Old Energy") + .template add_field>("New Rho") + .template add_field>("Old Rho") + .template add_field("P_new") + .template add_field("S") + .template add_field("Fock Operator") + .template add_field("Wave Function") .template add_field("Energy Tolerance") .template add_field("Density Tolerance") .template add_field("Gradient Tolerance"); @@ -43,8 +38,7 @@ TEMPLATED_PROPERTY_TYPE_INPUTS(ConvergenceProp, EnergyProp, FockProp, WfProp) { return rv; } -template -TEMPLATED_PROPERTY_TYPE_RESULTS(ConvergenceProp, EnergyProp, FockProp, WfProp) { +PROPERTY_TYPE_RESULTS(ConvergenceProp) { auto rv = pluginplay::declare_result().add_field("Convergence Status"); rv.at("Convergence Status") .set_description("The molecule corresponding to the input string"); diff --git a/src/scf/driver/convergence.cpp b/src/scf/driver/convergence.cpp index 3aa5745..182c5c5 100644 --- a/src/scf/driver/convergence.cpp +++ b/src/scf/driver/convergence.cpp @@ -18,71 +18,59 @@ #include namespace scf::driver { -template -TEMPLATED_MODULE_CTOR(ConvergenceMod, EnergyProp, FockProp, WfProp) { - using wf_type = simde::type::rscf_wf; + +MODULE_CTOR(ConvergenceMod) { satisfies_property_type(); - const unsigned int max_itr = 20; - add_input("max iterations").set_default(max_itr); add_input("energy tolerance").set_default(1.0E-6); add_input("density tolerance").set_default(1.0E-6); add_input("gradient tolerance").set_default(1.0E-6); - - add_submodule>("Electronic energy"); - add_submodule("Density matrix"); - add_submodule>("Guess update"); - add_submodule("One-electron Fock operator"); - add_submodule("Fock operator"); - add_submodule("Fock matrix builder"); - add_submodule("Charge-charge"); - add_submodule("Overlap matrix builder"); + add_submodule("Fock matrix builder"); } MODULE_RUN(ConvergenceMod) { - using wf_type = simde::type::rscf_wf; - using density_op_type = simde::type::rho_e; - const auto&& [braket, psi0] = pt::unwrap_inputs(inputs); - // Step 5: Converged? - // Change in the energy - simde::type::tensor de; - de("") = e_new("") - e_old(""); - - // Change in the density - simde::type::tensor dp; - dp("m,n") = rho_new.value()("m,n") - rho_old.value()("m,n"); - auto dp_norm = tensorwrapper::operations::infinity_norm(dp); - - // Orbital gradient: FPS-SPF - // TODO: module satisfying BraKet(aos, Commutator(F,P), aos) - chemist::braket::BraKet F_mn(aos, f_new, aos); - const auto& F_matrix = F_mod.run_as(F_mn); - simde::type::tensor FPS; - FPS("m,l") = F_matrix("m,n") * P_new("n,l"); - FPS("m,l") = FPS("m,n") * S("n,l"); - - simde::type::tensor SPF; - SPF("m,l") = P_new("m,n") * F_matrix("n,l"); - SPF("m,l") = S("m,n") * SPF("n,l"); - - simde::type::tensor grad; - simde::type::tensor grad_norm; - grad("m,n") = FPS("m,n") - SPF("m,n"); - grad_norm("") = grad("m,n") * grad("n,m"); - - Kernel k(get_runtime()); - - using tensorwrapper::utilities::floating_point_dispatch; - auto e_conv = floating_point_dispatch(k, de.buffer(), e_tol); - auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); - auto dp_conv = floating_point_dispatch(k, dp_norm.buffer(), dp_tol); - - logger.log(" dE = " + de.to_string()); - logger.log(" dP = " + dp_norm.to_string()); - logger.log(" dG = " + grad_norm.to_string()); - - if(e_conv && g_conv && dp_conv) converged = true; - } + const auto&& [e_new, e_old, rho_new, rho_old, P_new, S, f_new, aos, e_tol, dp_tol, g_tol] = ConvergenceProp::unwrap_inputs(inputs); + + auto& F_mod = submods.at("Fock matrix builder"); + + simde::type::tensor de; + de("") = e_new("") - e_old(""); + + // Change in the density + simde::type::tensor dp; + dp("m,n") = rho_new.value()("m,n") - rho_old.value()("m,n"); + auto dp_norm = tensorwrapper::operations::infinity_norm(dp); + + // Orbital gradient: FPS-SPF + // TODO: module satisfying BraKet(aos, Commutator(F,P), aos) + chemist::braket::BraKet F_mn(aos, f_new, aos); + const auto& F_matrix = F_mod.run_as(F_mn); + simde::type::tensor FPS; + FPS("m,l") = F_matrix("m,n") * P_new("n,l"); + FPS("m,l") = FPS("m,n") * S("n,l"); + + simde::type::tensor SPF; + SPF("m,l") = P_new("m,n") * F_matrix("n,l"); + SPF("m,l") = S("m,n") * SPF("n,l"); + + simde::type::tensor grad; + simde::type::tensor grad_norm; + grad("m,n") = FPS("m,n") - SPF("m,n"); + grad_norm("") = grad("m,n") * grad("n,m"); + + Kernel k(get_runtime()); + + using tensorwrapper::utilities::floating_point_dispatch; + auto e_conv = floating_point_dispatch(k, de.buffer(), e_tol); + auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); + auto dp_conv = floating_point_dispatch(k, dp_norm.buffer(), dp_tol); + + logger.log(" dE = " + de.to_string()); + logger.log(" dP = " + dp_norm.to_string()); + logger.log(" dG = " + grad_norm.to_string()); + + if(e_conv && g_conv && dp_conv) converged = true; +} // Step 6: Not converged so reset e_old = e_new; From 5fa99c434575ff9ac7ff7cca49a5b42e93a42edf Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Sun, 30 Mar 2025 15:43:02 -0500 Subject: [PATCH 6/8] templating the convergence module --- include/scf/driver/convergence.hpp | 9 ++++-- src/scf/driver/convergence.cpp | 50 +++++++++++++++++++++--------- src/scf/driver/driver.hpp | 2 ++ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index 1dceea1..23d3105 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -5,9 +5,11 @@ namespace scf { -DECLARE_PROPERTY_TYPE(ConvergenceProp); +template +DECLARE_TEMPLATED_PROPERTY_TYPE(ConvergenceProp, KernelType); -PROPERTY_TYPE_INPUTS(ConvergenceProp) { +template +TEMPLATED_PROPERTY_TYPE_INPUTS(ConvergenceProp, KernelType) { auto rv = pluginplay::declare_input() .add_field("New Energy") .template add_field("Old Energy") @@ -38,7 +40,8 @@ PROPERTY_TYPE_INPUTS(ConvergenceProp) { return rv; } -PROPERTY_TYPE_RESULTS(ConvergenceProp) { +template +TEMPLATED_PROPERTY_TYPE_RESULTS(ConvergenceProp, KernelType) { auto rv = pluginplay::declare_result().add_field("Convergence Status"); rv.at("Convergence Status") .set_description("The molecule corresponding to the input string"); diff --git a/src/scf/driver/convergence.cpp b/src/scf/driver/convergence.cpp index 182c5c5..8e88e63 100644 --- a/src/scf/driver/convergence.cpp +++ b/src/scf/driver/convergence.cpp @@ -17,10 +17,24 @@ #include "driver.hpp" #include + namespace scf::driver { -MODULE_CTOR(ConvergenceMod) { - satisfies_property_type(); +struct Kernel { + explicit Kernel(parallelzone::runtime::RuntimeView rv) : m_rv(rv) {} + template + auto run(const tensorwrapper::buffer::BufferBase& a, double tol) { + tensorwrapper::allocator::Eigen allocator(m_rv); + const auto& eigen_a = allocator.rebind(a); + return tensorwrapper::types::fabs(eigen_a.at()) < FloatType(tol); + } + + parallelzone::runtime::RuntimeView m_rv; +}; + +template +TEMPLATED_MODULE_CTOR(ConvergenceMod, Kernel) { + satisfies_property_type>(); add_input("energy tolerance").set_default(1.0E-6); add_input("density tolerance").set_default(1.0E-6); @@ -28,8 +42,11 @@ MODULE_CTOR(ConvergenceMod) { add_submodule("Fock matrix builder"); } -MODULE_RUN(ConvergenceMod) { - const auto&& [e_new, e_old, rho_new, rho_old, P_new, S, f_new, aos, e_tol, dp_tol, g_tol] = ConvergenceProp::unwrap_inputs(inputs); +template +TEMPLATED_MODULE_RUN(ConvergenceMod, Kernel) { + const auto&& [e_new, e_old, rho_new, rho_old, P_new, S, f_new, aos, e_tol, dp_tol, g_tol] = ConvergenceProp::unwrap_inputs(inputs); + + bool converged = false; auto& F_mod = submods.at("Fock matrix builder"); @@ -65,17 +82,20 @@ MODULE_RUN(ConvergenceMod) { auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); auto dp_conv = floating_point_dispatch(k, dp_norm.buffer(), dp_tol); - logger.log(" dE = " + de.to_string()); - logger.log(" dP = " + dp_norm.to_string()); - logger.log(" dG = " + grad_norm.to_string()); + // logger.log(" dE = " + de.to_string()); + // logger.log(" dP = " + dp_norm.to_string()); + // logger.log(" dG = " + grad_norm.to_string()); if(e_conv && g_conv && dp_conv) converged = true; -} - // Step 6: Not converged so reset - e_old = e_new; - psi_old = psi_new; - rho_old = rho_new; - if(converged) break; - ++iter; - } + auto rv = results(); + return scf::ConvergenceProp::wrap_inputs(rv, converged); +} +} + // // Step 6: Not converged so reset + // e_old = e_new; + // psi_old = psi_new; + // rho_old = rho_new; + // if(converged) break; + // ++iter; + // } diff --git a/src/scf/driver/driver.hpp b/src/scf/driver/driver.hpp index b47504b..13b72d3 100644 --- a/src/scf/driver/driver.hpp +++ b/src/scf/driver/driver.hpp @@ -22,6 +22,8 @@ namespace scf::driver { DECLARE_MODULE(SCFDriver); DECLARE_MODULE(SCFLoop); + +template DECLARE_MODULE(ConvergenceMod); inline void load_modules(pluginplay::ModuleManager& mm) { From 0a1f1845e63d08ba85eece4b5609e156dfd24beb Mon Sep 17 00:00:00 2001 From: Jacob Heflin Date: Sun, 30 Mar 2025 15:56:58 -0500 Subject: [PATCH 7/8] cleaning up scf_loop code for adding convergence mod --- include/scf/driver/convergence.hpp | 16 +------ src/scf/driver/convergence.cpp | 28 +++--------- src/scf/driver/scf_loop.cpp | 73 ++++++++++++++++-------------- 3 files changed, 46 insertions(+), 71 deletions(-) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index 23d3105..bf7a180 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -19,24 +19,10 @@ TEMPLATED_PROPERTY_TYPE_INPUTS(ConvergenceProp, KernelType) { .template add_field("S") .template add_field("Fock Operator") .template add_field("Wave Function") + .template add_field("K") .template add_field("Energy Tolerance") .template add_field("Density Tolerance") .template add_field("Gradient Tolerance"); - - rv.at("New Energy").set_description( - "The string identifying the desired molecule"); - rv.at("Old Energy").set_description( - "The string identifying the desired molecule"); - rv.at("Fock Operator").set_description( - "The string identifying the desired molecule"); - rv.at("Wave Function").set_description( - "The string identifying the desired molecule"); - rv.at("Energy Tolerance").set_description( - "The string identifying the desired molecule"); - rv.at("Density Tolerance").set_description( - "The string identifying the desired molecule"); - rv.at("Gradient Tolerance").set_description( - "The string identifying the desired molecule"); return rv; } diff --git a/src/scf/driver/convergence.cpp b/src/scf/driver/convergence.cpp index 8e88e63..1276805 100644 --- a/src/scf/driver/convergence.cpp +++ b/src/scf/driver/convergence.cpp @@ -20,21 +20,9 @@ namespace scf::driver { -struct Kernel { - explicit Kernel(parallelzone::runtime::RuntimeView rv) : m_rv(rv) {} - template - auto run(const tensorwrapper::buffer::BufferBase& a, double tol) { - tensorwrapper::allocator::Eigen allocator(m_rv); - const auto& eigen_a = allocator.rebind(a); - return tensorwrapper::types::fabs(eigen_a.at()) < FloatType(tol); - } - - parallelzone::runtime::RuntimeView m_rv; -}; - -template -TEMPLATED_MODULE_CTOR(ConvergenceMod, Kernel) { - satisfies_property_type>(); +template +TEMPLATED_MODULE_CTOR(ConvergenceMod, KernelType) { + satisfies_property_type>(); add_input("energy tolerance").set_default(1.0E-6); add_input("density tolerance").set_default(1.0E-6); @@ -42,9 +30,9 @@ TEMPLATED_MODULE_CTOR(ConvergenceMod, Kernel) { add_submodule("Fock matrix builder"); } -template -TEMPLATED_MODULE_RUN(ConvergenceMod, Kernel) { - const auto&& [e_new, e_old, rho_new, rho_old, P_new, S, f_new, aos, e_tol, dp_tol, g_tol] = ConvergenceProp::unwrap_inputs(inputs); +template +TEMPLATED_MODULE_RUN(ConvergenceMod, KernelType) { + const auto&& [e_new, e_old, rho_new, rho_old, P_new, S, f_new, aos, k, e_tol, dp_tol, g_tol] = ConvergenceProp::unwrap_inputs(inputs); bool converged = false; @@ -75,8 +63,6 @@ TEMPLATED_MODULE_RUN(ConvergenceMod, Kernel) { grad("m,n") = FPS("m,n") - SPF("m,n"); grad_norm("") = grad("m,n") * grad("n,m"); - Kernel k(get_runtime()); - using tensorwrapper::utilities::floating_point_dispatch; auto e_conv = floating_point_dispatch(k, de.buffer(), e_tol); auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); @@ -89,7 +75,7 @@ TEMPLATED_MODULE_RUN(ConvergenceMod, Kernel) { if(e_conv && g_conv && dp_conv) converged = true; auto rv = results(); - return scf::ConvergenceProp::wrap_inputs(rv, converged); + return scf::ConvergenceProp::wrap_inputs(rv, converged); } } // // Step 6: Not converged so reset diff --git a/src/scf/driver/scf_loop.cpp b/src/scf/driver/scf_loop.cpp index 39d6475..7eca8cf 100644 --- a/src/scf/driver/scf_loop.cpp +++ b/src/scf/driver/scf_loop.cpp @@ -92,6 +92,7 @@ MODULE_CTOR(SCFLoop) { add_submodule("Fock matrix builder"); add_submodule("Charge-charge"); add_submodule("Overlap matrix builder"); + add_submodule>("Converged Mod"); } MODULE_RUN(SCFLoop) { @@ -110,6 +111,7 @@ MODULE_RUN(SCFLoop) { auto& fock_mod = submods.at("One-electron Fock operator"); auto& Fock_mod = submods.at("Fock operator"); auto& V_nn_mod = submods.at("Charge-charge"); + auto& conv_mod = submods.at("Converged Mod"); // TODO: should be split off into orbital gradient module auto& F_mod = submods.at("Fock matrix builder"); @@ -191,53 +193,54 @@ MODULE_RUN(SCFLoop) { logger.log(e_msg); bool converged = false; - // Step 5: Converged? + // // Step 5: Converged? if(iter > 0) { // Change in the energy - simde::type::tensor de; - de("") = e_new("") - e_old(""); - - // Change in the density - simde::type::tensor dp; - dp("m,n") = rho_new.value()("m,n") - rho_old.value()("m,n"); - auto dp_norm = tensorwrapper::operations::infinity_norm(dp); - - // Orbital gradient: FPS-SPF - // TODO: module satisfying BraKet(aos, Commutator(F,P), aos) - chemist::braket::BraKet F_mn(aos, f_new, aos); - const auto& F_matrix = F_mod.run_as(F_mn); - simde::type::tensor FPS; - FPS("m,l") = F_matrix("m,n") * P_new("n,l"); - FPS("m,l") = FPS("m,n") * S("n,l"); - - simde::type::tensor SPF; - SPF("m,l") = P_new("m,n") * F_matrix("n,l"); - SPF("m,l") = S("m,n") * SPF("n,l"); - - simde::type::tensor grad; - simde::type::tensor grad_norm; - grad("m,n") = FPS("m,n") - SPF("m,n"); - grad_norm("") = grad("m,n") * grad("n,m"); + // simde::type::tensor de; + // de("") = e_new("") - e_old(""); + + // // Change in the density + // simde::type::tensor dp; + // dp("m,n") = rho_new.value()("m,n") - rho_old.value()("m,n"); + // auto dp_norm = tensorwrapper::operations::infinity_norm(dp); + + // // Orbital gradient: FPS-SPF + // // TODO: module satisfying BraKet(aos, Commutator(F,P), aos) + // chemist::braket::BraKet F_mn(aos, f_new, aos); + // const auto& F_matrix = F_mod.run_as(F_mn); + // simde::type::tensor FPS; + // FPS("m,l") = F_matrix("m,n") * P_new("n,l"); + // FPS("m,l") = FPS("m,n") * S("n,l"); + + // simde::type::tensor SPF; + // SPF("m,l") = P_new("m,n") * F_matrix("n,l"); + // SPF("m,l") = S("m,n") * SPF("n,l"); + + // simde::type::tensor grad; + // simde::type::tensor grad_norm; + // grad("m,n") = FPS("m,n") - SPF("m,n"); + // grad_norm("") = grad("m,n") * grad("n,m"); Kernel k(get_runtime()); - using tensorwrapper::utilities::floating_point_dispatch; - auto e_conv = floating_point_dispatch(k, de.buffer(), e_tol); - auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); - auto dp_conv = floating_point_dispatch(k, dp_norm.buffer(), dp_tol); + // using tensorwrapper::utilities::floating_point_dispatch; + // auto e_conv = floating_point_dispatch(k, de.buffer(), e_tol); + // auto g_conv = floating_point_dispatch(k, grad_norm.buffer(), g_tol); + // auto dp_conv = floating_point_dispatch(k, dp_norm.buffer(), dp_tol); - logger.log(" dE = " + de.to_string()); - logger.log(" dP = " + dp_norm.to_string()); - logger.log(" dG = " + grad_norm.to_string()); + // logger.log(" dE = " + de.to_string()); + // logger.log(" dP = " + dp_norm.to_string()); + // logger.log(" dG = " + grad_norm.to_string()); - if(e_conv && g_conv && dp_conv) converged = true; + // // if(e_conv && g_conv && dp_conv) converged = true; + auto converged = conv_mod.run_as>(e_new, e_old, rho_new, rho_old, P_new, S, f_new, aos, k, e_tol, dp_tol, g_tol); } + if (converged) break; // Step 6: Not converged so reset e_old = e_new; psi_old = psi_new; rho_old = rho_new; - if(converged) break; ++iter; } if(iter == max_iter) throw std::runtime_error("SCF failed to converge"); @@ -261,4 +264,4 @@ MODULE_RUN(SCFLoop) { return pt::wrap_results(rv, e_total, psi_old); } -} // namespace scf::driver \ No newline at end of file +} // namespace scf::driver From d1958a4e67794c9636bd821f85270369333ed53b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 30 Mar 2025 21:08:23 +0000 Subject: [PATCH 8/8] Committing clang-format changes --- include/scf/driver/convergence.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/scf/driver/convergence.hpp b/include/scf/driver/convergence.hpp index bf7a180..f130e2e 100644 --- a/include/scf/driver/convergence.hpp +++ b/include/scf/driver/convergence.hpp @@ -1,3 +1,19 @@ +/* + * 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. + */ + #pragma once #include #include