2#include "Angular/Wigner369j.hpp"
3#include "Wavefunction/DiracSpinor.hpp"
9#include <unordered_map>
21 if constexpr (std::is_same_v<A, DiracSpinor>) {
23 }
else if constexpr (std::is_same_v<A, int>) {
26 static_assert(std::is_same_v<A, std::size_t>);
27 return 2 *
static_cast<int>(a);
39template <
class A,
class B,
class C,
class D,
class E,
class F>
40double SixJ(
const A &a,
const B &b,
const C &c,
const D &d,
const E &e,
70 std::unordered_map<uint64_t, double> m_data{};
72 static auto s(
int i) {
return static_cast<uint8_t
>(i); };
88 int max_2jk()
const {
return m_max_2j_k; }
91 std::size_t
size()
const {
return m_data.size(); }
100 inline double get_2(
int a,
int b,
int c,
int d,
int e,
int f)
const {
103 const auto it = m_data.find(normal_order(a, b, c, d, e, f));
104 return (it == m_data.cend()) ? 0.0 : it->second;
115 template <
class A,
class B,
class C,
class D,
class E,
class F>
116 double get(
const A &a,
const B &b,
const C &c,
const D &d,
const E &e,
123 bool contains(
int a,
int b,
int c,
int d,
int e,
int f)
const {
124 const auto it = m_data.find(normal_order(a, b, c, d, e, f));
125 return (it != m_data.cend());
138 if (max_2j_k <= m_max_2j_k)
145 const auto max_2k = 2 * max_2j_k;
146 for (
int a = 0; a <= max_2k; ++a) {
148 for (
int b = a0; b <= max_2k; ++b) {
149 for (
int c = b; c <= max_2k; ++c) {
150 for (
int d = a0; d <= max_2k; ++d) {
151 for (
int e = b; e <= max_2k; ++e) {
152 for (
int f = b; f <= max_2k; ++f) {
158 if (std::abs(sj) > 1.0e-16) {
159 m_data[normal_order(a, b, c, d, e, f)] = sj;
169 m_max_2j_k = max_2j_k;
174 inline static auto make_key(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
175 uint8_t e, uint8_t f) {
176 static_assert(
sizeof(uint64_t) >= 6 *
sizeof(uint8_t));
178 const auto pk =
reinterpret_cast<uint8_t *
>(&key);
179 std::memcpy(pk, &a,
sizeof(uint8_t));
180 std::memcpy(pk + 1, &b,
sizeof(uint8_t));
181 std::memcpy(pk + 2, &c,
sizeof(uint8_t));
182 std::memcpy(pk + 3, &d,
sizeof(uint8_t));
183 std::memcpy(pk + 4, &e,
sizeof(uint8_t));
184 std::memcpy(pk + 5, &f,
sizeof(uint8_t));
187 inline static auto make_key(
int a,
int b,
int c,
int d,
int e,
int f) {
188 return make_key(s(a), s(b), s(c), s(d), s(e), s(f));
192 inline static auto normal_order_level2(
int a,
int b,
int c,
int d,
int e,
197 const auto min_bcef = std::min({b,
c, e,
f});
200 return make_key(s(a), s(b), s(c), s(d), s(e), s(f));
201 }
else if (min_bcef == c) {
202 return make_key(s(a), s(c), s(b), s(d), s(f), s(e));
203 }
else if (min_bcef == e) {
204 return make_key(s(a), s(e), s(f), s(d), s(b), s(c));
205 }
else if (min_bcef == f) {
206 return make_key(s(a), s(f), s(e), s(d), s(c), s(b));
208 assert(
false &&
"Fatal error 170: unreachable");
212 static uint64_t normal_order(
int a,
int b,
int c,
int d,
int e,
int f) {
250 const auto min = std::min({a, b,
c, d, e,
f});
256 return normal_order_level2(a, b, c, d, e, f);
257 }
else if (min == b) {
258 return normal_order_level2(b, a, c, e, d, f);
259 }
else if (min == c) {
260 return normal_order_level2(c, a, b, f, d, e);
261 }
else if (min == d) {
262 return normal_order_level2(d, e, c, a, b, f);
263 }
else if (min == e) {
264 return normal_order_level2(e, d, c, b, a, f);
265 }
else if (min == f) {
266 return normal_order_level2(f, a, e, c, d, b);
268 assert(
false &&
"Fatal error 193: unreachable");
Lookup table for Wigner 6j symbols.
Definition SixJTable.hpp:68
int max_2jk() const
Returns the maximum 2j (or k) currently stored; max(k) = 2*max(j).
Definition SixJTable.hpp:88
bool contains(int a, int b, int c, int d, int e, int f) const
Returns true if the symbol is present in the table (absent symbols may be zero or simply out of range...
Definition SixJTable.hpp:123
void fill(int max_2j_k)
Extends the table to cover all symbols up to max_2j_k.
Definition SixJTable.hpp:136
SixJTable()=default
Constructs an empty table; extend later with fill() or get().
std::size_t size() const
Returns the number of non-zero symbols stored in the table.
Definition SixJTable.hpp:91
double get_2(int a, int b, int c, int d, int e, int f) const
Returns 6j symbol {a/2, b/2, c/2; d/2, e/2, f/2}.
Definition SixJTable.hpp:100
double get(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f) const
"Magic" table lookup: pass integers (for k) or DiracSpinors (for j).
Definition SixJTable.hpp:116
SixJTable(int max_2j_k)
Constructs the table, pre-filling all symbols up to max_2j_k.
Definition SixJTable.hpp:85
Angular provides functions and classes for calculating and storing angular factors (3,...
Definition CkTable.cpp:7
double sixj_2(int two_j1, int two_j2, int two_j3, int two_j4, int two_j5, int two_j6)
Wigner 6j symbol {j1 j2 j3 | j4 j5 j6}. Inputs are 2*j as integers.
Definition Wigner369j.hpp:431
int twojk(const A &a)
Returns 2*k if a is an integer, or 2*j if a is a DiracSpinor.
Definition SixJTable.hpp:20
double SixJ(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f)
"Magic" 6j symbol accepting integers or DiracSpinors.
Definition SixJTable.hpp:40
bool sixj_zeroQ(int a, int b, int c, int d, int e, int f)
Returns true if the 6j symbol is zero by triangle/parity rules. Inputs are 2*j.
Definition Wigner369j.hpp:357
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:63
T min(T first, Args... rest)
Returns minimum of any number of parameters (variadic function)
Definition Maths.hpp:34