1+ /*
2+ * Copyright 2025 NWChemEx-Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ #include " guess.hpp"
18+
19+ namespace scf ::guess {
20+ namespace {
21+ const auto desc = R"(
22+ SAD Guess
23+ ---------
24+
25+ TODO: Write me!!!
26+ )" ;
27+ }
28+
29+ using rscf_wf = simde::type::rscf_wf;
30+ using density_t = simde::type::decomposable_e_density;
31+ using pt = simde::InitialGuess<rscf_wf>;
32+ using fock_op_pt = simde::FockOperator<density_t >;
33+ using update_pt = simde::UpdateGuess<rscf_wf>;
34+ using initial_rho_pt = simde::InitialDensity;
35+
36+ using simde::type::tensor;
37+
38+ // TODO: move to chemist?
39+ struct NElectronCounter : public chemist ::qm_operator::OperatorVisitor {
40+ NElectronCounter () : chemist::qm_operator::OperatorVisitor(false ) {}
41+
42+ void run (const simde::type::T_e_type& T_e) { set_n (T_e.particle ().size ()); }
43+
44+ void run (const simde::type::V_en_type& V_en) {
45+ set_n (V_en.lhs_particle ().size ());
46+ }
47+
48+ void run (const simde::type::V_ee_type& V_ee) {
49+ set_n (V_ee.lhs_particle ().size ());
50+ set_n (V_ee.rhs_particle ().size ());
51+ }
52+
53+ void set_n (unsigned int n) {
54+ if (n_electrons == 0 )
55+ n_electrons = n;
56+ else if (n_electrons != n) {
57+ throw std::runtime_error (" Deduced a different number of electrons" );
58+ }
59+ }
60+
61+ unsigned int n_electrons = 0 ;
62+ };
63+
64+ MODULE_CTOR (SAD) {
65+ description (desc);
66+ satisfies_property_type<pt>();
67+ add_submodule<fock_op_pt>(" Build Fock operator" );
68+ add_submodule<update_pt>(" Guess updater" );
69+ add_submodule<initial_rho_pt>(" SAD Density" );
70+ }
71+
72+ MODULE_RUN (SAD) {
73+ const auto && [H, aos] = pt::unwrap_inputs (inputs);
74+
75+ // Step 1: Build Fock Operator with zero density
76+ auto & initial_rho_mod = submods.at (" SAD Density" );
77+ const auto & rho = initial_rho_mod.run_as <initial_rho_pt>(H);
78+ auto & fock_op_mod = submods.at (" Build Fock operator" );
79+ const auto & f = fock_op_mod.run_as <fock_op_pt>(H, rho);
80+
81+ // Step 2: Get number of electrons and occupations
82+ simde::type::cmos cmos (tensor{}, aos, tensor{});
83+ NElectronCounter visitor;
84+ H.visit (visitor);
85+ auto n_electrons = visitor.n_electrons ;
86+ if (n_electrons % 2 != 0 )
87+ throw std::runtime_error (" Assumed even number of electrons" );
88+
89+ typename rscf_wf::orbital_index_set_type occs;
90+ using value_type = typename rscf_wf::orbital_index_set_type::value_type;
91+ for (value_type i = 0 ; i < n_electrons / 2 ; ++i) occs.insert (i);
92+
93+ rscf_wf zero_guess (occs, cmos);
94+ auto & update_mod = submods.at (" Guess updater" );
95+ const auto & Psi0 = update_mod.run_as <update_pt>(f, zero_guess);
96+
97+ auto rv = results ();
98+ return pt::wrap_results (rv, Psi0);
99+ }
100+
101+ } // namespace scf::guess
0 commit comments