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) {
28 updateFrequency(omega);
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 if (std::abs(omega) > 1.0e-10) {
46 m_constant = -3.0 / std::abs((m_alpha * m_alpha * omega));
47 SphericalBessel::fillBesselVec_kr(1, std::abs(omega) * m_alpha, m_r,
48 &m_vec);
49 } else {
50 // j1(kr) -> (r*k)/3, for k<<1
51 m_constant = -1.0 / (m_alpha);
52 m_vec = m_r;
53 }
54 }
55
56 static std::unique_ptr<TensorOperator> generate(const IO::InputBlock &input,
57 const Wavefunction &wf) {
58 input.check({{"", "No input options"}});
59 if (input.has_option("help"))
60 return nullptr;
61 return std::make_unique<M1>(wf.grid(), wf.alpha(), 0.0);
62 }
63
64private:
65 const std::vector<double> m_r; // store radial vector (copy)
66 const double m_alpha;
67};
68
69//==============================================================================
70//! Magnetic dipole operator, in non-relativistic form: M1 = L + 2S
71class M1nr final : public TensorOperator {
72public:
73 M1nr() : TensorOperator(1, Parity::even, 1.0) {}
74 std::string name() const override final { return "M1nr"; }
75 std::string units() const override final { return "|mu_B|"; }
76
77 double angularF(const int, const int) const override final {
78 // angular factor included in L and S
79 return 1.0;
80 }
81
82 DiracSpinor radial_rhs(const int kappa_a,
83 const DiracSpinor &Fb) const override final {
84 return m_l.reduced_rhs(kappa_a, Fb) + 2.0 * m_s.reduced_rhs(kappa_a, Fb);
85 }
86
87 double radialIntegral(const DiracSpinor &Fa,
88 const DiracSpinor &Fb) const override final {
89 // nb: faster not to do this, but nicer this way
90 return Fa * radial_rhs(Fa.kappa(), Fb);
91 }
92
93 static std::unique_ptr<TensorOperator> generate(const IO::InputBlock &input,
94 const Wavefunction &) {
95 input.check({{"", "No input options"}});
96 if (input.has_option("help"))
97 return nullptr;
98 return std::make_unique<M1nr>();
99 }
100
101private:
102 DiracOperator::s m_s{};
103 DiracOperator::l m_l{};
104};
105
106} // 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
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:71
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition M1.hpp:74
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:82
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:87
std::string units() const override final
Returns units of operator as a string (usually au, may be MHz, etc.)
Definition M1.hpp:75
double angularF(const int, const int) const override final
Angular factor A_ab linking the radial integral to the RME.
Definition M1.hpp:77
General tensor operator (virtual base class); all single-particle (one-body) tenosor operators derive...
Definition TensorOperator.hpp:198
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:27
s (spin) operator
Definition jls.hpp:57
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:374