5#include <gsl/gsl_sf_coupling.h>
44constexpr int l_k(
int ka) {
return (ka > 0) ? ka : -ka - 1; }
46constexpr int twoj_k(
int ka) {
return (ka > 0) ? 2 * ka - 1 : -2 * ka - 1; }
49 return (ka % 2 == 0) ? ((ka > 0) ? 1 : -1) : ((ka < 0) ? 1 : -1);
52constexpr int parity_l(
int l) {
return (l % 2 == 0) ? 1 : -1; }
54constexpr int l_tilde_k(
int ka) {
return (ka > 0) ? ka - 1 : -ka; }
57 return ((2 * l - twoj) * (twoj + 1)) / 2;
61 const auto l_minus = (twoj - 1) / 2;
62 const auto l_minus_pi = (l_minus % 2 == 0) ? 1 : -1;
63 const auto l = l_minus_pi == pi ? l_minus : l_minus + 1;
67inline constexpr bool zeroQ(
double x,
double eps = 1.0e-10) {
68 return x >= 0 ? x < eps : x > -eps;
99 return (ka < 0) ? std::uint64_t(-2 * ka - 2) : std::uint64_t(2 * ka - 1);
105 return (i % 2 == 0) ? int(-(i + 2) / 2) : int((i + 1) / 2);
111 return (i % 2 == 0) ? int(i + 1) : int(i);
117 return (i % 2 == 0) ? int(i / 2) : int((i + 1) / 2);
129 return (l == 0) ? 0 : std::uint64_t(2 * l);
146 const std::uint64_t nn =
static_cast<std::uint64_t
>(n);
147 return nn * nn - 2 * nn + 1;
193 const auto n = 1 + int(std::sqrt(nk_index));
200inline std::pair<int, std::uint64_t>
202 const auto n = 1 + int(std::sqrt(nk_index));
204 return {n, kappa_index};
210 const auto n = 1 + int(std::sqrt(nk_index));
218 const auto n = 1 + int(std::sqrt(nk_index));
226 const auto n = 1 + int(std::sqrt(
double(nk_index) + 0.01));
233constexpr bool evenQ(
int a) {
return (a % 2 == 0); }
235constexpr bool evenQ_2(
int two_a) {
return (two_a % 4 == 0); }
243constexpr int parity(
int la,
int lb,
int k) {
244 return evenQ(la + lb + k) ? 1 : 0;
251 return ((j1 + j2 < J) || (std::abs(j1 - j2) > J)) ? 0 : 1;
255 return (m1 + m2 + m3 != 0) ? 0 : 1;
277inline double threej_2(
int two_j1,
int two_j2,
int two_j3,
int two_m1,
278 int two_m2,
int two_m3) {
282 return gsl_sf_coupling_3j(two_j1, two_j2, two_j3, two_m1, two_m2, two_m3);
302 if (
triangle(two_j1, two_j2, two_k) == 0)
305 auto s =
evenQ_2(two_j1 + 1) ? 1.0 : -1.0;
306 return s / std::sqrt(two_j1 + 1);
308 return gsl_sf_coupling_3j(two_j1, two_j2, two_k, -1, 1, 0);
331inline double cg_2(
int two_j1,
int two_m1,
int two_j2,
int two_m2,
int two_J,
336 if ((two_j1 - two_j2 + two_M) % 4 == 0)
338 return sign * std::sqrt(two_J + 1.) *
339 gsl_sf_coupling_3j(two_j1, two_j2, two_J, two_m1, two_m2, -two_M);
357inline bool sixj_zeroQ(
int a,
int b,
int c,
int d,
int e,
int f) {
366 if (!
evenQ(a + b + c))
368 if (!
evenQ(c + d + e))
370 if (!
evenQ(b + d + f))
372 if (!
evenQ(e + f + a))
395inline bool sixjTriads(std::optional<int> a, std::optional<int> b,
396 std::optional<int> c, std::optional<int> d,
397 std::optional<int> e, std::optional<int> f) {
400 if (a && b && c &&
triangle(*a, *b, *c) == 0)
402 if (c && d && e &&
triangle(*c, *d, *e) == 0)
404 if (a && e && f &&
triangle(*a, *e, *f) == 0)
406 if (b && d && f &&
triangle(*b, *d, *f) == 0)
431inline double sixj_2(
int two_j1,
int two_j2,
int two_j3,
int two_j4,
int two_j5,
433 if (
sixj_zeroQ(two_j1, two_j2, two_j3, two_j4, two_j5, two_j6))
435 return gsl_sf_coupling_6j(two_j1, two_j2, two_j3, two_j4, two_j5, two_j6);
459inline double ninej_2(
int two_j1,
int two_j2,
int two_j3,
int two_j4,
460 int two_j5,
int two_j6,
int two_j7,
int two_j8,
462 return gsl_sf_coupling_9j(two_j1, two_j2, two_j3, two_j4, two_j5, two_j6,
463 two_j7, two_j8, two_j9);
486inline double Ck_kk(
int k,
int ka,
int kb) {
493 auto sign =
evenQ_2(two_ja + 1) ? 1 : -1;
494 auto f = std::sqrt((two_ja + 1) * (two_jb + 1));
519inline double Ck_kk_mmq(
int k,
int ka,
int kb,
int twoma,
int twomb,
int twoq) {
520 const auto tja =
twoj_k(ka);
521 const auto tjb =
twoj_k(kb);
523 threej_2(tja, 2 * k, tjb, -twoma, twoq, twomb) *
Ck_kk(k, ka, kb);
559 return m1tjph *
Ck_kk(k, ka, kb);
584 const auto aka = std::abs(ka);
585 const auto akb = std::abs(kb);
587 auto kmin = std::abs(aka - akb);
588 auto kmax = aka + akb - 1;
622inline double S_kk(
int ka,
int kb) {
630 auto sign = (((tja + 2 * la + 3) / 2) % 2 == 0) ? 1 : -1;
631 auto f = std::sqrt((tja + 1) * (tjb + 1) * 1.5);
633 auto sixj_sign = ((ka + kb) % 2 == 0) ? 1.0 : -1.0;
634 auto sixj = 0.5 * sixj_sign *
635 std::sqrt(std::fabs(((ka - 1) * (ka - 1) - kb * kb) /
636 (3.0 * ka * (1.0 + 2.0 * ka))));
637 return sign * f * sixj;
Angular provides functions and classes for calculating and storing angular factors (3,...
Definition CkTable.cpp:7
constexpr std::uint64_t kappa_to_kindex(int ka)
returns kappa_index, given kappa
Definition Wigner369j.hpp:98
constexpr bool zeroQ(double x, double eps=1.0e-10)
Checks if a double is within eps of 0.0 [eps=1.0e-10 by default].
Definition Wigner369j.hpp:67
constexpr std::uint64_t nk_to_index(int n, int k)
Returns nk_index, given {n, kappa}.
Definition Wigner369j.hpp:185
constexpr int kindex_to_kappa(std::uint64_t i)
Returns kappa, given kappa_index.
Definition Wigner369j.hpp:104
std::pair< int, int > index_to_nk(std::uint64_t nk_index)
Returns {n, kappa} given nk_index.
Definition Wigner369j.hpp:191
std::pair< int, int > kminmax_Ck(int ka, int kb)
Min and max non-zero multipole rank k for C^k, given kappa_a and kappa_b.
Definition Wigner369j.hpp:580
constexpr std::uint64_t l_to_max_kindex(int l)
Maximum kappa index for a given orbital angular momentum l.
Definition Wigner369j.hpp:128
double Ck_kk_mmq(int k, int ka, int kb, int twoma, int twomb, int twoq)
Full (non-reduced) C^k_q matrix element. Takes kappa and 2*m values.
Definition Wigner369j.hpp:519
double threej_2(int two_j1, int two_j2, int two_j3, int two_m1, int two_m2, int two_m3)
Wigner 3j symbol. Inputs are 2*j (or 2*l) as integers.
Definition Wigner369j.hpp:277
double cg_2(int two_j1, int two_m1, int two_j2, int two_m2, int two_J, int two_M)
Clebsch-Gordon coefficient <j1 m1, j2 m2 | J M>. Takes 2*j as integers.
Definition Wigner369j.hpp:331
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 nkindex_to_kappa(std::uint64_t nk_index)
Returns kappa, given nk_index.
Definition Wigner369j.hpp:209
constexpr int neg1pow(int a)
Evaluates (-1)^{a} (for integer a)
Definition Wigner369j.hpp:237
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:201
constexpr int kappa_twojl(int twoj, int l)
returns kappa, given 2j and l
Definition Wigner369j.hpp:56
int nkindex_to_twoj(std::uint64_t nk_index)
Returns 2*j, given nk_index.
Definition Wigner369j.hpp:217
double tildeCk_kk(int k, int ka, int kb)
Tilde variant of the C^k reduced ME: (-1)^{ja+1/2} * <ka||C^k||kb>
Definition Wigner369j.hpp:557
double S_kk(int ka, int kb)
Reduced spin-1/2 angular ME: <ka||S||kb>. Takes kappa values.
Definition Wigner369j.hpp:622
constexpr int sumsToZero(int m1, int m2, int m3)
Checks if three ints sum to zero, returns 1 if they do.
Definition Wigner369j.hpp:254
constexpr int l_k(int ka)
returns l given kappa
Definition Wigner369j.hpp:44
constexpr std::uint64_t states_below_n(int n)
Returns number of possible states below given n (i.e., n' < n)
Definition Wigner369j.hpp:145
constexpr int parity_l(int l)
returns parity [(-1)^l] given l
Definition Wigner369j.hpp:52
constexpr bool evenQ_2(int two_a)
Returns true if a (an int) is even, given 2*a (true if two_a/2 is even)
Definition Wigner369j.hpp:235
constexpr int kappa_twojpi(const int twoj, const int pi)
returns kappa, given 2*j and parity (+/-1),
Definition Wigner369j.hpp:60
double special_threej_2(int two_j1, int two_j2, int two_k)
Special 3j symbol: (j1 j2 k; -1/2 1/2 0). Inputs are 2*j as integers.
Definition Wigner369j.hpp:301
bool Ck_kk_SR(int k, int ka, int kb)
Selection rule check for C^k: returns true if <ka||C^k||kb> may be non-zero.
Definition Wigner369j.hpp:537
constexpr int l_tilde_k(int ka)
"Complimentary" l := (2j-l) = l+/-1, for j=l+/-1/2
Definition Wigner369j.hpp:54
constexpr int kindex_to_twoj(std::uint64_t i)
returns 2j, given kappa_index
Definition Wigner369j.hpp:110
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:239
constexpr int parity(int la, int lb, int k)
Parity rule. Returns 1 only if la+lb+k is even.
Definition Wigner369j.hpp:243
constexpr int parity_k(int ka)
returns parity [(-1)^l] given kappa
Definition Wigner369j.hpp:48
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
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:249
double ninej_2(int two_j1, int two_j2, int two_j3, int two_j4, int two_j5, int two_j6, int two_j7, int two_j8, int two_j9)
Wigner 9j symbol. Inputs are 2*j as integers.
Definition Wigner369j.hpp:459
int nkindex_to_l(std::uint64_t nk_index)
Returns l, given nk_index.
Definition Wigner369j.hpp:225
bool sixjTriads(std::optional< int > a, std::optional< int > b, std::optional< int > c, std::optional< int > d, std::optional< int > e, std::optional< int > f)
Checks 6j triangle conditions with optional arguments (wildcards). Inputs are 2*j.
Definition Wigner369j.hpp:395
constexpr int twoj_k(int ka)
returns 2j given kappa
Definition Wigner369j.hpp:46
constexpr bool evenQ(int a)
Returns true if a is even - for integer values.
Definition Wigner369j.hpp:233
double Ck_kk(int k, int ka, int kb)
Reduced relativistic angular ME: <ka||C^k||kb>. Takes kappa values.
Definition Wigner369j.hpp:486