2 #include "Angular/Wigner369j.hpp"
3 #include "Wavefunction/DiracSpinor.hpp"
9 #include <unordered_map>
26 std::unordered_map<uint64_t, double> m_data{};
28 static auto s(
int i) {
return static_cast<uint8_t
>(i); };
44 int max_2jk()
const {
return m_max_2j_k; }
47 std::size_t
size()
const {
return m_data.size(); }
53 inline double get_2(
int a,
int b,
int c,
int d,
int e,
int f)
const {
56 const auto it = m_data.find(normal_order(a, b, c, d, e, f));
57 return (it == m_data.cend()) ? 0.0 : it->second;
64 template <
class A,
class B,
class C,
class D,
class E,
class F>
65 double get(
const A &a,
const B &b,
const C &c,
const D &d,
const E &e,
67 return get_2(twojk(a), twojk(b), twojk(c), twojk(d), twojk(e), twojk(f));
73 bool contains(
int a,
int b,
int c,
int d,
int e,
int f)
const {
74 const auto it = m_data.find(normal_order(a, b, c, d, e, f));
75 return (it != m_data.cend());
82 if (max_2j_k <= m_max_2j_k)
89 const auto max_2k = 2 * max_2j_k;
90 for (
int a = 0; a <= max_2k; ++a) {
92 for (
int b = a0; b <= max_2k; ++b) {
93 for (
int c = b; c <= max_2k; ++c) {
94 for (
int d = a0; d <= max_2k; ++d) {
95 for (
int e = b; e <= max_2k; ++e) {
96 for (
int f = b; f <= max_2k; ++f) {
102 if (std::abs(sj) > 1.0e-16) {
103 m_data[normal_order(a, b, c, d, e, f)] = sj;
113 m_max_2j_k = max_2j_k;
118 inline static auto make_key(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
119 uint8_t e, uint8_t f) {
120 static_assert(
sizeof(uint64_t) >= 6 *
sizeof(uint8_t));
122 const auto pk =
reinterpret_cast<uint8_t *
>(&key);
123 std::memcpy(pk, &a,
sizeof(uint8_t));
124 std::memcpy(pk + 1, &b,
sizeof(uint8_t));
125 std::memcpy(pk + 2, &c,
sizeof(uint8_t));
126 std::memcpy(pk + 3, &d,
sizeof(uint8_t));
127 std::memcpy(pk + 4, &e,
sizeof(uint8_t));
128 std::memcpy(pk + 5, &f,
sizeof(uint8_t));
131 inline static auto make_key(
int a,
int b,
int c,
int d,
int e,
int f) {
132 return make_key(s(a), s(b), s(c), s(d), s(e), s(f));
136 inline static auto normal_order_level2(
int a,
int b,
int c,
int d,
int e,
141 const auto min_bcef = std::min({b,
c, e,
f});
144 return make_key(s(a), s(b), s(c), s(d), s(e), s(f));
145 }
else if (min_bcef == c) {
146 return make_key(s(a), s(c), s(b), s(d), s(f), s(e));
147 }
else if (min_bcef == e) {
148 return make_key(s(a), s(e), s(f), s(d), s(b), s(c));
149 }
else if (min_bcef == f) {
150 return make_key(s(a), s(f), s(e), s(d), s(c), s(b));
152 assert(
false &&
"Fatal error 170: unreachable");
156 static uint64_t normal_order(
int a,
int b,
int c,
int d,
int e,
int f) {
194 const auto min = std::min({a, b,
c, d, e,
f});
200 return normal_order_level2(a, b, c, d, e, f);
201 }
else if (min == b) {
202 return normal_order_level2(b, a, c, e, d, f);
203 }
else if (min == c) {
204 return normal_order_level2(c, a, b, f, d, e);
205 }
else if (min == d) {
206 return normal_order_level2(d, e, c, a, b, f);
207 }
else if (min == e) {
208 return normal_order_level2(e, d, c, b, a, f);
209 }
else if (min == f) {
210 return normal_order_level2(f, a, e, c, d, b);
212 assert(
false &&
"Fatal error 193: unreachable");
219 static int twojk(
const A &a) {
220 if constexpr (std::is_same_v<A, DiracSpinor>) {
223 static_assert(std::is_same_v<A, int>);
Lookup table for Wigner 6J symbols.
Definition: SixJTable.hpp:24
int max_2jk() const
Returns maximum element (k or 2j) of tables [max(k) = 2*max(j) = max(2j)].
Definition: SixJTable.hpp:44
bool contains(int a, int b, int c, int d, int e, int f) const
Checks if given 6j symbol is in table (note: may not be in table because it's zero)
Definition: SixJTable.hpp:73
void fill(int max_2j_k)
Fill the table. max_2jk is maximum (2*j) or k that appears in the symbols.
Definition: SixJTable.hpp:80
SixJTable()=default
Default contructor: creates empty table.
std::size_t size() const
Returns number of non-zero symbols stored.
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:53
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:65
SixJTable(int max_2j_k)
On construction, calculates + stores all possible 6j symbols up to maximum value of 2j (or k)
Definition: SixJTable.hpp:41
Angular provides functions and classes for calculating and storing angular factors (3,...
Definition: Angular.hpp:37
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:236
bool sixj_zeroQ(int a, int b, int c, int d, int e, int f)
Checks triangle conditions for 6j symbols (for 2*j)
Definition: Wigner369j.hpp:190
double f(RaB r, PrincipalQN n, DiracQN k, Zeff z, AlphaFS a)
Upper radial component.
Definition: DiracHydrogen.cpp:71
constexpr double c
speed of light in a.u. (=1/alpha)
Definition: PhysConst_constants.hpp:17
T min(T first, Args... rest)
Returns minimum of any number of parameters (variadic function)
Definition: Maths.hpp:34