ampsci
High-precision calculations for one- and two-valence atomic systems
M1.hpp
1#pragma once
2#include "DiracOperator/TensorOperator.hpp"
3#include "IO/InputBlock.hpp"
4#include "Wavefunction/Wavefunction.hpp"
5#include "jls.hpp"
6
7namespace DiracOperator {
8
9//! Magnetic dipole operator: <a||M1||b>
10/*! @details
11\f[ <a||M1||b> = R (k_a + k_b) <-k_a||C^1||k_b> \f]
12\f[R = \frac{-3}{\alpha^2\omega} \int (f_ag_b+g_af_b) j_1(kr) \, dr\f]
13\f$ k = \omega/c = \omega*\alpha \f$.
14Negative sign (and alpha) puts into units |mu_B|.
15For k<<1 (static case): j1(kr) -> (r*k)/3,
16\f[R = \frac{-1}{\alpha} \int (f_ag_b+g_af_b) r \, dr\f]
17
18Probably, alpha should always by actual alpha, just units, not relativistic?
19
20Be careful with this operator - compare with: U. I. Safronova, M. S. Safronova, and W. R. Johnson, Phys. Rev. A 95, 042507 (2017).
21*/
22class M1 final : public TensorOperator {
23public:
24 M1(const Grid &gr, const double alpha, const double omega = 0.0)
25 : TensorOperator(1, Parity::even, +0.0, {}, Realness::real, true),
26 m_r(gr.r()),
27 m_alpha(alpha) {
29 }
30 M1 &operator=(const M1 &) = delete;
31 M1(const M1 &) = default;
32 ~M1() = default;
33 std::string name() const override final { return std::string("M1"); }
34 std::string units() const override final { return std::string("|mu_B|"); }
35
36 double angularF(const int ka, const int kb) const override final {
37 return (ka + kb) * Angular::Ck_kk(1, -ka, kb);
38 }
39 double angularCff(int, int) const override final { return 0.0; }
40 double angularCgg(int, int) const override final { return 0.0; }
41 double angularCfg(int, int) const override final { return 1.0; }
42 double angularCgf(int, int) const override final { return 1.0; }
43
44 void updateFrequency(const double omega) override final {
45 m_omega = omega;
46 if (std::abs(omega) > 1.0e-10) {
47 m_constant = -3.0 / std::abs((m_alpha * m_alpha * omega));
48 SphericalBessel::fillBesselVec_kr(1, std::abs(omega) * m_alpha, m_r,
49 &m_vec);
50 } else {
51 // j1(kr) -> (r*k)/3, for k<<1
52 m_constant = -1.0 / (m_alpha);
53 m_vec = m_r;
54 }
55 }
56
57 std::unique_ptr<TensorOperator> clone() const override final {
58 return std::make_unique<M1>(*this);
59 }
60
61 static std::unique_ptr<TensorOperator> generate(const IO::InputBlock &input,
62 const Wavefunction &wf) {
63 input.check({{"", "No input options"}});
64 if (input.has_option("help"))
65 return nullptr;
66 return std::make_unique<M1>(wf.grid(), wf.alpha(), 0.0);
67 }
68
69private:
70 const std::vector<double> m_r; // store radial vector (copy)
71 const double m_alpha;
72};
73
74//==============================================================================
75//! Magnetic dipole operator, in non-relativistic form: M1 = L + 2S
76class M1nr final : public TensorOperator {
77public:
78 M1nr() : TensorOperator(1, Parity::even, 1.0) {}
79 std::string name() const override final { return "M1nr"; }
80 std::string units() const override final { return "|mu_B|"; }
81
82 double angularF(const int, const int) const override final {
83 // angular factor included in L and S
84 return 1.0;
85 }
86
87 DiracSpinor radial_rhs(const int kappa_a,
88 const DiracSpinor &Fb) const override final {
89 return m_l.reduced_rhs(kappa_a, Fb) + 2.0 * m_s.reduced_rhs(kappa_a, Fb);
90 }
91
92 double radialIntegral(const DiracSpinor &Fa,
93 const DiracSpinor &Fb) const override final {
94 // nb: faster not to do this, but nicer this way
95 return Fa * radial_rhs(Fa.kappa(), Fb);
96 }
97
98 std::unique_ptr<TensorOperator> clone() const override final {
99 return std::make_unique<M1nr>(*this);
100 }
101
102 static std::unique_ptr<TensorOperator> generate(const IO::InputBlock &input,
103 const Wavefunction &) {
104 input.check({{"", "No input options"}});
105 if (input.has_option("help"))
106 return nullptr;
107 return std::make_unique<M1nr>();
108 }
109
110private:
111 DiracOperator::s m_s{};
112 DiracOperator::l m_l{};
113};
114
115} // namespace DiracOperator
Magnetic dipole operator: <a||M1||b>
Definition M1.hpp:22
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition M1.hpp:33
double angularCff(int, int) const override final
Angular coefficient C_ff for the f_a*f_b term of the radial integral.
Definition M1.hpp:39
double angularF(const int ka, const int kb) const override final
Angular factor A_ab linking the radial integral to the RME.
Definition M1.hpp:36
double angularCgg(int, int) const override final
Angular coefficient C_gg for the g_a*g_b term of the radial integral.
Definition M1.hpp:40
double angularCgf(int, int) const override final
Angular coefficient C_gf for the g_a*f_b term of the radial integral.
Definition M1.hpp:42
std::string units() const override final
Returns units of operator as a string (usually au, may be MHz, etc.)
Definition M1.hpp:34
std::unique_ptr< TensorOperator > clone() const override final
Creates a polymorphic copy of the operator at its current state, or nullptr if cloning is not support...
Definition M1.hpp:57
double angularCfg(int, int) const override final
Angular coefficient C_fg for the f_a*g_b term of the radial integral.
Definition M1.hpp:41
void updateFrequency(const double omega) override final
Updates the operator for a new frequency omega.
Definition M1.hpp:44
Magnetic dipole operator, in non-relativistic form: M1 = L + 2S.
Definition M1.hpp:76
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition M1.hpp:79
std::unique_ptr< TensorOperator > clone() const override final
Creates a polymorphic copy of the operator at its current state, or nullptr if cloning is not support...
Definition M1.hpp:98
DiracSpinor radial_rhs(const int kappa_a, const DiracSpinor &Fb) const override final
Computes the right-hand spinor dF_b for the radial integral.
Definition M1.hpp:87
double radialIntegral(const DiracSpinor &Fa, const DiracSpinor &Fb) const override final
Radial integral R_ab, defined by RME = angularF(a,b) * radialIntegral(a,b).
Definition M1.hpp:92
std::string units() const override final
Returns units of operator as a string (usually au, may be MHz, etc.)
Definition M1.hpp:80
double angularF(const int, const int) const override final
Angular factor A_ab linking the radial integral to the RME.
Definition M1.hpp:82
General tensor operator (virtual base class); all single-particle (one-body) tenosor operators derive...
Definition TensorOperator.hpp:198
double omega() const
Returns the current frequency set by the last updateFrequency() call. Zero for frequency-independent ...
Definition TensorOperator.hpp:266
DiracSpinor reduced_rhs(const int ka, const DiracSpinor &Fb) const
Returns angularF(ka,kb) * radial_rhs(ka,Fb); spinor-valued RME action on Fb, used in perturbation the...
Definition TensorOperator.cpp:50
l (orbital angular momentum) operator
Definition jls.hpp:30
s (spin) operator
Definition jls.hpp:63
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
Non-uniform radial grid with Jacobian, suitable for atomic structure calculations.
Definition Grid.hpp:85
const std::vector< double > & r() const
Full grid vector r.
Definition Grid.hpp:131
Holds a named list of key=value options and nested InputBlocks.
Definition InputBlock.hpp:154
bool check(std::initializer_list< std::string > blocks, const std::vector< std::pair< std::string, std::string > > &list, bool print=false) const
Validates options and sub-blocks against an allowed list.
Definition InputBlock.hpp:649
bool has_option(std::string_view key) const
Returns true if key is present in this block's option list, even if unset.
Definition InputBlock.hpp:247
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
double Ck_kk(int k, int ka, int kb)
Reduced relativistic angular ME: <ka||C^k||kb>. Takes kappa values.
Definition Wigner369j.hpp:486
Dirac operators: TensorOperator base class and derived implementations for single-particle (one-body)...
Definition GenerateOperator.cpp:6
std::vector< double > fillBesselVec_kr(int l, double k, const std::vector< double > &rvec, bool cell_average)
As fillBesselVec, with the argument of j_L being k*r instead of x.
Definition SphericalBessel.cpp:386