2#include "DiracOperator/TensorOperator.hpp"
3#include "IO/InputBlock.hpp"
4#include "Wavefunction/Wavefunction.hpp"
5#include "qip/Maths.hpp"
18 Ek_omega(
const Grid &gr,
int K,
double alpha,
double omega,
21 gr.
r(), 0, Realness::real,
true),
24 m_transition_form(transition_form) {
27 std::string
name() const override final {
28 return m_transition_form ? std::string(
"t^E_") + std::to_string(m_K) :
29 std::string(
"E(") + std::to_string(m_K) +
")";
31 std::string
units() const override final {
32 return m_transition_form ? std::string(
"") : std::string(
"aB^k");
35 double angularF(
const int ka,
const int kb)
const override final {
47 if (
isZero(kappa_a, Fb.kappa())) {
53 const auto c1 = double(kappa_a - Fb.kappa()) / (m_K + 1) + 1;
54 const auto c2 = c1 - 2;
55 for (
auto i = Fb.min_pt(); i < Fb.max_pt(); i++) {
56 dF.
f(i) = j1[i] * Fb.f(i) - j2[i] * c1 * Fb.g(i);
57 dF.
g(i) = j1[i] * Fb.g(i) - j2[i] * c2 * Fb.g(i);
66 if (
isZero(Fa.kappa(), Fb.kappa())) {
70 const auto cc = double(Fa.kappa() - Fb.kappa()) / (m_K + 1);
73 const auto pi = std::max(Fa.min_pt(), Fb.min_pt());
74 const auto pf = std::min(Fa.max_pt(), Fb.max_pt());
76 const auto &drdu = Fb.grid().drdu();
78 const auto ff = NumCalc::integrate(1.0, pi, pf, j1, Fa.f(), Fb.f(), drdu);
79 const auto gg = NumCalc::integrate(1.0, pi, pf, j1, Fa.g(), Fb.g(), drdu);
82 const auto fg_not_gf = &Fa != &Fb;
84 fg_not_gf ? NumCalc::integrate(1.0, pi, pf, j2, Fa.f(), Fb.g(), drdu) :
87 fg_not_gf ? NumCalc::integrate(1.0, pi, pf, j2, Fa.g(), Fb.f(), drdu) :
90 return (ff + gg - cc * (fg + gf) - (fg - gf)) * Fb.grid().du();
95 const auto q = std::abs(m_alpha * omega);
98 m_constant = m_transition_form ?
102 SphericalBessel::fillBesselVec_kr(m_K, q, m_vec, &j1);
103 SphericalBessel::fillBesselVec_kr(m_K + 1, q, m_vec, &j2);
109 bool m_transition_form =
true;
110 std::vector<double> j1{};
111 std::vector<double> j2{};
124 bool transition_form)
126 gr.
r(), 0, Realness::real,
true),
129 m_transition_form(transition_form) {
132 std::string
name() const override final {
133 return m_transition_form ? std::string(
"tv^E_") + std::to_string(m_K) :
134 std::string(
"Ev(") + std::to_string(m_K) +
")";
136 std::string
units() const override final {
137 return m_transition_form ? std::string(
"") : std::string(
"aB^k");
140 double angularF(
const int ka,
const int kb)
const override final {
149 dF.
min_pt() = Fb.min_pt();
150 dF.
max_pt() = Fb.max_pt();
152 if (
isZero(kappa_a, Fb.kappa())) {
158 const auto c1 = double(kappa_a - Fb.kappa()) / (m_K + 1);
159 const auto c2 = -double(m_K);
160 const auto c3 = c1 * (m_K + 1);
161 for (
auto i = Fb.min_pt(); i < Fb.max_pt(); i++) {
162 dF.
f(i) = ((c3 + c2) * j1_on_qr[i] - c1 * j2[i]) * Fb.g(i);
163 dF.
g(i) = ((c3 - c2) * j1_on_qr[i] - c1 * j2[i]) * Fb.f(i);
172 if (
isZero(Fa.kappa(), Fb.kappa())) {
176 const auto c1 = double(Fa.kappa() - Fb.kappa()) / (m_K + 1);
177 const auto c2 = -double(m_K);
178 const auto c3 = c1 * (m_K + 1);
180 const auto pi = std::max(Fa.min_pt(), Fb.min_pt());
181 const auto pf = std::min(Fa.max_pt(), Fb.max_pt());
183 const auto &drdu = Fb.grid().drdu();
185 const auto same = &Fa == &Fb;
188 NumCalc::integrate(1.0, pi, pf, j1_on_qr, Fa.f(), Fb.g(), drdu);
189 const auto fg2 = NumCalc::integrate(1.0, pi, pf, j2, Fa.f(), Fb.g(), drdu);
193 NumCalc::integrate(1.0, pi, pf, j1_on_qr, Fa.g(), Fb.f(), drdu);
195 same ? fg2 : NumCalc::integrate(1.0, pi, pf, j2, Fa.g(), Fb.f(), drdu);
197 return ((c3 + c2) * fg1 + (c3 - c2) * gf1 - c1 * (fg2 + gf2)) *
203 const auto q = std::abs(m_alpha * omega);
207 m_constant = m_transition_form ?
211 SphericalBessel::fillBesselVec_kr(m_K, q, m_vec, &j1_on_qr);
212 SphericalBessel::fillBesselVec_kr(m_K + 1, q, m_vec, &j2);
213 for (std::size_t i = 0; i < m_vec.size(); ++i) {
214 j1_on_qr[i] /= (q * m_vec[i]);
222 bool m_transition_form =
true;
223 std::vector<double> j1_on_qr{};
224 std::vector<double> j2{};
231 Mk_omega(
const Grid &gr,
int K,
double alpha,
double omega,
232 bool transition_form)
234 gr.
r(), 0, Realness::real,
true),
237 m_transition_form(transition_form) {
240 std::string
name() const override final {
241 return m_transition_form ? std::string(
"t^M_") + std::to_string(m_K) :
242 std::string(
"M(") + std::to_string(m_K) +
")";
244 std::string
units() const override final {
245 return m_transition_form ? std::string(
"") : std::string(
"mu_B*aB^k");
248 double angularF(
const int ka,
const int kb)
const override final {
249 return -m_constant * (ka + kb) *
Angular::Ck_kk(m_K, -ka, kb) / (m_K + 1);
257 dF.
min_pt() = Fb.min_pt();
258 dF.
max_pt() = Fb.max_pt();
260 if (
isZero(kappa_a, Fb.kappa()) || (kappa_a == -Fb.kappa())) {
266 for (
auto i = Fb.min_pt(); i < Fb.max_pt(); i++) {
267 dF.
f(i) = j1[i] * Fb.g(i);
268 dF.
g(i) = j1[i] * Fb.f(i);
277 if (
isZero(Fa.kappa(), Fb.kappa()) || (Fa.kappa() == -Fb.kappa())) {
281 const auto pi = std::max(Fa.min_pt(), Fb.min_pt());
282 const auto pf = std::min(Fa.max_pt(), Fb.max_pt());
284 const auto &drdu = Fb.grid().drdu();
286 const auto fg = NumCalc::integrate(1.0, pi, pf, j1, Fa.f(), Fb.g(), drdu);
287 const auto gf = NumCalc::integrate(1.0, pi, pf, j1, Fa.g(), Fb.f(), drdu);
289 return (fg + gf) * Fb.grid().du();
294 const auto q = std::abs(m_alpha * omega);
297 m_constant = m_transition_form ?
302 SphericalBessel::fillBesselVec_kr(m_K, q, m_vec, &j1);
308 bool m_transition_form =
true;
309 std::vector<double> j1{};
314inline std::unique_ptr<DiracOperator::TensorOperator>
317 input.
check({{
"k",
"Rank: k=1 for E1, =2 for E2 etc. [1]"},
318 {
"omega",
"Frequency: nb: q = alpha*omega [0]"},
320 "Use transition form (true), or moment form (fasle). nb: use "
321 "moment form to compare to E1/E2 etc, transition form for "
322 "alpha*e^{iqr} expansion [true]"}});
326 const auto k = input.
get(
"k", 1);
327 const auto omega = input.
get(
"omega", 0.0);
328 const auto transition_form = input.
get(
"transition_form",
true);
329 return std::make_unique<Ek_omega>(wf.
grid(), k, wf.
alpha(), omega,
333inline std::unique_ptr<DiracOperator::TensorOperator>
336 input.
check({{
"k",
"Rank: k=1 for E1, =2 for E2 etc. [1]"},
337 {
"omega",
"Frequency: nb: q = alpha*omega [0]"},
339 "Use transition form (true), or moment form (fasle). nb: use "
340 "moment form to compare to E1/E2 etc, transition form for "
341 "alpha*e^{iqr} expansion [true]"}});
345 const auto k = input.
get(
"k", 1);
346 const auto omega = input.
get(
"omega", 0.0);
347 const auto transition_form = input.
get(
"transition_form",
true);
348 return std::make_unique<Mk_omega>(wf.
grid(), k, wf.
alpha(), omega,
352inline std::unique_ptr<DiracOperator::TensorOperator>
355 input.
check({{
"k",
"Rank: k=1 for E1, =2 for E2 etc. [1]"},
356 {
"omega",
"Frequency: nb: q = alpha*omega [0.001]"},
358 "Use transition form (true), or moment form (fasle). nb: use "
359 "moment form to compare to E1/E2 etc, transition form for "
360 "alpha*e^{iqr} expansion [true]"}});
364 const auto k = input.
get(
"k", 1);
365 const auto omega = input.
get(
"omega", 0.001);
366 const auto transition_form = input.
get(
"transition_form",
true);
367 return std::make_unique<Ekv_omega>(wf.
grid(), k, wf.
alpha(), omega,
Electric multipole operator, L-form, including frequency-dependence.
Definition EM_multipole.hpp:16
DiracSpinor radial_rhs(const int kappa_a, const DiracSpinor &Fb) const override final
radial_int = Fa * radial_rhs(a, Fb) (a needed for angular factor)
Definition EM_multipole.hpp:40
void updateFrequency(const double omega) override final
nb: q = alpha*omega!
Definition EM_multipole.hpp:94
double radialIntegral(const DiracSpinor &Fa, const DiracSpinor &Fb) const override final
Defined via <a||h||b> = angularF(a,b) * radialIntegral(a,b) (Note: if radial_rhs is overridden,...
Definition EM_multipole.hpp:63
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition EM_multipole.hpp:27
double angularF(const int ka, const int kb) const override final
angularF: links radiation integral to RME. RME = <a||h||b> = angularF(a,b) * radial_int(a,...
Definition EM_multipole.hpp:35
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition EM_multipole.hpp:31
Electric multipole operator, V-form, including frequency-dependence.
Definition EM_multipole.hpp:121
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition EM_multipole.hpp:132
double angularF(const int ka, const int kb) const override final
angularF: links radiation integral to RME. RME = <a||h||b> = angularF(a,b) * radial_int(a,...
Definition EM_multipole.hpp:140
DiracSpinor radial_rhs(const int kappa_a, const DiracSpinor &Fb) const override final
radial_int = Fa * radial_rhs(a, Fb) (a needed for angular factor)
Definition EM_multipole.hpp:145
double radialIntegral(const DiracSpinor &Fa, const DiracSpinor &Fb) const override final
Defined via <a||h||b> = angularF(a,b) * radialIntegral(a,b) (Note: if radial_rhs is overridden,...
Definition EM_multipole.hpp:169
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition EM_multipole.hpp:136
void updateFrequency(const double omega) override final
nb: q = alpha*omega!
Definition EM_multipole.hpp:202
Magnetic multipole operator, including frequency-dependence.
Definition EM_multipole.hpp:229
DiracSpinor radial_rhs(const int kappa_a, const DiracSpinor &Fb) const override final
radial_int = Fa * radial_rhs(a, Fb) (a needed for angular factor)
Definition EM_multipole.hpp:253
double angularF(const int ka, const int kb) const override final
angularF: links radiation integral to RME. RME = <a||h||b> = angularF(a,b) * radial_int(a,...
Definition EM_multipole.hpp:248
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition EM_multipole.hpp:240
double radialIntegral(const DiracSpinor &Fa, const DiracSpinor &Fb) const override final
Defined via <a||h||b> = angularF(a,b) * radialIntegral(a,b) (Note: if radial_rhs is overridden,...
Definition EM_multipole.hpp:274
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition EM_multipole.hpp:244
void updateFrequency(const double omega) override final
nb: q = alpha*omega!
Definition EM_multipole.hpp:293
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:110
bool isZero(const int ka, int kb) const
If matrix element <a|h|b> is zero, returns true.
Definition TensorOperator.cpp:15
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:41
auto max_pt() const
Effective size(); index after last non-zero point (index for f[i])
Definition DiracSpinor.hpp:144
const std::vector< double > & f() const
Upper (large) radial component function, f.
Definition DiracSpinor.hpp:125
auto min_pt() const
First non-zero point (index for f[i])
Definition DiracSpinor.hpp:140
const std::vector< double > & g() const
Lower (small) radial component function, g.
Definition DiracSpinor.hpp:132
Holds grid, including type + Jacobian (dr/du)
Definition Grid.hpp:31
const std::vector< double > & r() const
Grid points, r.
Definition Grid.hpp:75
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition Wavefunction.hpp:37
const Grid & grid() const
Returns a const reference to the radial grid.
Definition Wavefunction.hpp:82
double alpha() const
Local value of fine-structure constant.
Definition Wavefunction.hpp:88
constexpr bool evenQ(int a)
Returns true if a is even - for integer values.
Definition Wigner369j.hpp:146
double Ck_kk(int k, int ka, int kb)
Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].
Definition Wigner369j.hpp:298
Dirac Operators: General + derived.
Definition GenerateOperator.cpp:3
constexpr T double_factorial(T x)
Double factorial x!! - nb: does not check for overflow. Max x is 20 for uint64_t.
Definition Maths.hpp:131
constexpr auto pow(T x)
x^n for integer n (n compile-time template parameter), x any arithmetic type (T). Returns double for ...
Definition Maths.hpp:88