High-precision calculations for one- and two-valence atomic systems
AsymptoticSpinor.hpp
1#pragma once
2#include "Physics/PhysConst_constants.hpp"
3#include "qip/Maths.hpp"
4#include <array>
5#include <cassert>
6#include <cmath>
7
8namespace DiracODE {
9
10/*!
11 @brief Performs asymptotic expansion for f and g at large r, up to order Nx in (1/r).
12*/
13template <std::size_t Nx = 15>
15private:
16 int kappa;
17 double Zeff, en, alpha, m_mass, eps_target;
18 double kappa2, alpha2, c, lambda, sigma;
19 std::array<double, Nx> bx; // bx must be first
20 std::array<double, Nx> ax; // ax depends on bx
21
22public:
23 AsymptoticSpinor(int in_kappa, double in_Zeff, double in_en,
24 double in_alpha = PhysConst::alpha,
25 double in_eps_target = 1.0e-14, double m = 1.0)
26 : kappa(in_kappa),
27 Zeff(in_Zeff),
28 en(in_en),
29 alpha(in_alpha),
30 m_mass(m),
31 eps_target(in_eps_target),
32 kappa2(double(kappa * kappa)),
33 alpha2(alpha * alpha),
34 c(1.0 / alpha),
35 lambda(std::sqrt(-en * (2.0 * m_mass + en * alpha2))),
36 sigma((m + en * alpha2) * (Zeff / lambda)),
37 // Ren(en + m * c2),
38 bx(make_bx()),
39 ax(make_ax()) {
40 // assert(en < 0.0 && "Must have en<0 in AsymptoticSpinor");
41 }
42
43 /*!
44 @brief Returns {f(r), g(r)} via asymptotic expansion at large r.
45 @details
46 Large-r expansion of upper/lower radial components of the Dirac solution,
47 see Johnson (2007), Eqs. (2.170) -- (2.171).
48
49 f(r) = r^s exp(-yr) * { A(1 + O(1/r) + ...) + B(O(1/r) + ...)},
50
51 g(r) = r^s exp(-yr) * { -B(1 + O(1/r) + ...) + A(O(1/r) + ...)},
52
53 where s~1, y~1, A~1, B<<1.
54
55 The 1/r expansion inside the braces is truncated at order Nx. The series is
56 terminated early if the relative change drops below eps_target (typically
57 around order ~5).
58 */
59 std::pair<double, double> fg(double r) const {
60 // See Johnson (2007), Eqs. (2.170) -- (2.171)
61 // Notation difference:
62 // P(r) = f(r)
63 // Q(r) = -g(r)
64 // There appears to by typo in Eq. (2.171)
65
66 const double A_large = std::sqrt(1.0 + 0.5 * en * alpha2 / m_mass);
67 const double A_small = std::sqrt(-0.5 * en / m_mass) * alpha;
68
69 const double rfac = /*2.0 * */ std::pow(r, sigma) * std::exp(-lambda * r);
70 double fs = 1.0;
71 double gs = 0.0;
72 // Continue the expansion until reach eps, or Nx
73 for (std::size_t k = 0; k < Nx; k++) {
74 const auto rkp1 = qip::pow(r, int(k) + 1);
75 const auto df = ax[k] / rkp1;
76 const auto dg = bx[k] / rkp1;
77 fs += df;
78 gs += dg;
79 const auto eps = std::max(std::abs(df / fs), std::abs(dg / gs));
80 if (eps < eps_target) {
81 break;
82 }
83 }
84 // here: typo in Johnson, or not? Both work
85 return {rfac * (A_large * fs + A_small * gs),
86 rfac * (A_large * gs - A_small * fs)};
87 // -rfac * (A_large * fs - A_small * gs)};
88 }
89
90private:
91 std::array<double, Nx> make_bx() const {
92 // See Johnson (2007), Eqs. (2.172) -- (2.173)
93 std::array<double, Nx> tbx;
94 const auto Zalpha2 = Zeff * Zeff * alpha2;
95 tbx[0] = (kappa / m_mass + (Zeff / lambda)) * (0.5 * alpha);
96 for (std::size_t i = 1; i < Nx; i++) {
97 tbx[i] = (kappa2 - qip::pow<2>((double(i) - sigma)) - Zalpha2) *
98 tbx[i - 1] / (double(2 * i) * lambda);
99 }
100 return tbx;
101 }
102
103 std::array<double, Nx> make_ax() const {
104 // See Johnson (2007), Eq. (2.174)
105 // bx must already be initialised
106 std::array<double, Nx> tax;
107 const auto RenAlpha2 = m_mass + en * alpha2;
108 for (std::size_t i = 0; i < Nx; i++) {
109 tax[i] = (kappa * m_mass + (double(i + 1) - sigma) * RenAlpha2 -
110 Zeff * lambda * alpha2) *
111 (bx[i] * c) / (double(i + 1) * lambda);
112 }
113 return tax;
114 }
115};
116
117} // namespace DiracODE
Performs asymptotic expansion for f and g at large r, up to order Nx in (1/r).
Definition AsymptoticSpinor.hpp:14
std::pair< double, double > fg(double r) const
Returns {f(r), g(r)} via asymptotic expansion at large r.
Definition AsymptoticSpinor.hpp:59
Functions and classes used to solve the Dirac equation.
Definition AsymptoticSpinor.hpp:8
constexpr double alpha
Fine-structure constant: alpha = 1/137.035 999 177(21) [CODATA 2022].
Definition PhysConst_constants.hpp:24
constexpr double c
speed of light in a.u. (=1/alpha)
Definition PhysConst_constants.hpp:63
constexpr auto pow(T x)
x^n for compile-time integer n, x any arithmetic type.
Definition Maths.hpp:98