2#include "CoulombIntegrals.hpp"
3#include "IO/ChronoTimer.hpp"
4#include "IO/FRW_fileReadWrite.hpp"
5#include "Physics/AtomData.hpp"
7#include "fmt/format.hpp"
19 std::cout <<
"Stored non-zero Coulomb integrals: \n";
22 for (
auto &qk : m_data) {
23 fmt::print(
"k = {:2}: {}\n", k, qk.size());
28 std::cout <<
"Total: " << total <<
"\n";
34 for (
auto &qk : m_data) {
44 add(k, NormalOrder(a, b, c, d), value);
56 const auto sk = std::size_t(k);
57 if (sk >= m_data.size()) {
58 m_data.resize(sk + 1);
60 m_data.at(sk).insert({index, value});
68 update(k, NormalOrder(a, b, c, d), value);
83 const auto sk = std::size_t(k);
84 if (sk >= m_data.size()) {
85 m_data.resize(sk + 1);
87 m_data.at(sk).insert_or_assign(index, value);
93 const auto sk = std::size_t(k);
94 if (sk >= m_data.size())
96 return m_data.at(sk).find(NormalOrder(a, b, c, d)) != m_data.at(sk).cend();
108 const auto sk = std::size_t(k);
109 if (sk >= m_data.size())
111 return m_data.at(sk).find(index) != m_data.at(sk).cend();
119 const auto sk = std::size_t(k);
120 if (sk >= m_data.size())
123 const auto map_it = m_data.at(sk).find(index);
124 if (map_it == m_data.at(sk).cend())
126 return &(map_it->second);
133 const auto sk = std::size_t(k);
134 if (sk >= m_data.size())
137 const auto map_it = m_data.at(sk).find(NormalOrder(a, b, c, d));
138 if (map_it == m_data.at(sk).cend())
140 return map_it->second;
151 const auto sk = std::size_t(k);
152 if (sk >= m_data.size())
155 const auto map_it = m_data.at(sk).find(index);
156 if (map_it == m_data.at(sk).cend())
158 return map_it->second;
165 const auto tQk = Q(k, a, b, c, d);
177 return tQk / (s * tCkac * tCkbd);
207 const auto [lmin, lmax] =
k_minmax_Q(ka, kb, kd, kc);
208 for (
int l = lmin; l <= lmax; l += 2) {
209 const auto ql = this->Q(l, a, b, d, c);
212 const auto sixj = sj ? sj->
get_2(tja, tjc, 2 * k, tjb, tjd, 2 * l) :
235 const std::vector<double> &fk)
const {
239 if (Coulomb::triangle(a, c, k) == 0 || Coulomb::triangle(k, b, d) == 0)
242 const auto [lmin, lmax] =
k_minmax_Q(a, b, d, c);
243 for (
int l = lmin; l <= lmax; l += 2) {
244 const auto ql = this->Q(l, a, b, d, c);
247 const auto sixj = sj.
get(a, c, k, b, d, l);
250 const auto f_scr_l = (l < (int)fk.size()) ? fk[std::size_t(l)] : 1.0;
252 Pk_abcd += f_scr_l * sixj * ql;
269 return Q(k, a, b, c, d) + P(k, a, b, c, d, sj);
276 int tmb,
int tmc,
int tmd)
const {
278 if (tmc - tma != tmb - tmd)
280 const int twoq = tmc - tma;
285 for (
int k = k0; k <= ki; k += 2) {
286 if (std::abs(twoq) > 2 * k)
302 g += s * tjs1 * tjs2 * Q(k, a, b, c, d);
334 nk4Index out = FormIndex(a, b, c, d);
335 const auto min = std::min({a, b, c, d});
337 const auto tmp = FormIndex(a, d, c, b);
342 const auto tmp = std::min(FormIndex(b, a, d, c), FormIndex(b, c, d, a));
347 const auto tmp = std::min(FormIndex(c, b, a, d), FormIndex(c, d, a, b));
352 const auto tmp = std::min(FormIndex(d, a, b, c), FormIndex(d, c, b, a));
363 const auto tmp1 = FormIndex(a, b, c, d);
364 const auto tmp2 = FormIndex(b, a, d, c);
365 const auto tmp3 = FormIndex(c, d, a, b);
366 const auto tmp4 = FormIndex(d, c, b, a);
367 return std::min({tmp1, tmp2, tmp3, tmp4});
375 const auto tmp1 = FormIndex(a, b, c, d);
376 const auto tmp2 = FormIndex(b, a, d, c);
377 return std::min({tmp1, tmp2});
385 return FormIndex(a, b, c, d);
392 return NormalOrder_impl(a, b, c, d);
406 return FormIndex(a, b, c, d);
434 static_assert(
sizeof(
nkIndex) * 8 == 16);
441std::array<nkIndex, 4>
443 static_assert(
sizeof(
nk4Index) ==
sizeof(std::array<nkIndex, 4>));
444 std::array<nkIndex, 4> set;
445 std::memcpy(&set, &index,
sizeof(
nk4Index));
450 std::swap(set[0], set[3]);
451 std::swap(set[1], set[2]);
457std::array<std::size_t, 4>
459 std::size_t k_cutoff,
461 static_assert(S == Symmetry::Qk);
463 const auto tmp_max_k =
466 (k_cutoff <= 0) ? tmp_max_k : std::min(tmp_max_k, std::size_t(k_cutoff));
468 std::vector<std::size_t> count_non_zero_k_tot(max_k + 1);
469 std::vector<std::size_t> count_non_zero_k_Excited(max_k + 1);
470 std::vector<std::size_t> count_non_zero_k_MBPT(max_k + 1);
472 const auto select_Q_Excited = [eF](int,
const DiracSpinor &s,
479 const auto select_Q_MBPT = [eF](int,
const DiracSpinor &s,
483 return num == 1 || num == 2;
486#pragma omp parallel for
487 for (
auto k = 0ul; k <= max_k; ++k) {
488 const auto ik =
static_cast<int>(k);
489 for (
const auto &a : basis) {
490 for (
const auto &b : basis) {
491 for (
const auto &c : basis) {
494 for (
const auto &d : basis) {
496 if (NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d)) {
498 ++count_non_zero_k_tot[k];
500 if (select_Q_Excited(0, a, b, c, d)) {
501 ++count_non_zero_k_Excited[k];
503 if (select_Q_MBPT(0, a, b, c, d)) {
504 ++count_non_zero_k_MBPT[k];
516 const auto count_non_zero_tot = std::accumulate(
517 count_non_zero_k_tot.begin(), count_non_zero_k_tot.end(), 0ul);
519 const auto count_non_zero_Excited = std::accumulate(
520 count_non_zero_k_Excited.begin(), count_non_zero_k_Excited.end(), 0ul);
522 const auto count_non_zero_MBPT = std::accumulate(
523 count_non_zero_k_MBPT.begin(), count_non_zero_k_MBPT.end(), 0ul);
525 return {count_non_zero_tot, count_non_zero_Excited, count_non_zero_MBPT,
533 const YkTable &yk,
int k_cut,
bool print) {
534 static_assert(S == Symmetry::Qk);
535 IO::ChronoTimer t(
"fill");
553 const auto tmp_max_k =
557 (k_cut <= 0) ? tmp_max_k : std::min(tmp_max_k, std::size_t(k_cut));
559 if (m_data.size() < max_k + 1)
560 m_data.resize(max_k + 1);
563 std::vector<std::size_t> count_non_zero_k(max_k + 1);
564#pragma omp parallel for
565 for (
auto k = 0ul; k <= max_k; ++k) {
566 const auto ik =
static_cast<int>(k);
567 for (
const auto &a : basis) {
568 for (
const auto &b : basis) {
569 for (
const auto &c : basis) {
572 for (
const auto &d : basis) {
574 if (NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d)) {
576 ++count_non_zero_k[k];
586#pragma omp parallel for
587 for (
auto ik = 0ul; ik <= max_k; ++ik) {
588 m_data[ik].reserve(count_non_zero_k[ik]);
593#pragma omp parallel for
594 for (
auto k = 0ul; k <= max_k; ++k) {
595 for (
const auto &a : basis) {
596 for (
const auto &c : basis) {
599 for (
const auto &b : basis) {
600 for (
const auto &d : basis) {
603 const auto normal_index = NormalOrder(a, b, c, d);
604 if (normal_index == CurrentOrder(a, b, c, d)) {
605 add(
int(k), normal_index, 0.0);
613 std::cout <<
"Construct empty table: " << t.lap_reading_str() << std::endl;
620 std::cout <<
"Fill w/ values: " << std::flush;
622#pragma omp parallel for collapse(2)
623 for (
auto ia = 0ul; ia < basis.size(); ++ia) {
624 for (
auto ib = 0ul; ib < basis.size(); ++ib) {
625 const auto &a = basis[ia];
626 const auto &b = basis[ib];
627 for (
const auto &c : basis) {
628 for (
const auto &d : basis) {
629 const auto normal_index = NormalOrder(a, b, c, d);
630 if (normal_index == CurrentOrder(a, b, c, d)) {
631 const auto [kmin, kmax] =
k_minmax_Q(a, b, c, d);
632 for (
int k = kmin; k <= kmax && k <= int(max_k); k += 2) {
633 double *ptr = get(k, normal_index);
634 assert(ptr !=
nullptr);
638 *ptr = yk.
Q(k, a, b, c, d);
648 std::cout << t.lap_reading_str() << std::endl;
659 int k_cut,
bool print) {
660 static_assert(S == Symmetry::Qk);
661 IO::ChronoTimer t(
"fill");
667 const auto tmp_max_k =
671 (k_cut <= 0) ? tmp_max_k : std::min(tmp_max_k, std::size_t(k_cut));
673 if (m_data.size() < max_k + 1)
674 m_data.resize(max_k + 1);
677 std::vector<std::size_t> count_non_zero_k(max_k + 1);
678#pragma omp parallel for
679 for (
auto k = 0ul; k <= max_k; ++k) {
680 const auto ik =
static_cast<int>(k);
681 for (
const auto &a : basis) {
682 for (
const auto &b : basis) {
683 for (
const auto &c : basis) {
686 for (
const auto &d : basis) {
688 if (NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d)) {
690 SelectionFunction(ik, a, b, c, d)) {
691 ++count_non_zero_k[k];
701#pragma omp parallel for
702 for (
auto ik = 0ul; ik <= max_k; ++ik) {
703 m_data[ik].reserve(count_non_zero_k[ik]);
708#pragma omp parallel for
709 for (
auto k = 0ul; k <= max_k; ++k) {
710 for (
const auto &a : basis) {
711 for (
const auto &c : basis) {
714 for (
const auto &b : basis) {
715 for (
const auto &d : basis) {
718 if (!SelectionFunction(
int(k), a, b, c, d))
720 const auto normal_index = NormalOrder(a, b, c, d);
721 if (normal_index == CurrentOrder(a, b, c, d)) {
722 add(
int(k), normal_index, 0.0);
730 std::cout <<
"Construct empty table: " << t.lap_reading_str() << std::endl;
737 std::cout <<
"Fill w/ values: " << std::flush;
739#pragma omp parallel for collapse(2)
740 for (
auto ia = 0ul; ia < basis.size(); ++ia) {
741 for (
auto ib = 0ul; ib < basis.size(); ++ib) {
742 const auto &a = basis[ia];
743 const auto &b = basis[ib];
744 for (
const auto &c : basis) {
745 for (
const auto &d : basis) {
746 const auto normal_index = NormalOrder(a, b, c, d);
747 if (normal_index == CurrentOrder(a, b, c, d)) {
748 const auto [kmin, kmax] =
k_minmax_Q(a, b, c, d);
749 for (
int k = kmin; k <= kmax && k <= int(max_k); k += 2) {
750 if (!SelectionFunction(k, a, b, c, d))
752 double *ptr = get(k, normal_index);
753 assert(ptr !=
nullptr);
757 *ptr = yk.
Q(k, a, b, c, d);
767 std::cout << t.lap_reading_str() << std::endl;
778 IO::ChronoTimer t(
"fill");
800 (k_cut <= 0) ? tmp_max_k : std::min(tmp_max_k, std::size_t(k_cut));
802 if (m_data.size() < max_k + 1)
803 m_data.resize(max_k + 1);
806 std::vector<std::size_t> count_non_zero_k(max_k + 1);
807#pragma omp parallel for
808 for (
auto k = 0ul; k <= max_k; ++k) {
809 const auto ik =
static_cast<int>(k);
810 for (
const auto &a : basis) {
811 for (
const auto &b : basis) {
812 for (
const auto &c : basis) {
813 for (
const auto &d : basis) {
815 if (NormalOrder(a, b, c, d) == CurrentOrder(a, b, c, d)) {
816 if (Fk_SR(ik, a, b, c, d)) {
817 ++count_non_zero_k[k];
827#pragma omp parallel for
828 for (
auto ik = 0ul; ik <= max_k; ++ik) {
829 m_data[ik].reserve(count_non_zero_k[ik]);
834#pragma omp parallel for
835 for (
auto k = 0ul; k <= max_k; ++k) {
836 for (
const auto &a : basis) {
837 for (
const auto &b : basis) {
838 for (
const auto &c : basis) {
839 for (
const auto &d : basis) {
840 if (Fk_SR(
int(k), a, b, c, d)) {
841 const auto normal_index = NormalOrder(a, b, c, d);
842 if (normal_index == CurrentOrder(a, b, c, d)) {
843 add(
int(k), normal_index, 0.0);
852 std::cout <<
"Construct empty table: " << t.lap_reading_str() << std::endl;
859 std::cout <<
"Fill w/ values: " << std::flush;
862#pragma omp parallel for collapse(2)
863 for (std::size_t ia = 0; ia < basis.size(); ++ia) {
864 for (std::size_t ib = 0; ib < basis.size(); ++ib) {
865 const auto &a = basis[ia];
866 const auto &b = basis[ib];
867 for (
const auto &c : basis) {
868 for (
const auto &d : basis) {
869 const auto normal_index = NormalOrder(a, b, c, d);
870 if (normal_index == CurrentOrder(a, b, c, d)) {
871 for (
int k = 0; k <= int(max_k); ++k) {
872 if (Fk_SR(k, a, b, c, d)) {
873 double *ptr = get(k, normal_index);
874 assert(ptr !=
nullptr);
877 *ptr = Fk(k, a, b, c, d);
887 std::cout << t.lap_reading_str() << std::endl;
896 if (fname ==
"false")
899 std::cout <<
"Writing " << count() <<
" integrals to file: " << fname
900 <<
".." << std::flush;
902 const auto rw = IO::FRW::write;
903 IO::FRW::open_binary(f, fname, rw);
905 auto size = m_data.size();
906 rw_binary(f, rw, size);
907 for (
const auto &Q_k : m_data) {
908 auto size_k = Q_k.size();
909 rw_binary(f, rw, size_k);
910 for (
auto [key, value] : Q_k) {
912 rw_binary(f, rw, key_copy, value);
916 std::cout <<
"\n" << std::flush;
922 if (fname ==
"false" || fname.empty())
926 const auto rw = IO::FRW::read;
927 IO::FRW::open_binary(f, fname, rw);
931 std::vector<int> max_n_l;
932 constexpr bool count_orbs =
true;
938 std::cout <<
"Reading: " << fname <<
"\n" << std::flush;
941 rw_binary(f, rw, size);
943 if (m_data.size() == 0)
945 for (std::size_t i = 0; i < m_data.size(); ++i) {
946 auto &Q_k = m_data[i];
947 std::size_t size_k{0};
948 rw_binary(f, rw, size_k);
950 for (std::size_t ik = 0; ik < size_k; ++ik) {
953 rw_binary(f, rw, key, value);
957 if constexpr (count_orbs) {
958 const auto indexes = UnFormIndex(key);
959 for (
const auto index : indexes) {
962 if (max_n_l.size() < l + 1)
963 max_n_l.resize(l + 1);
964 if (n > max_n_l.at(l))
975 std::string basis_str;
976 for (
const auto &n : max_n_l) {
978 basis_str += std::to_string(n);
983 if (!basis_str.empty())
984 basis_str =
"[" + basis_str +
"] ";
986 std::cout <<
"Read " << count() <<
" integrals " << basis_str
987 <<
"from file: " << fname <<
"\n"
Lookup table for Wigner 6J symbols.
Definition SixJTable.hpp:47
double get_2(int a, int b, int c, int d, int e, int f) const
Return 6j symbol {a/2,b/2,c/2,d/2,e/2,f/2}. Note: takes in 2*j/2*k as int.
Definition SixJTable.hpp:76
double get(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f) const
Return "magic" 6j. Pass in either integer (for k), or DiracSpinor, F. e.g.: (F,F,k,...
Definition SixJTable.hpp:88
Base (pure virtual) class to store Coulomb integrals, and similar. 3 derived classes,...
Definition QkTable.hpp:64
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:232
double * get(int k, nk4Index index)
Directly gets one of the stored elements, given normal-ordered nk4Index.
Definition QkTable.ipp:118
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:656
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:223
bool read(const std::string &fname, bool verbose=true)
Reads coulomb integrals to disk. Returns false if none read in.
Definition QkTable.ipp:921
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:458
void write(const std::string &fname, bool verbose=true) const
Writes coulomb integrals to disk.
Definition QkTable.ipp:895
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:74
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:100
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:397
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:410
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:419
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:181
std::array< nkIndex, 4 > UnFormIndex(const nk4Index &index) const
Breaks nk4Index back into {ia,ib,ic,id}. Not used.
Definition QkTable.ipp:442
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:532
void summary() const
For testing: prints details of coulomb integrals stored.
Definition QkTable.ipp:18
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:274
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:48
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:144
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:260
std::size_t count() const
Returns number of stored integrals.
Definition QkTable.ipp:32
Calculates + stores Hartree Y functions + Angular (w/ look-up), taking advantage of symmetry.
Definition YkTable.hpp:26
double Q(const int k, const DiracSpinor &Fa, const DiracSpinor &Fb, const DiracSpinor &Fc, const DiracSpinor &Fd) const
Calculates Qk using the existing yk integrals. Note: Yk and Ck tables must include all required value...
Definition YkTable.cpp:127
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
static int max_tj(const std::vector< DiracSpinor > &orbs)
Returns maximum (2j) found in {orbs}.
Definition DiracSpinor.cpp:266
Index nk_index() const
(n,kappa) index (see AtomData)
Definition DiracSpinor.hpp:101
std::pair< int, int > index_to_nk(std::uint64_t nk_index)
Returns {n, kappa} given nk_index.
Definition Wigner369j.hpp:178
double threej_2(int two_j1, int two_j2, int two_j3, int two_m1, int two_m2, int two_m3)
Calculates wigner 3j symbol. Takes in 2*j (or 2*l) - intput is integer.
Definition Wigner369j.hpp:251
double sixj_2(int two_j1, int two_j2, int two_j3, int two_j4, int two_j5, int two_j6)
6j symbol {j1 j2 j3 \ j4 j5 j6} - [takes 2*j as int]
Definition Wigner369j.hpp:341
int nkindex_to_kappa(std::uint64_t nk_index)
Returns kappa, given nk_index.
Definition Wigner369j.hpp:196
constexpr int neg1pow(int a)
Evaluates (-1)^{a} (for integer a)
Definition Wigner369j.hpp:224
std::pair< int, std::uint64_t > nkindex_to_n_kindex(std::uint64_t nk_index)
Returns {n, kappa_index} given nk_index.
Definition Wigner369j.hpp:188
double tildeCk_kk(int k, int ka, int kb)
tildeCk_kk = (-1)^{ja+1/2}*Ck_kk
Definition Wigner369j.hpp:407
bool Ck_kk_SR(int k, int ka, int kb)
Ck selection rule only. Returns false if C^k=0, true if non-zero.
Definition Wigner369j.hpp:398
constexpr int kindex_to_l(std::uint64_t i)
returns l, given kappa_index
Definition Wigner369j.hpp:116
constexpr int neg1pow_2(int two_a)
Evaluates (-1)^{two_a/2} (for integer a; two_a is even)
Definition Wigner369j.hpp:226
constexpr int triangle(int j1, int j2, int J)
Returns 1 if triangle rule is satisfied. nb: works with j OR twoj!
Definition Wigner369j.hpp:236
constexpr int twoj_k(int ka)
returns 2j given kappa
Definition Wigner369j.hpp:46
std::string l_symbol(int l)
l (int) to symbol (e.g., 0->'s', 1->'p')
Definition AtomData.cpp:110
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:37
int number_below_Fermi(const DiracSpinor &i, const DiracSpinor &j, const DiracSpinor &k, const DiracSpinor &l, double eFermi)
Returns number of orbitals that are below Fermi level. Used for Qk selection.
Definition CoulombIntegrals.cpp:519
uint64_t nk4Index
index type for set of 4 orbitals {nk,nk,nk,nk} -> nk4Index [max n: 256]
Definition QkTable.hpp:19
double Pk_abcd(const int k, const DiracSpinor &Fa, const DiracSpinor &Fb, const DiracSpinor &Fc, const DiracSpinor &Fd)
Exchange only version of W (W-Q): W = Q + P [see Qk above].
Definition CoulombIntegrals.cpp:428
uint16_t nkIndex
index type for each {nk} (orbital) [max n: 256]
Definition QkTable.hpp:23
std::pair< int, int > k_minmax_Q(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d)
Returns min and max k (multipolarity) allowed for Q^k_abcd. Parity rule is included,...
Definition CoulombIntegrals.cpp:572
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:31
void add(std::vector< T > *first, const std::vector< T > &second, const Args &...rest)
Adds any number of vectors, in place (modifies first vector). Must be of same type....
Definition Vector.hpp:106