ampsci
High-precision calculations for one- and two-valence atomic systems
Angular Namespace Reference

Angular provides functions and classes for calculating and storing angular factors (3,6,9-J symbols etc.) More...

Classes

class  CkTable
 Lookup table for C^k and 3j symbols (special m=1/2, q=0 case) More...
 
class  SixJTable
 Lookup table for Wigner 6J symbols. More...
 

Functions

constexpr int jindex_to_twoj (int jindex)
 Converts jindex to 2*j [helper function].
 
constexpr int twoj_to_jindex (int twoj)
 Converts 2*j to jindex {1/2, 3/2, 5/2} -> {0, 1, 2} [helper function].
 
constexpr int kappa_to_jindex (int ka)
 Converts kappa to jindex {-1, 1, -2} -> {0, 0, 1} [helper function].
 
template<class A >
int twojk (const A &a)
 
template<class A , class B , class C , class D , class E , class F >
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. e.g.: (F,F,k,F,F,k) -> {j,j,k,j,j,k}. Do NOT *2! Do NOT pass j or 2j directly!
 
constexpr int l_k (int ka)
 returns l given kappa
 
constexpr int twoj_k (int ka)
 returns 2j given kappa
 
constexpr int parity_k (int ka)
 returns parity [(-1)^l] given kappa
 
constexpr int parity_l (int l)
 returns parity [(-1)^l] given l
 
constexpr int l_tilde_k (int ka)
 "Complimentary" l := (2j-l) = l+/-1, for j=l+/-1/2
 
constexpr int kappa_twojl (int twoj, int l)
 returns kappa, given 2j and l
 
constexpr int kappa_twojpi (const int twoj, const int pi)
 returns kappa, given 2*j and parity (+/-1),
 
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].
 
constexpr std::uint64_t kappa_to_kindex (int ka)
 returns kappa_index, given kappa
 
constexpr int kindex_to_kappa (std::uint64_t i)
 Returns kappa, given kappa_index.
 
constexpr int kindex_to_twoj (std::uint64_t i)
 returns 2j, given kappa_index
 
constexpr int kindex_to_l (std::uint64_t i)
 returns l, given kappa_index
 
constexpr std::uint64_t states_below_n (int n)
 Returns number of possible states below given n (i.e., n' < n)
 
constexpr std::uint64_t nk_to_index (int n, int k)
 Returns nk_index, given {n, kappa}.
 
std::pair< int, int > index_to_nk (std::uint64_t nk_index)
 Returns {n, kappa} given nk_index.
 
std::pair< int, std::uint64_t > nkindex_to_n_kindex (std::uint64_t nk_index)
 Returns {n, kappa_index} given nk_index.
 
int nkindex_to_kappa (std::uint64_t nk_index)
 Returns kappa, given nk_index.
 
int nkindex_to_twoj (std::uint64_t nk_index)
 Returns 2*j, given nk_index.
 
int nkindex_to_l (std::uint64_t nk_index)
 Returns l, given nk_index.
 
constexpr bool evenQ (int a)
 Returns true if a is even - for integer values.
 
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)
 
constexpr int neg1pow (int a)
 Evaluates (-1)^{a} (for integer a)
 
constexpr int neg1pow_2 (int two_a)
 Evaluates (-1)^{two_a/2} (for integer a; two_a is even)
 
constexpr int parity (int la, int lb, int k)
 Parity rule. Returns 1 only if la+lb+k is even.
 
constexpr int triangle (int j1, int j2, int J)
 Returns 1 if triangle rule is satisfied. nb: works with j OR twoj!
 
constexpr int sumsToZero (int m1, int m2, int m3)
 Checks if three ints sum to zero, returns 1 if they do.
 
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.
 
double special_threej_2 (int two_j1, int two_j2, int two_k)
 Special (common) 3js case: (j1 j2 k, -0.5, 0.5, 0)
 
double cg_2 (int two_j1, int two_m1, int two_j2, int two_m2, int two_J, int two_M)
 Clebsh-Gordon coeficient <j1 m1, j2 m2 | J M> [takes 2*j, as int].
 
bool sixj_zeroQ (int a, int b, int c, int d, int e, int f)
 Checks triangle conditions for 6j symbols (for 2*j)
 
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 if a 6j symbol is valid - each input is optional.
 
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]
 
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)
 9j symbol {j1 j2 j3 \ j4 j5 j6 \ j7 j8 j9} [takes 2*j as int]
 
double Ck_kk (int k, int ka, int kb)
 Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].
 
double Ck_kk_mmq (int k, int ka, int kb, int twoma, int twomb, int twoq)
 Full C^k_q matrix element - rarely used.
 
bool Ck_kk_SR (int k, int ka, int kb)
 Ck selection rule only. Returns false if C^k=0, true if non-zero.
 
double tildeCk_kk (int k, int ka, int kb)
 tildeCk_kk = (-1)^{ja+1/2}*Ck_kk
 
std::pair< int, int > kminmax_Ck (int ka, int kb)
 Returns [k_min, k_kmax] for C^k (min/max non-zero k, given kappa_a, kappa_b) Accounts for parity.
 
double S_kk (int ka, int kb)
 Reduced spin angular ME: (for spin 1/2): <ka||S||kb>
 

Detailed Description

Angular provides functions and classes for calculating and storing angular factors (3,6,9-J symbols etc.)

Provides functions to:

The general equations are defined:

\begin{align} \frac{1}{r_{12}} &= \sum_{kq} \frac{r_<^k}{r_>^{k+1}}(-1)^q C^k_{-q}(\hat{n}_1)C^k_{q}(\hat{n}_2)\\ C^k_{q} &\equiv \sqrt{\frac{4\pi}{2k+1}} Y_{kq}(\hat{n}), \end{align}

and

\begin{align} C^k_{ab} &\equiv \langle{\kappa_a}||C^k||{\kappa_b}\rangle \equiv (-1)^{j_a+1/2} \widetilde C^k_{ab} ,\\ &= (-1)^{j_a+1/2}\sqrt{[j_a][j_b]} \begin{pmatrix} {j_a} & {j_b} & {k} \\ {-1/2} & {1/2} &{0} \end{pmatrix} \pi(l_a+l_b+k). \end{align}

Function Documentation

◆ jindex_to_twoj()

constexpr int Angular::jindex_to_twoj ( int  jindex)
constexpr

Converts jindex to 2*j [helper function].

◆ twoj_to_jindex()

constexpr int Angular::twoj_to_jindex ( int  twoj)
constexpr

Converts 2*j to jindex {1/2, 3/2, 5/2} -> {0, 1, 2} [helper function].

◆ kappa_to_jindex()

constexpr int Angular::kappa_to_jindex ( int  ka)
constexpr

Converts kappa to jindex {-1, 1, -2} -> {0, 0, 1} [helper function].

◆ SixJ()

template<class A , class B , class C , class D , class E , class F >
double Angular::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. e.g.: (F,F,k,F,F,k) -> {j,j,k,j,j,k}. Do NOT *2! Do NOT pass j or 2j directly!

◆ l_k()

constexpr int Angular::l_k ( int  ka)
constexpr

returns l given kappa

◆ twoj_k()

constexpr int Angular::twoj_k ( int  ka)
constexpr

returns 2j given kappa

◆ parity_k()

constexpr int Angular::parity_k ( int  ka)
constexpr

returns parity [(-1)^l] given kappa

◆ parity_l()

constexpr int Angular::parity_l ( int  l)
constexpr

returns parity [(-1)^l] given l

◆ l_tilde_k()

constexpr int Angular::l_tilde_k ( int  ka)
constexpr

"Complimentary" l := (2j-l) = l+/-1, for j=l+/-1/2

◆ kappa_twojl()

constexpr int Angular::kappa_twojl ( int  twoj,
int  l 
)
constexpr

returns kappa, given 2j and l

◆ kappa_twojpi()

constexpr int Angular::kappa_twojpi ( const int  twoj,
const int  pi 
)
constexpr

returns kappa, given 2*j and parity (+/-1),

◆ zeroQ()

constexpr bool Angular::zeroQ ( double  x,
double  eps = 1.0e-10 
)
inlineconstexpr

Checks if a double is within eps of 0.0 [eps=1.0e-10 by default].

◆ kappa_to_kindex()

constexpr std::uint64_t Angular::kappa_to_kindex ( int  ka)
constexpr

returns kappa_index, given kappa

Kappa Index: For easy array access, define 1-to-1 index for each kappa:

kappa -1 1 -2 2 -3 3 -4 4 ...
index 0 1 2 3 4 5 6 7 ...

\[ i_k(\kappa)= \begin{cases} -2\kappa-2, & \kappa<0, \\ 2\kappa-1, & \kappa>0 . \end{cases} \]

\[ \kappa(i_k)= \begin{cases} -\left(\frac{i_k}{2}+1\right), & i_k\ \text{even},\\ \frac{i_k+1}{2}, & i_k\ \text{odd}. \end{cases} \]

◆ kindex_to_kappa()

constexpr int Angular::kindex_to_kappa ( std::uint64_t  i)
constexpr

Returns kappa, given kappa_index.

see Angular::kappa_to_kindex()

◆ kindex_to_twoj()

constexpr int Angular::kindex_to_twoj ( std::uint64_t  i)
constexpr

returns 2j, given kappa_index

see Angular::kappa_to_kindex()

◆ kindex_to_l()

constexpr int Angular::kindex_to_l ( std::uint64_t  i)
constexpr

returns l, given kappa_index

see Angular::kappa_to_kindex()

◆ states_below_n()

constexpr std::uint64_t Angular::states_below_n ( int  n)
constexpr

Returns number of possible states below given n (i.e., n' < n)

This could be made more "compact" with a maximum l. In practice, we go to large n, but never very large l.

Warning
  • n must be >1 (no non-standard states)

Cannot overflow; converts to std::uint64_t.

◆ nk_to_index()

constexpr std::uint64_t Angular::nk_to_index ( int  n,
int  k 
)
constexpr

Returns nk_index, given {n, kappa}.

For convenient array access we define a one-to-one mapping between the pair \((n,\kappa)\) and a non-negative index:

\[ i_{nk}(n,\kappa) = (n-1)^2 + i_k(\kappa), \]

where \(i_k(\kappa)\) is the kappa index defined by Angular::kappa_to_kindex()

Equivalently,

\[ i_{nk}(n,\kappa) = n^2 - 2n + 1 + i_k(\kappa). \]

Since

\[ n^2 - 2n + 1 = (n-1)^2 = \texttt{states\_below\_n}(n), \]

this counts the number of states with principal quantum number \(n' < n\), plus the index within the \(n\) shell.

Note
This indexing is only valid for physical bound-state quantum numbers, n >= 1, and cannot in general be used for arbitrary basis states.
Warning
To safely convert the returned index (uint64_t) to int, one must have n <= 46340.
To safely convert the returned index to Coulomb::nkIndex (uint16_t), one must have n <= 256.

◆ index_to_nk()

std::pair< int, int > Angular::index_to_nk ( std::uint64_t  nk_index)
inline

Returns {n, kappa} given nk_index.

Inverse of Angular::nk_to_index().

◆ nkindex_to_n_kindex()

std::pair< int, std::uint64_t > Angular::nkindex_to_n_kindex ( std::uint64_t  nk_index)
inline

Returns {n, kappa_index} given nk_index.

Inverse of Angular::nk_to_index().

◆ nkindex_to_kappa()

int Angular::nkindex_to_kappa ( std::uint64_t  nk_index)
inline

Returns kappa, given nk_index.

See Angular::nk_to_index().

◆ nkindex_to_twoj()

int Angular::nkindex_to_twoj ( std::uint64_t  nk_index)
inline

Returns 2*j, given nk_index.

See Angular::nk_to_index().

◆ nkindex_to_l()

int Angular::nkindex_to_l ( std::uint64_t  nk_index)
inline

Returns l, given nk_index.

See Angular::nk_to_index().

◆ evenQ()

constexpr bool Angular::evenQ ( int  a)
constexpr

Returns true if a is even - for integer values.

◆ evenQ_2()

constexpr bool Angular::evenQ_2 ( int  two_a)
constexpr

Returns true if a (an int) is even, given 2*a (true if two_a/2 is even)

◆ neg1pow()

constexpr int Angular::neg1pow ( int  a)
constexpr

Evaluates (-1)^{a} (for integer a)

◆ neg1pow_2()

constexpr int Angular::neg1pow_2 ( int  two_a)
constexpr

Evaluates (-1)^{two_a/2} (for integer a; two_a is even)

◆ parity()

constexpr int Angular::parity ( int  la,
int  lb,
int  k 
)
constexpr

Parity rule. Returns 1 only if la+lb+k is even.

◆ triangle()

constexpr int Angular::triangle ( int  j1,
int  j2,
int  J 
)
constexpr

Returns 1 if triangle rule is satisfied. nb: works with j OR twoj!

◆ sumsToZero()

constexpr int Angular::sumsToZero ( int  m1,
int  m2,
int  m3 
)
constexpr

Checks if three ints sum to zero, returns 1 if they do.

◆ threej_2()

double Angular::threej_2 ( int  two_j1,
int  two_j2,
int  two_j3,
int  two_m1,
int  two_m2,
int  two_m3 
)
inline

Calculates wigner 3j symbol. Takes in 2*j (or 2*l) - intput is integer.

\[ \begin{pmatrix}j1&j2&j3\\m1&m2&m3\end{pmatrix} \]

◆ special_threej_2()

double Angular::special_threej_2 ( int  two_j1,
int  two_j2,
int  two_k 
)
inline

Special (common) 3js case: (j1 j2 k, -0.5, 0.5, 0)

\[ \begin{pmatrix}j1&j2&k\\-1/2&1/2&0\end{pmatrix} \]

◆ cg_2()

double Angular::cg_2 ( int  two_j1,
int  two_m1,
int  two_j2,
int  two_m2,
int  two_J,
int  two_M 
)
inline

Clebsh-Gordon coeficient <j1 m1, j2 m2 | J M> [takes 2*j, as int].

◆ sixj_zeroQ()

bool Angular::sixj_zeroQ ( int  a,
int  b,
int  c,
int  d,
int  e,
int  f 
)
inline

Checks triangle conditions for 6j symbols (for 2*j)

◆ sixjTriads()

bool Angular::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 
)
inline

Checks if a 6j symbol is valid - each input is optional.

i.e., sixjTriads(a,b,c,{},{},{}) will check if any 6J symbol of form {a b c \ * * *} is valid (* can be any value)

◆ sixj_2()

double Angular::sixj_2 ( int  two_j1,
int  two_j2,
int  two_j3,
int  two_j4,
int  two_j5,
int  two_j6 
)
inline

6j symbol {j1 j2 j3 \ j4 j5 j6} - [takes 2*j as int]

◆ ninej_2()

double Angular::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 
)
inline

9j symbol {j1 j2 j3 \ j4 j5 j6 \ j7 j8 j9} [takes 2*j as int]

◆ Ck_kk()

double Angular::Ck_kk ( int  k,
int  ka,
int  kb 
)
inline

Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].

◆ Ck_kk_mmq()

double Angular::Ck_kk_mmq ( int  k,
int  ka,
int  kb,
int  twoma,
int  twomb,
int  twoq 
)
inline

Full C^k_q matrix element - rarely used.

◆ Ck_kk_SR()

bool Angular::Ck_kk_SR ( int  k,
int  ka,
int  kb 
)
inline

Ck selection rule only. Returns false if C^k=0, true if non-zero.

◆ tildeCk_kk()

double Angular::tildeCk_kk ( int  k,
int  ka,
int  kb 
)
inline

tildeCk_kk = (-1)^{ja+1/2}*Ck_kk

◆ kminmax_Ck()

std::pair< int, int > Angular::kminmax_Ck ( int  ka,
int  kb 
)
inline

Returns [k_min, k_kmax] for C^k (min/max non-zero k, given kappa_a, kappa_b) Accounts for parity.

◆ S_kk()

double Angular::S_kk ( int  ka,
int  kb 
)
inline

Reduced spin angular ME: (for spin 1/2): <ka||S||kb>

Reduced spin angular ME: (for spin 1/2!) <ka||S||kb> = d(la,lb) * (-1)^{ja+la+3/2} * Sqrt([ja]jb) * sjs{ja, 1, jb, 1/2, la, 1/2} Special 6j case: sjs{ja, 1, jb, 1/2, la, 1/2} = 0.5 (-1)^{ka+kb} * Sqrt(abs[{(ka-1)^2 - kb^2}/{3ka(1+2ka)}]) triangle rule for j! At least ~least 20% faster