ampsci
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, eps_target;
18 double kappa2, alpha2, c, c2, lambda, sigma, Ren;
19 double m_mass;
20 std::array<double, Nx> bx; // bx must be first
21 std::array<double, Nx> ax; // ax depends on bx
22
23public:
24 AsymptoticSpinor(int in_kappa, double in_Zeff, double in_en,
25 double in_alpha = PhysConst::alpha,
26 double in_eps_target = 1.0e-14, double m = 1.0)
27 : kappa(in_kappa),
28 Zeff(in_Zeff),
29 en(in_en),
30 alpha(in_alpha),
31 eps_target(in_eps_target),
32 kappa2(double(kappa * kappa)),
33 alpha2(alpha * alpha),
34 c(1.0 / alpha),
35 c2(c * c),
36 lambda(std::sqrt(-en * (2.0 + en * alpha2 / m))),
37 sigma((m + en * alpha2) * (Zeff / lambda)),
38 Ren(en + m * c2),
39 m_mass(m),
40 bx(make_bx()),
41 ax(make_ax()) {
42 // assert(en < 0.0 && "Must have en<0 in AsymptoticSpinor");
43 }
44
45 /*!
46 @brief Returns {f(r), g(r)} via asymptotic expansion at large r.
47 @details
48 Large-r expansion of upper/lower radial components of the Dirac solution,
49 see Johnson (2007), Eqs. (2.170) -- (2.171).
50
51 f(r) = r^s exp(-yr) * { A(1 + O(1/r) + ...) + B(O(1/r) + ...)},
52
53 g(r) = r^s exp(-yr) * { -B(1 + O(1/r) + ...) + A(O(1/r) + ...)},
54
55 where s~1, y~1, A~1, B<<1.
56
57 The 1/r expansion inside the braces is truncated at order Nx. The series is
58 terminated early if the relative change drops below eps_target (typically
59 around order ~5).
60 */
61 std::pair<double, double> fg(double r) const {
62 // See Johnson (2007), Eqs. (2.170) -- (2.171)
63 // Notation difference:
64 // P(r) = f(r)
65 // Q(r) = -g(r)
66 // There appears to by typo in Eq. (2.171)
67
68 const double A_large = std::sqrt(1.0 + 0.5 * en * alpha2 / m_mass);
69 const double A_small = std::sqrt(-0.5 * en / m_mass) * alpha;
70
71 const double rfac = 2.0 * std::pow(r, sigma) * std::exp(-lambda * r);
72 double fs = 1.0;
73 double gs = 0.0;
74 double rk = 1.0;
75 // Continue the expansion until reach eps, or Nx
76 for (std::size_t k = 0; k < Nx; k++) {
77 rk *= r;
78 fs += (ax[k] / rk);
79 gs += (bx[k] / rk);
80 const auto eps =
81 std::max(std::abs(ax[k] / fs), std::abs(bx[k] / gs)) / rk;
82 if (eps < eps_target) {
83 break;
84 }
85 }
86 // here: typo in Johnson, or not? Both work
87 return {rfac * (A_large * fs + A_small * gs),
88 rfac * (A_large * gs - A_small * fs)};
89 // -rfac * (A_large * fs - A_small * gs)};
90 }
91
92private:
93 std::array<double, Nx> make_bx() const {
94 // See Johnson (2007), Eqs. (2.172) -- (2.173)
95 std::array<double, Nx> tbx;
96 const auto Zalpha2 = Zeff * Zeff * alpha2;
97 tbx[0] = (kappa + (Zeff / lambda)) * (0.5 * alpha);
98 for (std::size_t i = 1; i < Nx; i++) {
99 tbx[i] = (kappa2 - qip::pow<2>((double(i) - sigma)) - Zalpha2) *
100 tbx[i - 1] / (double(2 * i) * lambda);
101 }
102 return tbx;
103 }
104
105 std::array<double, Nx> make_ax() const {
106 // See Johnson (2007), Eq. (2.174)
107 // bx must already be initialised
108 std::array<double, Nx> tax;
109 const auto RenAlpha2 = 1.0 + en * alpha2;
110 for (std::size_t i = 0; i < Nx; i++) {
111 tax[i] =
112 (kappa + (double(i + 1) - sigma) * RenAlpha2 - Zeff * lambda * alpha2) *
113 (bx[i] * c) / (double(i + 1) * lambda);
114 }
115 return tax;
116 }
117};
118
119} // 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:61
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