ampsci
c++ program for high-precision atomic structure calculations of single-valence systems
Loading...
Searching...
No Matches
Sigma2.ipp
1#pragma once
2#include "Angular/Angular.hpp"
3#include "Coulomb/Coulomb.hpp"
4#include "Wavefunction/DiracSpinor.hpp"
5
6namespace MBPT {
7
10template <class CoulombIntegral> // CoulombIntegral may be YkTable or QkTable
11double Sigma_vw(const DiracSpinor &v, const DiracSpinor &w,
12 const CoulombIntegral &qk, const std::vector<DiracSpinor> &core,
13 const std::vector<DiracSpinor> &excited, int max_l_internal,
14 std::optional<double> ev) {
15
16 static_assert(std::is_same_v<CoulombIntegral, Coulomb::QkTable> ||
17 std::is_same_v<CoulombIntegral, Coulomb::YkTable>);
18
19 // const auto e_v = ev ? *ev : v.en();
20
21 const auto e_v = ev ? *ev : 0.5 * (v.en() + w.en());
22 // Should be e_v, OR e_w, depending on time ordering. We use average to make
23 // diagrams symmetric.
24
25 // Calculates <Fv|Sigma|Fw> from scratch, at Fw energy [full grid + fg+gg]
26 if (v.kappa() != w.kappa())
27 return 0.0;
28
29 // Mainly for tests, but can include basis states only up to maximum l
30 if (max_l_internal < 0)
31 max_l_internal = 999;
32
33 double sum = 0.0;
34#pragma omp parallel for reduction(+ : sum) collapse(2)
35 for (auto ia = 0ul; ia < core.size(); ia++) {
36 for (auto in = 0ul; in < excited.size(); in++) {
37
38 const auto &a = core[ia];
39 const auto &n = excited[in];
40
41 if (a.l() > max_l_internal || n.l() > max_l_internal)
42 continue;
43
44 const auto de_an = a.en() - n.en();
45
46 // Diagrams (a) [direct] and (b) [exchange]
47 for (const auto &m : excited) {
48 if (m.l() > max_l_internal)
49 continue;
50
51 const auto inv_de = 1.0 / (e_v + de_an - m.en());
52
53 const auto [k0, k1] = Coulomb::k_minmax_Q(v, a, m, n);
54 for (int k = k0; k <= k1; k += 2) {
55 const auto Qk_vamn = qk.Q(k, v, a, m, n);
56 const auto Qk_wamn = (v == w) ? Qk_vamn : qk.Q(k, w, a, m, n);
57 const auto Pk_wamn = qk.P(k, w, a, m, n);
58 sum += Qk_vamn * (Qk_wamn + Pk_wamn) * inv_de / (2.0 * k + 1.0);
59 }
60 }
61
62 // Diagrams (c) [direct] and (d) [exchange]
63 for (const auto &b : core) {
64 if (b.l() > max_l_internal)
65 continue;
66
67 const auto inv_de = 1.0 / (e_v - de_an - b.en()); // v? w? ... careful!
68
69 const auto [k0, k1] = Coulomb::k_minmax_Q(v, n, b, a);
70 for (int k = k0; k <= k1; k += 2) {
71 const auto Qk_vnba = qk.Q(k, v, n, b, a);
72 const auto Qk_wnba = (v == w) ? Qk_vnba : qk.Q(k, w, n, b, a);
73 const auto Pk_wnba = qk.P(k, w, n, b, a);
74 sum += Qk_vnba * (Qk_wnba + Pk_wnba) * inv_de / (2.0 * k + 1.0);
75 }
76 }
77
78 } // n
79 } // a
80
81 return sum * (1.0 / v.twojp1());
82}
83
84} // namespace MBPT
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:41
int twojp1() const
2j+1
Definition DiracSpinor.hpp:91
int kappa() const
Dirac quantum number, kappa.
Definition DiracSpinor.hpp:84
double en() const
Single-particle energy, not including rest energy.
Definition DiracSpinor.hpp:113
std::pair< int, int > k_minmax_Q(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d)
Returns min and max k (multipolarity) allowed for Q^k_abcd. Parity rule is included,...
Definition CoulombIntegrals.cpp:556
Many-body perturbation theory.
Definition CI_Integrals.hpp:9
double Sigma_vw(const DiracSpinor &v, const DiracSpinor &w, const CoulombIntegral &qk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, int max_l_internal=99, std::optional< double > ev=std::nullopt)
Matrix element of 1-body Sigma (2nd-order correlation) operator; de_v = <v|Sigma|v>.
Definition Sigma2.ipp:11