ampsci
High-precision calculations for one- and two-valence atomic systems
EM_multipole_base.hpp
1#pragma once
2#include "DiracOperator/TensorOperator.hpp"
3#include <memory>
4
5namespace DiracOperator {
6
7/*!
8 @brief Intermediate abstract base class for all EM relativistic multipole
9 operators.
10
11 @details
12
13 These are the \f$ t^K_Q \tilde\gamma \f$, \f$ T^{(\sigma)}_{KQ} \tilde\gamma \f$
14 operators from the vector expansion:
15
16 \f[
17 \begin{align}
18 e^{i\vec{q}\cdot\vec{r}}
19 &= \sqrt{4\pi}\sum_{KQ}\sqrt{[K]} \,
20 i^K \, {Y^*_{KQ}}{(\hat q)} \, t^K_Q(q,r),\\
21 \vec{\alpha} \, e^{i\vec{q}\cdot\vec{r}}
22 & = \sqrt{4\pi} \sum_{KQ\sigma} \sqrt{[K]} \, i^{K-\sigma} \,
23 \vec{Y}_{KQ}^{(\sigma)*}(\hat{{q}}) \,
24 T^{(\sigma)}_{KQ},
25 \end{align}
26 \f]
27
28 with \f$ \tilde\gamma = 1,\f$ \f$ \gamma^5, \f$ \f$ \gamma^0, \f$ \f$ i\gamma^0\gamma^5 \f$
29 for vector (V), axial(pseudo)-vector (A), scalar (S), or pseudoscalar (P).
30
31 Stores the construction parameters needed to reconstruct the concrete
32 operator via the MultipoleOperator factory, enabling type-erased cloning
33 without the caller knowing the derived type.
34
35 Specifically, the stored parameters are: a pointer to the radial grid, the
36 current frequency @p omega (updated by each derived class's
37 updateFrequency()), the Lorentz type character @p m_type, the component
38 character @p m_comp, the low-q flag @p m_low_q, an optional Bessel table
39 pointer @p m_jl (shallow-owned; shared between original and clone), and a
40 form character @p m_form (used to distinguish the length-form electric
41 operator VEk_Len from the velocity-form VEk).
42
43 All concrete EM multipole operators VEk, VMk, VLk, Phik, Sk, AEk, ALk,
44 AMk, Phi5k, S5k, and their low-q counterparts derive from this class.
45
46 @note This class does not implement angularF() and so remains abstract.
47 Operators must be constructed via the concrete derived types or the
48 MultipoleOperator factory.
49*/
51protected:
52 /*!
53 @brief Initialise the EM_multipole base layer.
54 @details Called exclusively from derived-class constructors.
55
56 @param rank_k Tensor rank of the operator.
57 @param pi Parity.
58 @param constant Overall multiplicative constant.
59 @param vec Radial vector (usually gr.r(), sometimes empty).
60 @param RorI Real or imaginary matrix elements.
61 @param freq_dep True if the operator is frequency-dependent.
62 @param grid Pointer to the radial Grid (stored for clone()).
63 @param type Lorentz type: 'V', 'A', 'S', or 'P'.
64 @param comp Component: 'E', 'M', 'L', or 'T'.
65 @param low_q True for the low-momentum (long-wavelength) approximation.
66 @param jl Optional pointer to a precomputed Bessel table.
67 @param form 'V' (velocity/V-form) or 'L' (length-form, VEk_Len only).
68 */
69 EM_multipole(int rank_k, Parity pi, double constant,
70 const std::vector<double> &vec, Realness RorI, bool freq_dep,
71 const Grid *grid, char type, char comp, bool low_q,
72 const SphericalBessel::JL_table *jl = nullptr, char form = 'V')
73 : TensorOperator(rank_k, pi, constant, vec, 0, RorI, freq_dep),
74 m_grid(grid),
75 m_type(type),
76 m_comp(comp),
77 m_low_q(low_q),
78 m_form(form),
79 m_jl(jl) {}
80
81public:
82 //! Returns the precomputed Bessel table pointer (may be nullptr).
83 const SphericalBessel::JL_table *jl() const { return m_jl; }
84
85 //! Returns a human-readable label, e.g. "T^E_1", "T^M5_2", "t_1", "P_1".
86 std::string name() const override {
87 const bool axial = (m_type == 'A');
88 const std::string g5 = axial ? "5" : "";
89 std::string base;
90 if (m_type == 'V' || m_type == 'A') {
91 switch (m_comp) {
92 case 'E':
93 base = std::string("T^E") + g5;
94 break;
95 case 'M':
96 base = std::string("T^M") + g5;
97 break;
98 case 'L':
99 base = std::string("T^L") + g5;
100 break;
101 case 'T':
102 base = std::string("t") + g5;
103 break;
104 default:
105 base = "?";
106 break;
107 }
108 } else if (m_type == 'S') {
109 base = "S";
110 } else if (m_type == 'P') {
111 base = "P";
112 } else {
113 base = "?";
114 }
115 if (m_form == 'L')
116 base += "(Len)";
117 if (m_low_q)
118 base += "(lq)";
119 return base + "_" + std::to_string(m_rank);
120 }
121
122 /*!
123 @brief Angular factor linking the radial integral to the reduced matrix
124 element: \f$ \langle a \| h \| b \rangle = F(\kappa_a,\kappa_b) \cdot
125 \int \! dr \f$.
126 @details
127 Returns \f$ C^K(\kappa_a, \kappa_b) \f$ or
128 \f$ C^K(\kappa_a, -\kappa_b) \f$ depending on the Lorentz structure.
129 The flipped form applies to: vector-magnetic (VM), all axial components
130 except axial-magnetic (AE, AL, AT), and pseudoscalar (P).
131
132 @note \f$ C^K(\kappa_a,-\kappa_b) = C^K(-\kappa_a,\kappa_b) \f$.
133 @note VMk_lowq overrides this with an extra \f$(_a+_b)\f$ prefactor.
134 */
135 double angularF(const int ka, const int kb) const override {
136 const bool flip = (m_type == 'V' && m_comp == 'M') ||
137 (m_type == 'A' && m_comp != 'M') || (m_type == 'P');
138 return flip ? Angular::Ck_kk(m_rank, ka, -kb) :
139 Angular::Ck_kk(m_rank, ka, kb);
140 }
141
142 /*!
143 @brief Updates the tensor rank and adjusts parity accordingly.
144 @details
145 Parity follows the tensor rank: even K gives even parity for most
146 operators, but is flipped (even K odd parity) for vector-magnetic,
147 all axial components except axial-magnetic, and pseudoscalar operators.
148 The same flip rule as angularF() applies.
149
150 @note Must be followed by a call to updateFrequency() to recompute
151 the radial Bessel vectors for the new rank.
152 */
153 void updateRank(int new_K) override {
154 m_rank = new_K;
155 const bool flip = (m_type == 'V' && m_comp == 'M') ||
156 (m_type == 'A' && m_comp != 'M') || (m_type == 'P');
157 m_parity = (Angular::evenQ(new_K) != flip) ? Parity::even : Parity::odd;
158 }
159
160 /*!
161 @brief Creates a fully independent copy of this operator at its current
162 (rank, frequency) state via the MultipoleOperator factory.
163 @details
164 The Bessel table pointer @p m_jl is shallow-copied (the clone shares the
165 same external table), but all computed radial vectors are regenerated
166 independently on the first updateFrequency() call.
167
168 @return A std::unique_ptr<TensorOperator> to the cloned operator.
169 */
170 std::unique_ptr<TensorOperator> clone() const override;
171
172protected:
173 const Grid *m_grid{nullptr};
174 double m_omega{
175 0.0}; //!< Current frequency; cached by each derived updateFrequency().
176 char m_type{};
177 char m_comp{};
178 bool m_low_q{};
179 char m_form{};
180 const SphericalBessel::JL_table *m_jl{nullptr};
181
182public:
183 EM_multipole(const EM_multipole &) = default;
184 EM_multipole &operator=(const EM_multipole &) = default;
185 EM_multipole(EM_multipole &&) = default;
186 EM_multipole &operator=(EM_multipole &&) = default;
187};
188
189} // namespace DiracOperator
Intermediate abstract base class for all EM relativistic multipole operators.
Definition EM_multipole_base.hpp:50
const SphericalBessel::JL_table * jl() const
Returns the precomputed Bessel table pointer (may be nullptr).
Definition EM_multipole_base.hpp:83
void updateRank(int new_K) override
Updates the tensor rank and adjusts parity accordingly.
Definition EM_multipole_base.hpp:153
std::string name() const override
Returns a human-readable label, e.g. "T^E_1", "T^M5_2", "t_1", "P_1".
Definition EM_multipole_base.hpp:86
double angularF(const int ka, const int kb) const override
Angular factor linking the radial integral to the reduced matrix element: .
Definition EM_multipole_base.hpp:135
double m_omega
Current frequency; cached by each derived updateFrequency().
Definition EM_multipole_base.hpp:174
EM_multipole(int rank_k, Parity pi, double constant, const std::vector< double > &vec, Realness RorI, bool freq_dep, const Grid *grid, char type, char comp, bool low_q, const SphericalBessel::JL_table *jl=nullptr, char form='V')
Initialise the EM_multipole base layer.
Definition EM_multipole_base.hpp:69
std::unique_ptr< TensorOperator > clone() const override
Creates a fully independent copy of this operator at its current (rank, frequency) state via the Mult...
Definition EM_multipole.cpp:619
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:66
Holds grid, including type + Jacobian (dr/du)
Definition Grid.hpp:31
Spherical Bessel Lookup table; in the form j_L(qr) = J[L][q][r].
Definition SphericalBessel.hpp:120
constexpr bool evenQ(int a)
Returns true if a is even - for integer values.
Definition Wigner369j.hpp:220
double Ck_kk(int k, int ka, int kb)
Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].
Definition Wigner369j.hpp:372
Dirac Operators: General + derived.
Definition GenerateOperator.cpp:3
Parity
Parity of operator.
Definition TensorOperator.hpp:19
Realness
Realness of matrix element; impacts symmetry only.
Definition TensorOperator.hpp:22