ampsci
High-precision calculations for one- and two-valence atomic systems
QkTable.hpp
1#pragma once
2#include "Angular/SixJTable.hpp"
3#include "Wavefunction/DiracSpinor.hpp"
4#include "YkTable.hpp"
5#include <array>
6#include <cstdint>
7#include <functional>
8#include <unordered_map>
9
10namespace Coulomb {
11
12//! Symmetry (state index order) for tables.
13enum class Symmetry { Qk, Wk, Lk, none };
14//! Data type used to store integrals
15using Real = double;
16//! index type for set of 4 orbitals {nk,nk,nk,nk} -> nk4Index
17using nk4Index = uint64_t;
18//! index type for each {nk} (orbital)
19using nkIndex = uint16_t;
20
21static_assert(sizeof(nkIndex) == sizeof(DiracSpinor::Index));
22
23//! Function type for calculating Coulomb(-like) integrals.
24//! Takes k and 4 DiracSpinors, returns a double
26 std::function<double(int, const DiracSpinor &a, const DiracSpinor &b,
27 const DiracSpinor &c, const DiracSpinor &d)>;
28
29//! Function type for determining Coulomb(-like) integral selection rules.
30//! Takes k and 4 DiracSpinors, returns a true if integral is allowed.
32 std::function<bool(int, const DiracSpinor &a, const DiracSpinor &b,
33 const DiracSpinor &c, const DiracSpinor &d)>;
34
35//==============================================================================
36/*!
37@brief
38Base (pure virtual) class to store Coulomb integrals, and similar. 3 derived
39classes, which account for symmetry.
40 @details
41Mostly, a wrapper for std::unordered_map.
42Stores data in a std::vector of maps, each element (map) for each k
43(multipolarity).
44The symmetry is taken into account by defining a "Normal Ordering" of set of
45orbitals {a,b,c,d}. How this is defined depends on the specific symmetry in
46question.
47 Qk symmetry:
48 {abcd} = cbad = adcb = cdab = badc = bcda = dabc = dcba.
49 Normal ordering: i = min(a,b,c,d) is first index.
50 Two options (second and fourth may be swapped): choose 2nd to be smallest
51 Wk symmetry (same as g):
52 {abcd} = badc = cdab = dcba
53 Lk symmetry:
54 {abcd} = badc
55*/
56template <Symmetry S>
58
59private:
60 // each vector element corresponds to a 'k'
61 std::vector<std::unordered_map<nk4Index, Real>> m_data{};
62
63public:
64 // 'Rule of zero' (except virtual destructor)
65 // virtual ~CoulombTable() = default;
66
67 //! Takes a constructed YkTable, and fills Coulomb table with all possible
68 //! non-zero Qk Coulomb integrals, accounting for symmetry (only allowed
69 //! for QkTable), up to maximum k, k_cut (set k_cut to <=0 to use all k)
70 void fill(const std::vector<DiracSpinor> &basis, const YkTable &yk,
71 int k_cut = -1, bool print = true);
72
73 //! Takes a constructed YkTable, and fills Coulomb table with all possible
74 //! non-zero Qk Coulomb integrals that are allowed by the SelectionFunction,
75 //! accounting for symmetry (only allowed for QkTable), up to maximum k,
76 //! k_cut (set k_cut to <=0 to use all k)
77 void fill_if(const std::vector<DiracSpinor> &basis, const YkTable &yk,
78 const SelectionRules &SelectionFunction, int k_cut = -1,
79 bool print = true);
80
81 void fill(const std::vector<DiracSpinor> &basis, const CoulombFunction &Fk,
82 const SelectionRules &Fk_SR, int k_cut = -1, bool print = true);
83
84 //! Gives arrow access to all underlying vector<unordered_map> functions
85 auto operator->() { return &m_data; }
86
87 //! For testing: prints details of coulomb integrals stored
88 void summary() const;
89 //! Returns number of stored integrals
90 std::size_t count() const;
91
92 //! adds a new value. Note: does nothing if {k,a,b,c,d} already exists
93 void add(int k, const DiracSpinor &a, const DiracSpinor &b,
94 const DiracSpinor &c, const DiracSpinor &d, Real value);
95 //! adds a new value. Note: does nothing if {k,a,b,c,d} already exists
96 void add(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, Real value);
97 //! adds a new value. Note: does nothing if {k,a,b,c,d} already exists
98 void add(int k, nk4Index index, Real value);
99
100 //! Updates value in table. If not present, adds new value
101 void update(int k, const DiracSpinor &a, const DiracSpinor &b,
102 const DiracSpinor &c, const DiracSpinor &d, Real value);
103 //! Updates value in table. If not present, adds new value
104 void update(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, Real value);
105 //! Updates value in table. If not present, adds new value
106 void update(int k, nk4Index index, Real value);
107
108 //! Checks if given {k,a,b,c,d} is in the table
109 bool contains(int k, const DiracSpinor &a, const DiracSpinor &b,
110 const DiracSpinor &c, const DiracSpinor &d) const;
111 //! Checks if given {k,a,b,c,d} is in the table
112 bool contains(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const;
113 //! Checks if given {k,a,b,c,d} is in the table
114 bool contains(int k, nk4Index index) const;
115
116 //! Returns true if table is empty
117 bool emptyQ() const {
118 return (m_data.size() == 0);
119 // nb: possible to be empty if size > 0... (but doesn't matter..)
120 }
121
122 //! Retrieve a stored Q. If not present, returns 0. (Returns exactly as
123 //! stored in table.)
124 Real Q(int k, const DiracSpinor &a, const DiracSpinor &b,
125 const DiracSpinor &c, const DiracSpinor &d) const;
126 //! Retrieve a stored Q. If not present, returns 0. (Returns exactly as
127 //! stored in table.)
128
129 Real Q(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const;
130 //! Retrieve a stored Q. If not present, returns 0. (Returns exactly as
131 //! stored in table.)
132 Real Q(int k, nk4Index index) const;
133
134 //! Returns 'R', defined via: R := Q / (angular_coef)
135 Real R(int k, const DiracSpinor &a, const DiracSpinor &b,
136 const DiracSpinor &c, const DiracSpinor &d) const;
137 //! Returns 'R', defined via: R := Q / (angular_coef)
138 Real R(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const;
139
140 //! 'Exchange-only', defined via W = Q + P. Optionally, takes pointer to 6J
141 //! table (faster eval of 6J symbols)
142 Real P(int k, const DiracSpinor &a, const DiracSpinor &b,
143 const DiracSpinor &c, const DiracSpinor &d,
144 const Angular::SixJTable *const sj = nullptr) const;
145 //! 'Exchange-only', defined via W = Q + P. Optionally, takes pointer to 6J
146 //! table (faster eval of 6J symbols)
147 Real P(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d,
148 const Angular::SixJTable *const sj = nullptr) const;
149
150 //! 'Exchange-only', defined via W = Q + P. Optionally, takes pointer to 6J
151 //! table (faster eval of 6J symbols) - with screening
152 Real P2(int k, const DiracSpinor &a, const DiracSpinor &b,
153 const DiracSpinor &c, const DiracSpinor &d,
154 const Angular::SixJTable &sj, const std::vector<double> &fk) const;
155
156 //! W^k_abcd = Q^k_abcd + \sum_l [k] 6j * Q^l_abdc. Optionally, takes
157 //! pointer to 6J table (faster eval of 6J symbols)
158 Real W(int k, const DiracSpinor &a, const DiracSpinor &b,
159 const DiracSpinor &c, const DiracSpinor &d,
160 const Angular::SixJTable *const sj = nullptr) const;
161
162 //! W^k_abcd = Q^k_abcd + \sum_l [k] 6j * Q^l_abdc.
163 //! Optionally, takes pointer to 6J table (faster eval of 6J symbols)
164 Real W(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d,
165 const Angular::SixJTable *const sj = nullptr) const;
166
167 //! Returns 'g_abcd'
168 Real g(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c,
169 const DiracSpinor &d, int tma, int tmb, int tmc, int tmd) const;
170
171 //! Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of
172 //! {a,b,c,d}
173 nk4Index NormalOrder(const DiracSpinor &a, const DiracSpinor &b,
174 const DiracSpinor &c, const DiracSpinor &d) const;
175 //! Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of
176 //! {a,b,c,d}
178
179 //! Checks if set {a,b,c,d} are already in NormalOrder
181 return NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d);
182 }
183 //! Checks if set {a,b,c,d} are already in NormalOrder
184 bool is_NormalOrdered(const DiracSpinor &a, const DiracSpinor &b,
185 const DiracSpinor &c, const DiracSpinor &d) const {
186 return NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d);
187 }
188
189 //! Writes coulomb integrals to disk
190 void write(const std::string &fname) const;
191 //! Reads coulomb integrals to disk. Returns false if none read in
192 bool read(const std::string &fname);
193
194 //! Directly gets one of the stored elements, given normal-ordered nk4Index
195 double *get(int k, nk4Index index);
196
197 //! Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be
198 //! used to check if {a,b,c,d} are already in 'NormalOrder'
199 nk4Index CurrentOrder(const DiracSpinor &a, const DiracSpinor &b,
200 const DiracSpinor &c, const DiracSpinor &d) const;
201
202 //! Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be
203 //! used to check if {a,b,c,d} are already in 'NormalOrder'
205
206 //! Converts given set of nkIndex's (in any order) to nk4Index
207 static nk4Index FormIndex(nkIndex a, nkIndex b, nkIndex c, nkIndex d);
208
209 //! Breaks nk4Index back into {ia,ib,ic,id}. Not used.
210 std::array<nkIndex, 4> UnFormIndex(const nk4Index &index) const;
211
212private:
213 // Returns the "NormalOrder" nk4Index for given set. Implemented by
214 // specific symmetries
215 static inline nk4Index NormalOrder_impl(nkIndex a, nkIndex b, nkIndex c,
216 nkIndex d);
217};
218
219//! Stores Coulomb(-like) integrals, assuming Q-like symmetry
221//! Stores Coulomb(-like) integrals, assuming W-like symmetry
223//! Stores Coulomb(-like) integrals, assuming L-like symmetry
225//! Stores Coulomb(-like) integrals, assuming no symmetry
227
228} // namespace Coulomb
229
230#include "QkTable.ipp"
Lookup table for Wigner 6J symbols.
Definition SixJTable.hpp:24
Base (pure virtual) class to store Coulomb integrals, and similar. 3 derived classes,...
Definition QkTable.hpp:57
Real P2(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable &sj, const std::vector< double > &fk) const
'Exchange-only', defined via W = Q + P. Optionally, takes pointer to 6J table (faster eval of 6J symb...
Definition QkTable.ipp:230
double * get(int k, nk4Index index)
Directly gets one of the stored elements, given normal-ordered nk4Index.
Definition QkTable.ipp:116
void fill_if(const std::vector< DiracSpinor > &basis, const YkTable &yk, const SelectionRules &SelectionFunction, int k_cut=-1, bool print=true)
Takes a constructed YkTable, and fills Coulomb table with all possible non-zero Qk Coulomb integrals ...
Definition QkTable.ipp:587
Real P(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable *const sj=nullptr) const
'Exchange-only', defined via W = Q + P. Optionally, takes pointer to 6J table (faster eval of 6J symb...
Definition QkTable.ipp:221
bool is_NormalOrdered(nkIndex a, nkIndex b, nkIndex c, nkIndex d) const
Checks if set {a,b,c,d} are already in NormalOrder.
Definition QkTable.hpp:180
bool read(const std::string &fname)
Reads coulomb integrals to disk. Returns false if none read in.
Definition QkTable.ipp:863
bool is_NormalOrdered(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const
Checks if set {a,b,c,d} are already in NormalOrder.
Definition QkTable.hpp:184
void update(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, Real value)
Updates value in table. If not present, adds new value.
Definition QkTable.ipp:72
auto operator->()
Gives arrow access to all underlying vector<unordered_map> functions.
Definition QkTable.hpp:85
bool contains(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const
Checks if given {k,a,b,c,d} is in the table.
Definition QkTable.ipp:98
nk4Index NormalOrder(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const
Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of {a,b,c,d}.
Definition QkTable.ipp:395
nk4Index CurrentOrder(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const
Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be used to check if {a,...
Definition QkTable.ipp:408
static nk4Index FormIndex(nkIndex a, nkIndex b, nkIndex c, nkIndex d)
Converts given set of nkIndex's (in any order) to nk4Index.
Definition QkTable.ipp:417
Real R(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const
Returns 'R', defined via: R := Q / (angular_coef)
Definition QkTable.ipp:179
std::array< nkIndex, 4 > UnFormIndex(const nk4Index &index) const
Breaks nk4Index back into {ia,ib,ic,id}. Not used.
Definition QkTable.ipp:440
void fill(const std::vector< DiracSpinor > &basis, const YkTable &yk, int k_cut=-1, bool print=true)
Takes a constructed YkTable, and fills Coulomb table with all possible non-zero Qk Coulomb integrals,...
Definition QkTable.ipp:456
void write(const std::string &fname) const
Writes coulomb integrals to disk.
Definition QkTable.ipp:839
void summary() const
For testing: prints details of coulomb integrals stored.
Definition QkTable.ipp:16
Real g(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, int tma, int tmb, int tmc, int tmd) const
Returns 'g_abcd'.
Definition QkTable.ipp:272
void add(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, Real value)
adds a new value. Note: does nothing if {k,a,b,c,d} already exists
Definition QkTable.ipp:46
Real Q(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const
Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table....
Definition QkTable.ipp:142
Real W(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable *const sj=nullptr) const
W^k_abcd = Q^k_abcd + \sum_l [k] 6j * Q^l_abdc. Optionally, takes pointer to 6J table (faster eval of...
Definition QkTable.ipp:258
std::size_t count() const
Returns number of stored integrals.
Definition QkTable.ipp:30
bool emptyQ() const
Returns true if table is empty.
Definition QkTable.hpp:117
Calculates + stores Hartree Y functions + Angular (w/ look-up), taking advantage of symmetry.
Definition YkTable.hpp:26
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:41
Functions (+classes) for computing Coulomb integrals.
Definition CoulombIntegrals.cpp:13
double Real
Data type used to store integrals.
Definition QkTable.hpp:15
std::function< bool(int, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d)> SelectionRules
Function type for determining Coulomb(-like) integral selection rules. Takes k and 4 DiracSpinors,...
Definition QkTable.hpp:33
uint64_t nk4Index
index type for set of 4 orbitals {nk,nk,nk,nk} -> nk4Index
Definition QkTable.hpp:17
uint16_t nkIndex
index type for each {nk} (orbital)
Definition QkTable.hpp:19
Symmetry
Symmetry (state index order) for tables.
Definition QkTable.hpp:13
std::function< double(int, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d)> CoulombFunction
Function type for calculating Coulomb(-like) integrals. Takes k and 4 DiracSpinors,...
Definition QkTable.hpp:27