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 <string_view>
9#include <unordered_map>
10
11namespace Coulomb {
12
13//! Symmetry (state index order) for tables.
14enum class Symmetry { Qk, Wk, Lk, none };
15
16//! Convert Symmetry to string
17inline std::string_view to_string(Symmetry s) {
18 switch (s) {
19 case Symmetry::Qk:
20 return "Qk";
21 case Symmetry::Wk:
22 return "Wk";
23 case Symmetry::Lk:
24 return "Lk";
25 case Symmetry::none:
26 return "none";
27 }
28 return "";
29}
30
31//! Data type used to store integrals
32using Real = double;
33
34//! index type for set of 4 orbitals {nk,nk,nk,nk} -> nk4Index [max n: 256]
35//! @details @warning Requires 0<n<256, see \ref Angular::nk_to_index
36using nk4Index = uint64_t;
37
38//! index type for each {nk} (orbital) [max n: 256]
39//! @details @warning Requires 0<n<256, see \ref Angular::nk_to_index
40using nkIndex = uint16_t;
41
42static_assert(sizeof(nkIndex) == sizeof(DiracSpinor::Index));
43
44//! Function type for calculating Coulomb(-like) integrals.
45//! Takes k and 4 DiracSpinors, returns a double
47 std::function<double(int, const DiracSpinor &a, const DiracSpinor &b,
48 const DiracSpinor &c, const DiracSpinor &d)>;
49
50//! Function type for determining Coulomb(-like) integral selection rules.
51//! Takes k and 4 DiracSpinors, returns a true if integral is allowed.
53 std::function<bool(int, const DiracSpinor &a, const DiracSpinor &b,
54 const DiracSpinor &c, const DiracSpinor &d)>;
55
56//==============================================================================
57/*!
58 @brief
59 Base class template to store Coulomb integrals, and similar.
60 3 specific cases (by template instantiation), account for specific symmetrs.
61
62 @details
63 Mostly, a wrapper for std::unordered_map.
64 Stores data in a std::vector of maps, each element (map) for each k
65 (multipolarity).
66 The symmetry is taken into account by defining a "Normal Ordering" of set of
67 orbitals {a,b,c,d}, which is defined as the "smallest" arrangment of equivilant indices. The details depend on the specific symmetry in question:
68
69 ### Qk symmetry:
70
71 - {abcd} = cbad = adcb = cdab = badc = bcda = dabc = dcba.
72 - Normal ordering: "smallest" of above 8 options
73 - [ Also assumes Coulomb selection rules, for @ref fill(), and @ref P(), @ref W() ]
74
75 ### Wk symmetry (same as g):
76
77 - {abcd} = badc = cdab = dcba
78
79 ### Lk symmetry:
80
81 - {abcd} = badc
82
83 ### Nk symmetry:
84
85 - No symmetry assumed; each integral treated as unique.
86
87 @note Hashtable lookup is significant bottleneck. Should look into better hashmaps.
88
89 @warning
90 Requires 0<n<256, see \ref Angular::nk_to_index
91
92 @note The internal summations in @ref P(), @ref P2(), @ref W(), and @ref g()
93 depend on the selection rules, and @p S:
94 for @ref Symmetry::Qk, we assume Coulomb angular selection rules,
95 including parity rule, (via @ref k_minmax_Q);
96 for all other symmetries no explicit selection rule is assumed.
97 The @ref fill() and @ref fill_if() functions also make this assumption;
98 these functions are only available for the @ref Symmetry::Qk symmetry, and
99 in that case, assume the regular Coulomb selection rules.
100*/
101template <Symmetry S>
103
104private:
105 // each vector element corresponds to a 'k'
106 std::vector<std::unordered_map<nk4Index, Real>> m_data{};
107
108public:
109 // 'Rule of zero' (except virtual destructor)
110 // virtual ~CoulombTable() = default;
111
112 /*!
113 @brief Fill table with all non-zero Coulomb Q integrals from a YkTable.
114 @details
115 Fills the table with Q^k_abcd for all orbitals in @p basis, exploiting
116 the 8-fold Qk symmetry to avoid redundant calculations. Uses a precomputed
117 @p yk for the radial integrals.
118
119 Filling proceeds in four stages:
120 1. Count non-zero integrals per k (for map reservation)
121 2. Reserve map capacity
122 3. Initialise all entries to zero (parallelised over k)
123 4. Fill values in parallel (safe since no new map insertions occur)
124
125 @param basis Basis set of orbitals.
126 @param yk Precomputed Yk table for radial integrals.
127 @param k_cut Maximum multipolarity k. Set to <=0 for no cut-off.
128 @param print If true, prints timing and summary.
129
130 @note Only valid for QkTable ( @ref Symmetry::Qk ) (enforced via static_assert).
131 @warning Does not update existing entries; only adds new ones.
132 */
133 void fill(const std::vector<DiracSpinor> &basis, const YkTable &yk,
134 int k_cut = -1, bool print = true);
135
136 /*!
137 @brief Fill table with Coulomb Q integrals satisfying a selection rule.
138 @details
139 Same as default @ref fill(basis, yk, k_cut, print), but only computes and stores
140 integrals for which @p SelectionFunction returns true. Useful for
141 restricting to a particular subset of integrals (e.g., CI- or MBPT-relevant).
142
143 Uses the same four-stage filling strategy as fill(basis, yk, ...).
144
145 @param basis Basis set of orbitals.
146 @param yk Precomputed Yk table for radial integrals.
147 @param SelectionFunction Returns true for integrals to include.
148 @param k_cut Maximum multipolarity k. Set to <=0 for no cut-off.
149 @param print If true, prints timing and summary.
150
151 @note Only valid for QkTable ( @ref Symmetry::Qk ) (enforced via static_assert).
152 @warning Does not update existing entries; only adds new ones.
153 */
154 void fill_if(const std::vector<DiracSpinor> &basis, const YkTable &yk,
155 const SelectionRules &SelectionFunction, int k_cut = -1,
156 bool print = true);
157
158 /*!
159 @brief Fill table using a general CoulombFunction and selection rules.
160 @details
161 Fills the table with Fk(k,a,b,c,d) for all orbitals in @p basis,
162 restricted to entries for which @p Fk_SR returns true, accounting for
163 the symmetry of the table. Unlike the YkTable overloads, this version
164 is general-purpose and does not assume Qk angular selection rules.
165
166 Uses the same four-stage filling strategy as fill(basis, yk, ...).
167
168 @param basis Basis set of orbitals.
169 @param Fk Function to compute the integral value.
170 @param Fk_SR Selection rule; only integrals passing this are stored.
171 @param k_cut Maximum multipolarity k. Set to <=0 for no cut-off.
172 @param print If true, prints timing and summary.
173
174 @warning Does not update existing entries; only adds new ones.
175 */
176 void fill(const std::vector<DiracSpinor> &basis, const CoulombFunction &Fk,
177 const SelectionRules &Fk_SR, int k_cut = -1, bool print = true);
178
179 /*!
180 @brief Re-calculate all existing table entries using a CoulombFunction.
181 @details
182 Updates all integrals currently stored in the table by re-evaluating
183 Fk(k,a,b,c,d) using the provided @ref CoulombFunction() for each entry.
184 Unlike @ref fill(), this recalculates all
185 existing entries and does not add new ones. Useful for iterating.
186
187 @warning Note: does not calculate any new integrals;
188 only re-calculates existing ones.
189 Table must have corect size/shape before calling.
190
191 Damping: With \f$\eta = \text{damp}\f$, integrals are updated as:
192 \f[
193 Q^k_{abcd} \to \eta Q^k_{abcd} + (1-\eta) Fk(k,a,b,c,d)
194 \f]
195 where @p Fk is a @ref CoulombFunction. \f$\eta=0\f$ means no damping.
196 Must be between 0 and 1 (0 is allowed, 1 is not).
197
198 @param basis Basis set of orbitals.
199 @param Fk Function to compute the integral value.
200 @param damp Damping factor, \f$\eta \in [0,1)\f$. 0 means no damping.
201 @param print If true, prints a progress bar.
202 */
203 void update(const std::vector<DiracSpinor> &basis, const CoulombFunction &Fk,
204 double damp, bool print = true);
205
206 //! Gives arrow access to all underlying vector<unordered_map> functions
207 auto operator->() { return &m_data; }
208
209 //! For testing: prints details of coulomb integrals stored
210 void summary() const;
211
212 //! Returns number of stored integrals
213 std::size_t count() const;
214
215 //!
216 /*! Maximum k stored in table. If table is empty, returns '-1'
217 @details
218 @note Based on _size_ of map only; doesn't check for values.
219 May sometimes have a map with no non-zero integrals for a given k.
220 Guarenteed to be no integrals with k larger than this;
221 no guarentee that there are non-zero integrals at or below this k.
222 */
223 int max_k() const { return int(m_data.size()) - 1; }
224
225 //! adds a new value. Note: does nothing if {k,a,b,c,d} already exists
226 void add(int k, const DiracSpinor &a, const DiracSpinor &b,
227 const DiracSpinor &c, const DiracSpinor &d, Real value);
228 //! adds a new value. Note: does nothing if {k,a,b,c,d} already exists
229 void add(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, Real value);
230 //! adds a new value. Note: does nothing if {k,a,b,c,d} already exists
231 void add(int k, nk4Index index, Real value);
232
233 //! Updates value in table. If not present, adds new value
234 void update(int k, const DiracSpinor &a, const DiracSpinor &b,
235 const DiracSpinor &c, const DiracSpinor &d, Real value);
236 //! Updates value in table. If not present, adds new value
237 void update(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, Real value);
238 //! Updates value in table. If not present, adds new value
239 void update(int k, nk4Index index, Real value);
240
241 //! Checks if given {k,a,b,c,d} is in the table
242 bool contains(int k, const DiracSpinor &a, const DiracSpinor &b,
243 const DiracSpinor &c, const DiracSpinor &d) const;
244 //! Checks if given {k,a,b,c,d} is in the table
245 bool contains(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const;
246 //! Checks if given {k,a,b,c,d} is in the table
247 bool contains(int k, nk4Index index) const;
248
249 //! Returns true if table is empty
250 bool emptyQ() const {
251 return (m_data.size() == 0);
252 // nb: possible to be empty if size > 0... (but doesn't matter..)
253 }
254
255 /*! Counts number of non-zero Coulomb integrals, accounting for symmetry
256 @details
257
258 @note Specifically assumes Qk selection rules, and therefore only works for Qk.
259
260 In theory, easily updated for general symmetry/selection rules,
261 but this is usually the bottle-neck!
262 */
263 std::array<std::size_t, 4>
264 count_non_zero_integrals(const std::vector<DiracSpinor> &basis,
265 std::size_t max_k = 99, double eF = 0.0) const;
266
267 //! Retrieve a stored Q. If not present, returns 0. (Returns exactly as
268 //! stored in table.)
269 Real Q(int k, const DiracSpinor &a, const DiracSpinor &b,
270 const DiracSpinor &c, const DiracSpinor &d) const;
271
272 //! Retrieve a stored Q. If not present, returns 0. (Returns exactly as
273 //! stored in table.)
274 Real Q(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const;
275
276 //! Retrieve a stored Q. If not present, returns 0. (Returns exactly as
277 //! stored in table.)
278 Real Q(int k, nk4Index index) const;
279
280 //! Returns 'R', defined via: R := Q / (angular_coef)
281 Real R(int k, const DiracSpinor &a, const DiracSpinor &b,
282 const DiracSpinor &c, const DiracSpinor &d) const;
283
284 //! Returns 'R', defined via: R := Q / (angular_coef)
285 Real R(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const;
286
287 /*!
288 @brief Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc.
289 @details
290 Computes the exchange part of the antisymmetrised W = Q + P integral.
291 Optionally uses a precomputed 6J table for faster evaluation.
292 @note For @ref Symmetry::Qk, l is iterated using Coulomb angular selection
293 rule bounds (k_minmax_Q); for all other symmetries, l runs over
294 [0, max_k()]. See @ref CoulombTable.
295 */
296 Real P(int k, const DiracSpinor &a, const DiracSpinor &b,
297 const DiracSpinor &c, const DiracSpinor &d,
298 const Angular::SixJTable *const sj = nullptr) const;
299
300 /*!
301 @brief Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc.
302 @details
303 As @ref P(int, const DiracSpinor&, ...) but takes @ref nkIndex arguments.
304 @note For @ref Symmetry::Qk, l is iterated using Coulomb angular selection
305 rule bounds (k_minmax_Q); for all other symmetries, l runs over
306 [0, max_k()]. See @ref CoulombTable.
307 */
308 Real P(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d,
309 const Angular::SixJTable *const sj = nullptr) const;
310
311 /*!
312 @brief Exchange integral P^k_abcd with effective Coulomb screening.
313 @details
314 As @ref P(), but each l term is weighted by a screening factor fk[l].
315 @note For @ref Symmetry::Qk, l is iterated using Coulomb angular selection
316 rule bounds (k_minmax_Q); for all other symmetries, l runs over
317 [0, max_k()]. See @ref CoulombTable.
318 */
319 Real P2(int k, const DiracSpinor &a, const DiracSpinor &b,
320 const DiracSpinor &c, const DiracSpinor &d,
321 const Angular::SixJTable &sj, const std::vector<double> &fk) const;
322
323 /*!
324 @brief Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd.
325 @details
326 Returns Q + P. Optionally uses a precomputed 6J table.
327 @note l iteration in P() depends on symmetry S; see @ref P() and @ref CoulombTable.
328 */
329 Real W(int k, const DiracSpinor &a, const DiracSpinor &b,
330 const DiracSpinor &c, const DiracSpinor &d,
331 const Angular::SixJTable *const sj = nullptr) const;
332
333 /*!
334 @brief Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd.
335 @details
336 As @ref W(int, const DiracSpinor&, ...) but takes @ref nkIndex arguments.
337 @note l iteration in P() depends on symmetry S; see @ref P() and @ref CoulombTable.
338 */
339 Real W(int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d,
340 const Angular::SixJTable *const sj = nullptr) const;
341
342 /*!
343 @brief Full matrix element g_abcd with explicit magnetic quantum numbers.
344 @details
345 Sums over k, weighted by 3j symbols, using the stored Q^k values.
346 @note For @ref Symmetry::Qk, k is iterated using Coulomb angular selection
347 rule bounds (step 2); for all other symmetries, k runs over
348 [0, max_k()] with step 1. See @ref CoulombTable.
349 */
350 Real g(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c,
351 const DiracSpinor &d, int tma, int tmb, int tmc, int tmd) const;
352
353 //! Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of
354 //! {a,b,c,d}
355 nk4Index NormalOrder(const DiracSpinor &a, const DiracSpinor &b,
356 const DiracSpinor &c, const DiracSpinor &d) const;
357 //! Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of
358 //! {a,b,c,d}
360
361 //! Checks if set {a,b,c,d} are already in NormalOrder
363 return NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d);
364 }
365 //! Checks if set {a,b,c,d} are already in NormalOrder
366 bool is_NormalOrdered(const DiracSpinor &a, const DiracSpinor &b,
367 const DiracSpinor &c, const DiracSpinor &d) const {
368 return NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d);
369 }
370
371 //! Writes coulomb integrals to disk
372 void write(const std::string &fname, bool verbose = true) const;
373 //! Reads coulomb integrals to disk. Returns false if none read in
374 bool read(const std::string &fname, bool verbose = true);
375
376 //! Directly gets one of the stored elements, given normal-ordered nk4Index
377 double *get(int k, nk4Index index);
378
379 //! Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be
380 //! used to check if {a,b,c,d} are already in 'NormalOrder'
381 nk4Index CurrentOrder(const DiracSpinor &a, const DiracSpinor &b,
382 const DiracSpinor &c, const DiracSpinor &d) const;
383
384 //! Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be
385 //! used to check if {a,b,c,d} are already in 'NormalOrder'
387
388 //! Converts given set of nkIndex's (in any order) to nk4Index
389 static nk4Index FormIndex(nkIndex a, nkIndex b, nkIndex c, nkIndex d);
390
391 //! Breaks nk4Index back into {ia,ib,ic,id}. Not often used.
392 std::array<nkIndex, 4> UnFormIndex(const nk4Index &index) const;
393
394private:
395 // Returns the "NormalOrder" nk4Index for given set. Implemented by
396 // specific symmetries
397 static inline nk4Index NormalOrder_impl(nkIndex a, nkIndex b, nkIndex c,
398 nkIndex d);
399};
400
401/*!
402 @brief Coulomb integral table with 8-fold Qk symmetry.
403 @details
404 Stores Q^k_abcd assuming the symmetry:
405
406 - {abcd} = cbad = adcb = cdab = badc = bcda = dabc = dcba.
407
408 Normal ordering is the lexicographically smallest arrangement among
409 these 8 equivalents.
410
411 @note See @ref CoulombTable note regarding selection rules assumptions
412*/
414
415/*!
416 @brief Coulomb integral table with 4-fold Wk symmetry.
417 @details
418 Stores integrals assuming the symmetry:
419 {abcd} = badc = cdab = dcba.
420*/
422
423/*!
424 @brief Coulomb integral table with 2-fold Lk symmetry.
425 @details
426 Stores integrals assuming the symmetry:
427 {abcd} = badc.
428*/
430
431/*!
432 @brief Coulomb integral table with no assumed symmetry.
433 @details
434 Each {k,a,b,c,d} is treated as a unique entry; no normal ordering is applied.
435*/
437
438//==============================================================================
439//==============================================================================
440//==============================================================================
441
442/*!
443 @brief Estimate memory required for a QkTable for a given basis.
444 @details
445 Given the @p basis_string, counts the number of non-zero Coulomb integrals
446 using Qk symmetry and angular selection rules.
447 Reports the estimated memory usage in GB for three subsets:
448 - All possible Q^k integrals (e.g., structure radiation)
449 - Excited-only integrals (all four orbitals above the Fermi level) [CI]
450 - Core-Excited integrals (1 or 2 orbitals below Fermi level) [MBPT]
451
452 - And @ref CoulombTable::count_non_zero_integrals() to count integrals
453 - Uses @ref estimate_memory_GB() to convert integral counts to memory estimates.
454
455 @note count_non_zero_integrals() takes non-trivial time for large basis
456
457 @param basis_string Basis specification string (e.g., "20spdf").
458 @param core_string Core configuration string (e.g., "[Xe]").
459 Used to determine the Fermi level.
460 Pass an empty string for no core.
461 @param k_cut Maximum multipolarity k to consider.
462*/
463void estimate_memory_usage(const std::string &basis_string,
464 const std::string &core_string, int k_cut = 999);
465
466//! Estimate memory required for a Qk table
467double estimate_memory_GB(std::size_t number_of_integrals,
468 double efficiency = 0.65);
469
470} // namespace Coulomb
471
472#include "QkTable.ipp"
Lookup table for Wigner 6j symbols.
Definition SixJTable.hpp:68
Base class template to store Coulomb integrals, and similar. 3 specific cases (by template instantiat...
Definition QkTable.hpp:102
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 integral P^k_abcd with effective Coulomb screening.
Definition QkTable.ipp:245
double * get(int k, nk4Index index)
Directly gets one of the stored elements, given normal-ordered nk4Index.
Definition QkTable.ipp:121
void fill_if(const std::vector< DiracSpinor > &basis, const YkTable &yk, const SelectionRules &SelectionFunction, int k_cut=-1, bool print=true)
Fill table with Coulomb Q integrals satisfying a selection rule.
Definition QkTable.ipp:691
Real P(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable *const sj=nullptr) const
Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc.
Definition QkTable.ipp:236
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:362
void update(const std::vector< DiracSpinor > &basis, const CoulombFunction &Fk, double damp, bool print=true)
Re-calculate all existing table entries using a CoulombFunction.
Definition QkTable.ipp:935
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:366
bool read(const std::string &fname, bool verbose=true)
Reads coulomb integrals to disk. Returns false if none read in.
Definition QkTable.ipp:1013
std::array< std::size_t, 4 > count_non_zero_integrals(const std::vector< DiracSpinor > &basis, std::size_t max_k=99, double eF=0.0) const
Definition QkTable.ipp:488
void write(const std::string &fname, bool verbose=true) const
Writes coulomb integrals to disk.
Definition QkTable.ipp:987
auto operator->()
Gives arrow access to all underlying vector<unordered_map> functions.
Definition QkTable.hpp:207
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:103
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:427
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:440
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:449
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:184
std::array< nkIndex, 4 > UnFormIndex(const nk4Index &index) const
Breaks nk4Index back into {ia,ib,ic,id}. Not often used.
Definition QkTable.ipp:472
void fill(const std::vector< DiracSpinor > &basis, const YkTable &yk, int k_cut=-1, bool print=true)
Fill table with all non-zero Coulomb Q integrals from a YkTable.
Definition QkTable.ipp:564
int max_k() const
Definition QkTable.hpp:223
void summary() const
For testing: prints details of coulomb integrals stored.
Definition QkTable.ipp:19
Real g(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, int tma, int tmb, int tmc, int tmd) const
Full matrix element g_abcd with explicit magnetic quantum numbers.
Definition QkTable.ipp:297
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:51
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:147
Real W(int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable *const sj=nullptr) const
Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd.
Definition QkTable.ipp:283
std::size_t count() const
Returns number of stored integrals.
Definition QkTable.ipp:35
bool emptyQ() const
Returns true if table is empty.
Definition QkTable.hpp:250
Calculates + stores Hartree Y functions + Angular (w/ look-up), taking advantage of symmetry.
Definition YkTable.hpp:31
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
Functions (+classes) for computing Coulomb integrals.
Definition CoulombBreit.cpp:13
void estimate_memory_usage(const std::string &basis_string, const std::string &core_string, int k_cut)
Estimate memory required for a QkTable for a given basis.
Definition QkTable.cpp:8
double Real
Data type used to store integrals.
Definition QkTable.hpp:32
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:54
std::string_view to_string(Symmetry s)
Convert Symmetry to string.
Definition QkTable.hpp:17
uint64_t nk4Index
index type for set of 4 orbitals {nk,nk,nk,nk} -> nk4Index [max n: 256]
Definition QkTable.hpp:36
uint16_t nkIndex
index type for each {nk} (orbital) [max n: 256]
Definition QkTable.hpp:40
double estimate_memory_GB(std::size_t number_of_integrals, double load_factor)
Estimate memory required for a Qk table.
Definition QkTable.cpp:76
Symmetry
Symmetry (state index order) for tables.
Definition QkTable.hpp:14
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:48