2#include "Angular/Wigner369j.hpp"
3#include "Wavefunction/DiracSpinor.hpp"
9#include <unordered_map>
21int twojk(
const A &a) {
22 if constexpr (std::is_same_v<A, DiracSpinor>) {
24 }
else if constexpr (std::is_same_v<A, int>) {
27 static_assert(std::is_same_v<A, std::size_t>);
28 return 2 *
static_cast<int>(a);
34template <
class A,
class B,
class C,
class D,
class E,
class F>
35double SixJ(
const A &a,
const B &b,
const C &c,
const D &d,
const E &e,
37 return sixj_2(twojk(a), twojk(b), twojk(c), twojk(d), twojk(e), twojk(f));
49 std::unordered_map<uint64_t, double> m_data{};
51 static auto s(
int i) {
return static_cast<uint8_t
>(i); };
67 int max_2jk()
const {
return m_max_2j_k; }
70 std::size_t
size()
const {
return m_data.size(); }
76 inline double get_2(
int a,
int b,
int c,
int d,
int e,
int f)
const {
79 const auto it = m_data.find(normal_order(a, b, c, d, e, f));
80 return (it == m_data.cend()) ? 0.0 : it->second;
87 template <
class A,
class B,
class C,
class D,
class E,
class F>
88 double get(
const A &a,
const B &b,
const C &c,
const D &d,
const E &e,
90 return get_2(twojk(a), twojk(b), twojk(c), twojk(d), twojk(e), twojk(f));
96 bool contains(
int a,
int b,
int c,
int d,
int e,
int f)
const {
97 const auto it = m_data.find(normal_order(a, b, c, d, e, f));
98 return (it != m_data.cend());
105 if (max_2j_k <= m_max_2j_k)
112 const auto max_2k = 2 * max_2j_k;
113 for (
int a = 0; a <= max_2k; ++a) {
115 for (
int b = a0; b <= max_2k; ++b) {
116 for (
int c = b; c <= max_2k; ++c) {
117 for (
int d = a0; d <= max_2k; ++d) {
118 for (
int e = b; e <= max_2k; ++e) {
119 for (
int f = b; f <= max_2k; ++f) {
125 if (std::abs(sj) > 1.0e-16) {
126 m_data[normal_order(a, b, c, d, e, f)] = sj;
136 m_max_2j_k = max_2j_k;
141 inline static auto make_key(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
142 uint8_t e, uint8_t f) {
143 static_assert(
sizeof(uint64_t) >= 6 *
sizeof(uint8_t));
145 const auto pk =
reinterpret_cast<uint8_t *
>(&key);
146 std::memcpy(pk, &a,
sizeof(uint8_t));
147 std::memcpy(pk + 1, &b,
sizeof(uint8_t));
148 std::memcpy(pk + 2, &c,
sizeof(uint8_t));
149 std::memcpy(pk + 3, &d,
sizeof(uint8_t));
150 std::memcpy(pk + 4, &e,
sizeof(uint8_t));
151 std::memcpy(pk + 5, &f,
sizeof(uint8_t));
154 inline static auto make_key(
int a,
int b,
int c,
int d,
int e,
int f) {
155 return make_key(s(a), s(b), s(c), s(d), s(e), s(f));
159 inline static auto normal_order_level2(
int a,
int b,
int c,
int d,
int e,
164 const auto min_bcef = std::min({b,
c, e,
f});
167 return make_key(s(a), s(b), s(c), s(d), s(e), s(f));
168 }
else if (min_bcef == c) {
169 return make_key(s(a), s(c), s(b), s(d), s(f), s(e));
170 }
else if (min_bcef == e) {
171 return make_key(s(a), s(e), s(f), s(d), s(b), s(c));
172 }
else if (min_bcef == f) {
173 return make_key(s(a), s(f), s(e), s(d), s(c), s(b));
175 assert(
false &&
"Fatal error 170: unreachable");
179 static uint64_t normal_order(
int a,
int b,
int c,
int d,
int e,
int f) {
217 const auto min = std::min({a, b,
c, d, e,
f});
223 return normal_order_level2(a, b, c, d, e, f);
224 }
else if (min == b) {
225 return normal_order_level2(b, a, c, e, d, f);
226 }
else if (min == c) {
227 return normal_order_level2(c, a, b, f, d, e);
228 }
else if (min == d) {
229 return normal_order_level2(d, e, c, a, b, f);
230 }
else if (min == e) {
231 return normal_order_level2(e, d, c, b, a, f);
232 }
else if (min == f) {
233 return normal_order_level2(f, a, e, c, d, b);
235 assert(
false &&
"Fatal error 193: unreachable");
Lookup table for Wigner 6J symbols.
Definition SixJTable.hpp:47
int max_2jk() const
Returns maximum element (k or 2j) of tables [max(k) = 2*max(j) = max(2j)].
Definition SixJTable.hpp:67
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:96
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:103
SixJTable()=default
Default contructor: creates empty table.
std::size_t size() const
Returns number of non-zero symbols stored.
Definition SixJTable.hpp:70
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
SixJTable(int max_2j_k)
On construction, calculates + stores all possible 6j symbols up to maximum value of 2j (or k)
Definition SixJTable.hpp:64
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)
6j symbol {j1 j2 j3 \ j4 j5 j6} - [takes 2*j as int]
Definition Wigner369j.hpp:341
double SixJ(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f)
"Magic" 6j, for integers and DiracSpinors. Pass int (for k), or DiracSpinor for j....
Definition SixJTable.hpp:35
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:295
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