ampsci
c++ program for high-precision atomic structure calculations of single-valence 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 
8 namespace DiracODE {
9 
11 template <std::size_t Nx = 15>
13 private:
14  int kappa;
15  double Zeff, en, alpha, eps_target;
16  double kappa2, alpha2, c, c2, lambda, sigma, Ren;
17  double m_mass;
18  std::array<double, Nx> bx; // bx must be first
19  std::array<double, Nx> ax; // ax depends on bx
20 
21 public:
22  AsymptoticSpinor(int in_kappa, double in_Zeff, double in_en,
23  double in_alpha = PhysConst::alpha,
24  double in_eps_target = 1.0e-14, double m = 1.0)
25  : kappa(in_kappa),
26  Zeff(in_Zeff),
27  en(in_en),
28  alpha(in_alpha),
29  eps_target(in_eps_target),
30  kappa2(double(kappa * kappa)),
31  alpha2(alpha * alpha),
32  c(1.0 / alpha),
33  c2(c * c),
34  lambda(std::sqrt(-en * (2.0 + en * alpha2 / m))),
35  sigma((m + en * alpha2) * (Zeff / lambda)),
36  Ren(en + m * c2),
37  m_mass(m),
38  bx(make_bx()),
39  ax(make_ax()) {
40  // assert(en < 0.0 && "Must have en<0 in AsymptoticSpinor");
41  }
42 
44 
58  std::pair<double, double> fg(double r) const {
59  // See Johnson (2007), Eqs. (2.170) -- (2.171)
60  // Notation difference:
61  // P(r) = f(r)
62  // Q(r) = -g(r)
63  // There appears to by typo in Eq. (2.171)
64 
65  const double A_large = std::sqrt(1.0 + 0.5 * en * alpha2 / m_mass);
66  const double A_small = std::sqrt(-0.5 * en) * alpha;
67 
68  const double rfac = 2.0 * std::pow(r, sigma) * std::exp(-lambda * r);
69  double fs = 1.0;
70  double gs = 0.0;
71  double rk = 1.0;
72  // Continue the expansion until reach eps, or Nx
73  for (std::size_t k = 0; k < Nx; k++) {
74  rk *= r;
75  fs += (ax[k] / rk);
76  gs += (bx[k] / rk);
77  const auto eps =
78  std::max(std::abs(ax[k] / fs), std::abs(bx[k] / gs)) / rk;
79  if (eps < eps_target) {
80  break;
81  }
82  }
83  return {rfac * (A_large * fs + A_small * gs),
84  rfac * (A_large * gs - A_small * fs)};
85  }
86 
87 private:
88  std::array<double, Nx> make_bx() const {
89  // See Johnson (2007), Eqs. (2.172) -- (2.173)
90  std::array<double, Nx> tbx;
91  const auto Zalpha2 = Zeff * Zeff * alpha2;
92  tbx[0] = (kappa + (Zeff / lambda)) * (0.5 * alpha);
93  for (std::size_t i = 1; i < Nx; i++) {
94  tbx[i] = (kappa2 - qip::pow<2>((double(i) - sigma)) - Zalpha2) *
95  tbx[i - 1] / (double(2 * i) * lambda);
96  }
97  return tbx;
98  }
99 
100  std::array<double, Nx> make_ax() const {
101  // See Johnson (2007), Eq. (2.174)
102  // bx must already be initialised
103  std::array<double, Nx> tax;
104  const auto RenAlpha2 = 1.0 + en * alpha2;
105  for (std::size_t i = 0; i < Nx; i++) {
106  tax[i] = (kappa + (double(i + 1) - sigma) * RenAlpha2 -
107  Zeff * lambda * alpha2) *
108  (bx[i] * c) / (double(i + 1) * lambda);
109  }
110  return tax;
111  }
112 };
113 
114 } // namespace DiracODE
Performs asymptotic expansion for f and g at large r, up to order Nx in (1/r)
Definition: AsymptoticSpinor.hpp:12
std::pair< double, double > fg(double r) const
Performs asymptotic expansion for f and g at large r, up to order Nx in (1/r)
Definition: AsymptoticSpinor.hpp:58
Functions and classes used to solve the Dirac equation.
Definition: AsymptoticSpinor.hpp:8
constexpr double alpha
fine-structure constant
Definition: PhysConst_constants.hpp:13
constexpr double c
speed of light in a.u. (=1/alpha)
Definition: PhysConst_constants.hpp:17