ampsci
High-precision calculations for one- and two-valence atomic systems
Ek.hpp
1#pragma once
2#include "DiracOperator/TensorOperator.hpp"
3#include "IO/InputBlock.hpp"
4#include "Wavefunction/Wavefunction.hpp"
5
6namespace DiracOperator {
7
8//==============================================================================
9//! E^k (electric multipole) operator
10/*! @details
11\f[ h = -|e|r^k = -e r^k \f]
12\f[<a||d||b> = R C^k_{ab}\f]
13\f[R = -e \int r^k (f_a f_b + g_a g_b) \, dr\f]
14*/
15class Ek : public TensorOperator {
16public:
17 Ek(const Grid &gr, const int k)
18 : TensorOperator(k, Angular::evenQ(k) ? Parity::even : Parity::odd, -1.0,
19 gr.rpow(k), 0),
20 m_k(k) {}
21 double angularF(const int ka, const int kb) const override final {
22 return Angular::Ck_kk(m_k, ka, kb);
23 }
24 std::string name() const override {
25 return std::string("E") + std::to_string(m_k);
26 }
27 std::string units() const override {
28 return m_k == 1 ? "|e|aB" : std::string("|e|aB^") + std::to_string(m_k);
29 }
30
31private:
32 int m_k;
33};
34
35//==============================================================================
36//! Electric dipole operator: -|e|r = -er
37/*! @details
38\f[<a||d||b> = R (-1)^{ja+1/2} \sqrt{[ja][jb]} \, tjs(ja,jb,1, -1/2,1/2,0)\f]
39\f[<a||d||b> = R <k_a||C^k||k_b>\f]
40\f[R = -e \int r(f_a f_b + g_a g_b) \, dr\f]
41*/
42class E1 final : public Ek {
43public:
44 E1(const Grid &gr) : Ek(gr, 1) {}
45};
46
47//==============================================================================
48class sigma_r final : public ScalarOperator {
49public:
50 sigma_r(const Grid &rgrid) : ScalarOperator(Parity::odd, -1.0, rgrid.r()) {}
51 std::string name() const override final { return "s.r"; }
52 std::string units() const override final { return "aB"; }
53};
54
55//==============================================================================
56//! @brief Electric dipole operator, v-form:
57//! \f$ \frac{ie}{\omega \alpha} \vec{\alpha}\f$
58/*! @details
59\f[ <a||d_v||b> = R \f]
60\f[ R = -\frac{2e}{\omega \alpha}
61\int( f_ag_b <ka||s||-kb> - g_af_b <-ka||s||kb>)\,dr \f]
62*/
63class E1v final : public TensorOperator
64// d_v = (ie/w alpha) v{alpha} [v{a} = g0v{g}]\f$
65// <a||dv||b> = -2e/(w alpha) Int[ fagb <ka||s||-kb> - gafb <-ka||s||kb>]
66{
67public:
68 E1v(const double alpha, const double omega = 0.0)
69 : TensorOperator(1, Parity::odd, -0.0, {}, 0, Realness::real, true),
70 m_alpha(alpha) {
71 updateFrequency(omega);
72 }
73 std::string name() const override final { return "E1v"; }
74 std::string units() const override final { return "|e|aB"; }
75
76 double angularF(const int ka, const int kb) const override final {
77 // return 1;
78 return Angular::Ck_kk(1, ka, kb);
79 }
80
81 double angularCff(int, int) const override final { return 0; }
82 double angularCgg(int, int) const override final { return 0; }
83 double angularCfg(int ka, int kb) const override final {
84 // return Angular::S_kk(ka, -kb);
85 return ka - kb - 1;
86 }
87 double angularCgf(int ka, int kb) const override final {
88 // return -Angular::S_kk(-ka, kb);
89 return ka - kb + 1;
90 }
91
92 void updateFrequency(const double omega) override final {
93 // m_constant = std::abs(omega) > 1.0e-10 ? -2.0 / (m_alpha * omega) : 1.0;
94 m_constant = std::abs(omega) > 1.0e-10 ? -1.0 / (m_alpha * omega) : -1.0;
95 }
96
97private:
98 double m_alpha; // (including var-alpha)
99};
100
101//==============================================================================
102//! @brief i\vec{\alpha} matrix element: propto Electric dipole operator.
103//! i factored so that ME is real
104class ialpha final : public TensorOperator {
105public:
106 ialpha() : TensorOperator(1, Parity::odd, 1.0, {}, 0, Realness::real, true) {}
107
108 std::string name() const override final { return "i*alpha"; }
109 std::string units() const override final { return "au"; }
110
111 double angularF(const int ka, const int kb) const override final {
112 return Angular::Ck_kk(1, ka, kb);
113 }
114
115 double angularCff(int, int) const override final { return 0; }
116 double angularCgg(int, int) const override final { return 0; }
117 double angularCfg(int ka, int kb) const override final { return ka - kb - 1; }
118 double angularCgf(int ka, int kb) const override final { return ka - kb + 1; }
119};
120
121//==============================================================================
122
123inline std::unique_ptr<DiracOperator::TensorOperator>
124generate_sigma_r(const IO::InputBlock &input, const Wavefunction &wf) {
125 using namespace DiracOperator;
126 input.check({{"no options", ""}});
127 if (input.has_option("help")) {
128 return nullptr;
129 }
130 return std::make_unique<sigma_r>(wf.grid());
131}
132
133inline std::unique_ptr<DiracOperator::TensorOperator>
134generate_E1(const IO::InputBlock &input, const Wavefunction &wf) {
135 using namespace DiracOperator;
136 input.check({{"no options", ""}});
137 if (input.has_option("help")) {
138 return nullptr;
139 }
140 return std::make_unique<E1>(wf.grid());
141}
142
143inline std::unique_ptr<DiracOperator::TensorOperator>
144generate_E1v(const IO::InputBlock &input, const Wavefunction &wf) {
145 using namespace DiracOperator;
146 input.check({{"no options", ""}});
147 if (input.has_option("help")) {
148 return nullptr;
149 }
150 return std::make_unique<E1v>(wf.alpha(), 0.0);
151}
152
153inline std::unique_ptr<DiracOperator::TensorOperator>
154generate_E2(const IO::InputBlock &input, const Wavefunction &wf) {
155 using namespace DiracOperator;
156 input.check({{"no options", ""}});
157 if (input.has_option("help")) {
158 return nullptr;
159 }
160 return std::make_unique<Ek>(wf.grid(), 2);
161}
162
163inline std::unique_ptr<DiracOperator::TensorOperator>
164generate_ialpha(const IO::InputBlock &input, const Wavefunction &) {
165 using namespace DiracOperator;
166 input.check({{"no options", ""}});
167 if (input.has_option("help")) {
168 return nullptr;
169 }
170 return std::make_unique<ialpha>();
171}
172
173//------------------------------------------------------------------------------
174inline std::unique_ptr<DiracOperator::TensorOperator>
175generate_Ek(const IO::InputBlock &input, const Wavefunction &wf) {
176 using namespace DiracOperator;
177 input.check({{"k", "Rank: k=1 for E1, =2 for E2 etc. [1]"}});
178 if (input.has_option("help")) {
179 return nullptr;
180 }
181 const auto k = input.get("k", 1);
182 return std::make_unique<Ek>(wf.grid(), k);
183}
184
185} // namespace DiracOperator
Electric dipole operator: -|e|r = -er.
Definition Ek.hpp:42
Electric dipole operator, v-form: .
Definition Ek.hpp:66
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 Ek.hpp:76
void updateFrequency(const double omega) override final
Update frequency for frequency-dependant operators.
Definition Ek.hpp:92
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition Ek.hpp:73
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition Ek.hpp:74
E^k (electric multipole) operator.
Definition Ek.hpp:15
std::string name() const override
Returns "name" of operator (e.g., 'E1')
Definition Ek.hpp:24
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 Ek.hpp:21
std::string units() const override
Returns units of operator (usually au, may be MHz, etc.)
Definition Ek.hpp:27
Speacial case for scalar operator.
Definition TensorOperator.hpp:233
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:110
Holds grid, including type + Jacobian (dr/du)
Definition Grid.hpp:31
std::vector< double > rpow(double k) const
Calculates+returns vector of 1/r.
Definition Grid.cpp:120
Holds list of Options, and a list of other InputBlocks. Can be initialised with a list of options,...
Definition InputBlock.hpp:142
bool check(std::initializer_list< std::string > blocks, const std::vector< std::pair< std::string, std::string > > &list, bool print=false) const
Check all the options and blocks in this; if any of them are not present in 'list',...
Definition InputBlock.hpp:595
bool has_option(std::string_view key) const
Check is option is present (even if not set) in current block.
Definition InputBlock.hpp:201
T get(std::string_view key, T default_value) const
If 'key' exists in the options, returns value. Else, returns default_value. Note: If two keys with sa...
Definition InputBlock.hpp:417
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:154
double Ck_kk(int k, int ka, int kb)
Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].
Definition Wigner369j.hpp:306
Dirac Operators: General + derived.
Definition GenerateOperator.cpp:3