ampsci
High-precision calculations for one- and two-valence atomic systems
CkTable.hpp
1#pragma once
2#include "Angular/Wigner369j.hpp"
3#include <algorithm>
4#include <iostream>
5#include <vector>
6
7namespace Angular {
8
9//==============================================================================
10// Helper index-conversion functions
11//! Converts jindex to 2j; jindex = 0,1,2,... maps to 2j = 1,3,5,...
12constexpr int jindex_to_twoj(int jindex) { return 2 * jindex + 1; }
13//! Converts 2j to jindex; 2j = 1,3,5,... maps to jindex = 0,1,2,...
14constexpr int twoj_to_jindex(int twoj) { return (twoj - 1) / 2; }
15//! Converts kappa to jindex; e.g. {-1, 1, -2, 2} -> {0, 0, 1, 1}
16constexpr int kappa_to_jindex(int ka) { return (ka > 0) ? ka - 1 : -ka - 1; }
17
18//==============================================================================
19/*!
20 @brief Lookup table for Ck_ab reduced matrix elements and the
21 special 3j symbol (j_a, j_b, k; -1/2, 1/2, 0).
22 @details
23 Pre-computes and caches the angular symbols needed for radial matrix-element
24 evaluation. Three quantities are stored for each triple \f$(k, \kappa_a,
25 \kappa_b)\f$:
26
27 - The reduced matrix element of the normalised spherical harmonic:
28 \f[
29 C^k_{ab} \equiv \redmatel{\kappa_a}{C^k}{\kappa_b}
30 = (-1)^{j_a+\frac{1}{2}}\sqrt{[j_a][j_b]}
31 \threej{j_a}{j_b}{k}{-\tfrac{1}{2}}{\tfrac{1}{2}}{0}
32 \,\pi(l_a+l_b+k),
33 \f]
34 where \f$[x]\equiv 2x+1\f$ and \f$\pi\f$ encodes the parity selection
35 rule. \f$C^k_{ab}\f$ is antisymmetric under interchange up to a phase.
36
37 - The symmetrised (tilde) variant:
38 \f[
39 \widetilde C^k_{ab} = (-1)^{j_a+\frac{1}{2}} C^k_{ab},
40 \f]
41 which is fully symmetric: \f$\widetilde C^k_{ab} = \widetilde C^k_{ba}\f$.
42
43 - The underlying special 3j symbol:
44 \f[
45 \threej{j_a}{j_b}{k}{-\tfrac{1}{2}}{\tfrac{1}{2}}{0}.
46 \f]
47
48 All table lookups take \f$k\f$ and the Dirac quantum numbers
49 \f$\kappa_a, \kappa_b\f$ as input.
50
51 @note
52 - Table is filled up to a maximum \f$2j\f$ at construction; call fill()
53 to extend it afterwards.
54 - All symbols with \f$2j \le \f$ max_tj() and \f$k \le \f$ max_k() are
55 guaranteed to be present; there are no gaps.
56 - Non-mutable accessors are thread-safe. The `_mutable` variants extend the
57 table on demand but are **not** thread-safe.
58
59 @warning Calling a non-mutable accessor with out-of-range indices is
60 undefined behaviour; check against max_tj() and max_k() first.
61*/
62class CkTable {
63
64public:
65 /*!
66 @brief Constructs the table, pre-filling all symbols up to @p in_max_twoj.
67 @details Calls fill() internally; passing zero (the default) creates an
68 empty table that can be extended later with fill() or the mutable
69 accessors.
70 @param in_max_twoj Maximum value of \f$2j\f$ to pre-compute.
71 */
72 CkTable(const int in_max_twoj = 0) { fill(in_max_twoj); }
73
74public:
75 /*!
76 @brief Extends the lookup table to cover all symbols up to @p in_max_twoj.
77 @details Called automatically on construction. Only needed explicitly when
78 the required \f$2j\f$ grows beyond the original maximum.
79 @param in_max_twoj New maximum value of \f$2j\f$; no-op if already met.
80 */
81 void fill(const int in_max_twoj);
82
83 //! Returns Ck_ab; extends table if needed. Not thread-safe.
84 double get_Ckab_mutable(int k, int ka, int kb);
85 //! Returns tilde-Ck_ab; extends table if needed. Not thread-safe.
86 double get_tildeCkab_mutable(int k, int ka, int kb);
87 //! Returns 3j(j_a,j_b,k; -1/2,1/2,0); extends table if needed. Not thread-safe.
88 double get_3jkab_mutable(int k, int ka, int kb);
89
90 //! Returns Ck_ab. Undefined behaviour if indices exceed max_tj() or max_k().
91 double get_Ckab(int k, int ka, int kb) const;
92 //! Returns tilde-Ck_ab. Undefined behaviour if indices exceed max_tj() or max_k().
93 double get_tildeCkab(int k, int ka, int kb) const;
94 //! Returns 3j(j_a,j_b,k; -1/2,1/2,0). Undefined behaviour if indices exceed max_tj() or max_k().
95 double get_3jkab(int k, int ka, int kb) const;
96
97 //! Equivalent to get_Ckab(@p k, @p ka, @p kb).
98 double operator()(int k, int ka, int kb) const { return get_Ckab(k, ka, kb); }
99
100 /*!
101 @brief Returns Lambda^k_ab := 3j(j_a,j_b,k; -1/2,1/2,0)^2 * parity(l_a+l_b+k).
102 @details
103 This is the angular factor that appears in the Coulomb interaction after
104 angular reduction, and equals \f$\left(C^k_{ab}\right)^2 / ([j_a][j_b])\f$
105 up to a phase.
106 */
107 double get_Lambdakab(int k, int ka, int kb) const;
108
109 //! Maximum value of 2j currently stored in the table.
110 int max_tj() const { return jindex_to_twoj(m_max_jindex_sofar); }
111 //! Maximum value of k currently stored in the table.
112 int max_k() const { return m_max_k_sofar; }
113
114private:
115 std::vector<std::vector<std::vector<double>>> m_3j_k_a_b = {};
116 std::vector<std::vector<double>> m_Rjab_a_b = {}; // Sqrt([ja][jb])
117 int m_max_jindex_sofar = -1;
118 int m_max_k_sofar = -1;
119};
120
121} // namespace Angular
Lookup table for Ck_ab reduced matrix elements and the special 3j symbol (j_a, j_b,...
Definition CkTable.hpp:62
double get_Ckab(int k, int ka, int kb) const
Returns Ck_ab. Undefined behaviour if indices exceed max_tj() or max_k().
Definition CkTable.cpp:96
double get_tildeCkab(int k, int ka, int kb) const
Returns tilde-Ck_ab. Undefined behaviour if indices exceed max_tj() or max_k().
Definition CkTable.cpp:67
int max_tj() const
Maximum value of 2j currently stored in the table.
Definition CkTable.hpp:110
int max_k() const
Maximum value of k currently stored in the table.
Definition CkTable.hpp:112
double get_tildeCkab_mutable(int k, int ka, int kb)
Returns tilde-Ck_ab; extends table if needed. Not thread-safe.
Definition CkTable.cpp:52
double get_Lambdakab(int k, int ka, int kb) const
Returns Lambda^k_ab := 3j(j_a,j_b,k; -1/2,1/2,0)^2 * parity(l_a+l_b+k).
Definition CkTable.cpp:119
double get_3jkab_mutable(int k, int ka, int kb)
Returns 3j(j_a,j_b,k; -1/2,1/2,0); extends table if needed. Not thread-safe.
Definition CkTable.cpp:102
double get_3jkab(int k, int ka, int kb) const
Returns 3j(j_a,j_b,k; -1/2,1/2,0). Undefined behaviour if indices exceed max_tj() or max_k().
Definition CkTable.cpp:111
double get_Ckab_mutable(int k, int ka, int kb)
Returns Ck_ab; extends table if needed. Not thread-safe.
Definition CkTable.cpp:91
void fill(const int in_max_twoj)
Extends the lookup table to cover all symbols up to in_max_twoj.
Definition CkTable.cpp:9
double operator()(int k, int ka, int kb) const
Equivalent to get_Ckab(k, ka, kb).
Definition CkTable.hpp:98
CkTable(const int in_max_twoj=0)
Constructs the table, pre-filling all symbols up to in_max_twoj.
Definition CkTable.hpp:72
Angular provides functions and classes for calculating and storing angular factors (3,...
Definition CkTable.cpp:7
constexpr int twoj_to_jindex(int twoj)
Converts 2j to jindex; 2j = 1,3,5,... maps to jindex = 0,1,2,...
Definition CkTable.hpp:14
constexpr int jindex_to_twoj(int jindex)
Converts jindex to 2j; jindex = 0,1,2,... maps to 2j = 1,3,5,...
Definition CkTable.hpp:12
constexpr int kappa_to_jindex(int ka)
Converts kappa to jindex; e.g. {-1, 1, -2, 2} -> {0, 0, 1, 1}.
Definition CkTable.hpp:16