ampsci
High-precision calculations for one- and two-valence atomic systems
StructureRad.hpp
1#pragma once
2#include "Coulomb/include.hpp"
3#include "Coulomb/meTable.hpp"
4#include "IO/FRW_fileReadWrite.hpp"
5#include "Wavefunction/DiracSpinor.hpp"
6#include <memory>
7#include <optional>
8#include <vector>
9class Wavefunction;
10class DiracSpinor;
11namespace DiracOperator {
12class TensorOperator;
13}
14namespace ExternalField {
15class CorePolarisation;
16}
17
18//! Many-body perturbation theory
19namespace MBPT {
20
21/*! @brief Calculates Structure Radiation + Normalisation of states, using diagram
22method.
23
24 @details
25 Two main functions: reducedME(), norm(), which retrun the reduced matrix elements
26 for structure radiation and normalisation, respectively.
27
28 @note
29 For Structure Radiation, must call StructureRad::solve_core() first.
30
31 Structure radiation is sum of srTB()+srC(); norm() gives normalisation of
32 states.
33
34 * Typically, one should use splines for the 'legs' (outer states) of diagrams.
35 However, code is written such that {w,v} (the valence states) always appear as
36 the _first_ state in the Q integrals; thus those states are always directly
37 integrated (other states may use the existing y^k integrals, which were
38 calculated using the spline states) * unless using QkTable (see below).
39
40 * For using spline states as legs: This means you must typically ensure basis
41 is large enough to make relevant valence states "physical"
42
43 * The user should check if the zeroth order <w|t|v> matches closely between
44 valence/spline states. If not, basis/cavity is too small and SR+N probably
45 meaningless
46
47 * Option to use QkTable to calculate SR+N. Otherwise, calculates Coulomb
48 integrals on-the-fly. If QkTable is used, leads to ~10x speed-up, but uses large
49 amount of memory. Also, using QkTable means spline states are used for "legs" of
50 diagrams.
51
52 * Norm() works differently; It directly taken in the operator to calculate norm.
53 This is because norm depends only on Coulomb operators .
54 In some sense, would make sense to keep norm in a seperate class.
55 However, they are typically calculated together, and use the same Coulomb integrals.
56
57 * Formulas are presented in (for example):
58 * W. R. Johnson, Z. W. Liu, and J. Sapirstein, [At. Data Nucl. Data Tables 64,
59 279 (1996)](https://www.sciencedirect.com/science/article/pii/S0092640X96900248).
60
61 * Specific form of formulas used here are presented in:
62 [Phys. Rev. A **107**, 052812 (2023)](https://arxiv.org/abs/2211.11134)
63
64*/
66
67public:
68 //! Construct a Structeure Radiation (MBPT) object
69 /*! @details
70 en_core defines the core boundary: states with e < en_core are treated as
71 core states, while states with e > en_core are treated as excited states.
72 Typically
73 en_core = max(e_core) - min(e_valence) = wf.FermiLevel().
74
75 nminmax is the pair {nmin, nmax}. Only core states with n >= nmin are used,
76 and only excited states with n <= nmax are included in the summations.
77
78 Qk_fname is the filename for the QkTable. If provided, the QkTable will be
79 read from / written to this file and then used to calculate SR. This leads
80 to ~10 speedup in the calculation at the cost of significantly higher
81 memory usage.
82
83 fk and etak are effective screening factors for screening and hole-particle.
84 These should only be used as a test.
85 */
86 StructureRad(const std::vector<DiracSpinor> &basis, double en_core,
87 std::pair<int, int> nminmax = {0, 999},
88 const std::string &Qk_fname = "", int k_cut = 99,
89 const std::vector<double> &fk = {},
90 const std::vector<double> &etak = {}, bool verbose = true);
91
92private:
93 // Switch to use Qk (rather than Yk) table
94 bool m_use_Qk;
95 // effective screening; sqrt - add to both sides!
96 std::vector<double> m_root_fk;
97 // effective hole-particle
98 std::vector<double> m_etak;
99 int m_k_cut;
100
101 Coulomb::YkTable mY{};
102 std::optional<Coulomb::QkTable> mQ{std::nullopt};
103 // Keeping a local copy is significantly faster
104 std::vector<DiracSpinor> mCore{}, mExcited{}, mBasis{};
105
106 // matrix element table; set by solve_core
108 // Rank of current operator; set by solve_core
109 int m_K{-1};
110
111public:
112 //! const reference to employed _subset_ of core orbitals
113 const std::vector<DiracSpinor> &core() const { return mCore; }
114 //! const reference to employed _subset_ of excited orbitals
115 const std::vector<DiracSpinor> &excited() const { return mExcited; }
116 //! const reference to employed _subset_ of core+excited orbitals
117 const std::vector<DiracSpinor> &basis() const { return mBasis; }
118 //! const reference to underlying matrix element table. May be empty
119 const Coulomb::meTable<double> &me_Table() const { return mTab; }
120
121 //! const reference to Yk table. NOTE: may not be initialised!
122 const Coulomb::YkTable &Yk() const { return mY; }
123 //! const reference to underlying Qk table. Optional; may not be set
124 const std::optional<Coulomb::QkTable> &Qk() const { return mQ; }
125
126 //! Prepares
127 /*! @details
128 - Pre-computes the full set of <i||T||j> matrix elements
129 - Does for all core-core, core-excited, excited-excited orbitals
130 - Optionally includes core polarisation; dV may be null
131 - h must not be null
132 - For frequency-dependent operators, this assumes operator has already been updated
133 - Assumes Core Polarisation has already been solves
134
135 @note
136 This must be called before structure radiation can be calculated
137 */
138 void solve_core(const DiracOperator::TensorOperator *const h,
139 const ExternalField::CorePolarisation *const dV = nullptr);
140
141 //! Reduced matrix element of structure radiation <w||h_sr||v>
142 double SR(const DiracSpinor &w, const DiracSpinor &v,
143 double omega = 0.0) const {
144 return srTB(w, v, omega) + srC(w, v);
145 }
146
147 //! Returns Normalisation of states, reduced ME: <w||h||v>_norm.
148 double norm(const DiracSpinor &w, const DiracSpinor &v,
149 const DiracOperator::TensorOperator *const h,
150 const ExternalField::CorePolarisation *const dV = nullptr) const;
151
152 //! Normalisation factor; defined: <w||h||v>_norm = <w||h||v>(f_v + f_w)
153 double f_norm(const DiracSpinor &v) const { return -0.5 * (n1(v) + n2(v)); }
154
155 //! Returns sum of SR+Norm diagrams, reduced ME: <w||T+B+C+N||v>.
156 //! @note Must call solve_core() first! h and dV used for norm() only
157 double srn(const DiracSpinor &w, const DiracSpinor &v,
158 const DiracOperator::TensorOperator *const h,
159 const ExternalField::CorePolarisation *const dV = nullptr,
160 double omega = 0.0) const {
161 const auto tb = srTB(w, v, omega);
162 const auto c = srC(w, v);
163 const auto n = norm(w, v, h, dV);
164 return tb + c + n;
165 }
166
167 //! Effective screening factor for Coulomb lines
168 double f_root_scr(int k) const {
169 const auto sk = std::size_t(k);
170 return sk < m_root_fk.size() ? m_root_fk[sk] : 1.0;
171 }
172
173 //! Effective hole-particle factor for polarisation loops
174 double eta_hp(int k) const {
175 const auto sk = std::size_t(k);
176 return sk < m_etak.size() ? m_etak[sk] : 1.0;
177 }
178
179 //! Returns Brueckner orbital contribution to the, reduced ME: <w||h||v>_norm.
180 //! Returns a pair: {N, N+dV}: second includes RPA (if dV given).
181 //! @details from 10.1006/adnd.1996.0024
182 double BO(const DiracSpinor &w, const DiracSpinor &v, double fw = 1.0,
183 double fv = 1.0) const;
184
185 //! Calculates <v|Sigma|w>
186 double Sigma_vw(const DiracSpinor &v, const DiracSpinor &w) const;
187
188 //! constructs an me table of {srn, srn+dv} for each pair or {a,b}
191 const std::vector<DiracSpinor> &as,
192 const std::vector<DiracSpinor> &tbs = {}, double omega = 0.0,
193 const ExternalField::CorePolarisation *const dV = nullptr) const;
194
195private:
196 //! Returns sum of Top+Bottom (SR) diagrams, reduced ME: <w||T+B||v>.
197 double srTB(const DiracSpinor &w, const DiracSpinor &v,
198 double omega = 0.0) const;
199
200 //! Returns Centre (SR) diagrams, reduced ME: <w||C||v>. No explicit omega dependence
201 double srC(const DiracSpinor &w, const DiracSpinor &v) const;
202
203 // "Top" diagrams
204 double t1234(int k, const DiracSpinor &w, const DiracSpinor &r,
205 const DiracSpinor &v, const DiracSpinor &c) const;
206 double t1(int k, const DiracSpinor &w, const DiracSpinor &r,
207 const DiracSpinor &v, const DiracSpinor &c) const;
208 double t2(int k, const DiracSpinor &w, const DiracSpinor &r,
209 const DiracSpinor &v, const DiracSpinor &c) const;
210 double t3(int k, const DiracSpinor &w, const DiracSpinor &r,
211 const DiracSpinor &v, const DiracSpinor &c) const;
212 double t4(int k, const DiracSpinor &w, const DiracSpinor &r,
213 const DiracSpinor &v, const DiracSpinor &c) const;
214
215 // "Bottom" diagrams
216 double b1234(int k, const DiracSpinor &w, const DiracSpinor &c,
217 const DiracSpinor &v, const DiracSpinor &r) const;
218
219 // "Centre" diagrams (most important)
220 double c1(int k, const DiracSpinor &w, const DiracSpinor &a,
221 const DiracSpinor &v, const DiracSpinor &c) const;
222 double c2(int k, const DiracSpinor &w, const DiracSpinor &a,
223 const DiracSpinor &v, const DiracSpinor &c) const;
224 double d1(int k, const DiracSpinor &w, const DiracSpinor &r,
225 const DiracSpinor &v, const DiracSpinor &m) const;
226 double d2(int k, const DiracSpinor &w, const DiracSpinor &r,
227 const DiracSpinor &v, const DiracSpinor &m) const;
228
229 // "Normalisation" terms (most important)
230 double n1(const DiracSpinor &v) const;
231 double n2(const DiracSpinor &v) const;
232 double dSigma_dE(const DiracSpinor &v, const DiracSpinor &i,
233 const DiracSpinor &j, const DiracSpinor &k) const;
234
235 double z_bo(const DiracSpinor &w, const DiracSpinor &v,
236 bool transpose = false) const;
237
238 //
239 double Q(int k, const DiracSpinor &a, const DiracSpinor &b,
240 const DiracSpinor &c, const DiracSpinor &d) const {
241 // inlcudes effective Coulomb screening
242 const auto fk = f_root_scr(k);
243 return m_use_Qk ? fk * mQ->Q(k, a, b, c, d) : fk * mY.Q(k, a, b, c, d);
244 }
245
246 double P(int k, const DiracSpinor &a, const DiracSpinor &b,
247 const DiracSpinor &c, const DiracSpinor &d) const {
248 // inlcudes effective Coulomb screening
249 return m_use_Qk ? mQ->P2(k, a, b, c, d, mY.SixJ(), m_root_fk) :
250 mY.P2(k, a, b, c, d, m_root_fk);
251 }
252
253 double W(int k, const DiracSpinor &a, const DiracSpinor &b,
254 const DiracSpinor &c, const DiracSpinor &d) const {
255 // inlcudes effective Coulomb screening
256 return Q(k, a, b, c, d) + P(k, a, b, c, d);
257 }
258};
259
260} // namespace MBPT
Calculates + stores Hartree Y functions + Angular (w/ look-up), taking advantage of symmetry.
Definition YkTable.hpp:26
double Q(const int k, const DiracSpinor &Fa, const DiracSpinor &Fb, const DiracSpinor &Fc, const DiracSpinor &Fd) const
Calculates Qk using the existing yk integrals. Note: Yk and Ck tables must include all required value...
Definition YkTable.cpp:127
const Angular::SixJTable & SixJ() const
Returns a (const ref) to SixJ table [see Angular::SixJTable].
Definition YkTable.hpp:58
Look-up table for matrix elements. Note: does not assume any symmetry: (a,b) is stored independantly ...
Definition meTable.hpp:17
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:65
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
Virtual Core Polarisation class, for <a||dV||b>. See TDHF, DiagramRPA, etc.
Definition CorePolarisation.hpp:35
Calculates Structure Radiation + Normalisation of states, using diagram method.
Definition StructureRad.hpp:65
const std::vector< DiracSpinor > & core() const
const reference to employed subset of core orbitals
Definition StructureRad.hpp:113
const std::vector< DiracSpinor > & excited() const
const reference to employed subset of excited orbitals
Definition StructureRad.hpp:115
Coulomb::meTable< double > srn_table(const DiracOperator::TensorOperator *const h, const std::vector< DiracSpinor > &as, const std::vector< DiracSpinor > &tbs={}, double omega=0.0, const ExternalField::CorePolarisation *const dV=nullptr) const
constructs an me table of {srn, srn+dv} for each pair or {a,b}
Definition StructureRad.cpp:211
double f_root_scr(int k) const
Effective screening factor for Coulomb lines.
Definition StructureRad.hpp:168
double f_norm(const DiracSpinor &v) const
Normalisation factor; defined: <w||h||v>_norm = <w||h||v>(f_v + f_w)
Definition StructureRad.hpp:153
double norm(const DiracSpinor &w, const DiracSpinor &v, const DiracOperator::TensorOperator *const h, const ExternalField::CorePolarisation *const dV=nullptr) const
Returns Normalisation of states, reduced ME: <w||h||v>_norm.
Definition StructureRad.cpp:195
double BO(const DiracSpinor &w, const DiracSpinor &v, double fw=1.0, double fv=1.0) const
Returns Brueckner orbital contribution to the, reduced ME: <w||h||v>_norm. Returns a pair: {N,...
Definition StructureRad.cpp:766
double eta_hp(int k) const
Effective hole-particle factor for polarisation loops.
Definition StructureRad.hpp:174
const std::optional< Coulomb::QkTable > & Qk() const
const reference to underlying Qk table. Optional; may not be set
Definition StructureRad.hpp:124
void solve_core(const DiracOperator::TensorOperator *const h, const ExternalField::CorePolarisation *const dV=nullptr)
Prepares.
Definition StructureRad.cpp:83
double SR(const DiracSpinor &w, const DiracSpinor &v, double omega=0.0) const
Reduced matrix element of structure radiation <w||h_sr||v>
Definition StructureRad.hpp:142
double Sigma_vw(const DiracSpinor &v, const DiracSpinor &w) const
Calculates <v|Sigma|w>
Definition StructureRad.cpp:777
const Coulomb::meTable< double > & me_Table() const
const reference to underlying matrix element table. May be empty
Definition StructureRad.hpp:119
double srn(const DiracSpinor &w, const DiracSpinor &v, const DiracOperator::TensorOperator *const h, const ExternalField::CorePolarisation *const dV=nullptr, double omega=0.0) const
Returns sum of SR+Norm diagrams, reduced ME: <w||T+B+C+N||v>.
Definition StructureRad.hpp:157
const Coulomb::YkTable & Yk() const
const reference to Yk table. NOTE: may not be initialised!
Definition StructureRad.hpp:122
const std::vector< DiracSpinor > & basis() const
const reference to employed subset of core+excited orbitals
Definition StructureRad.hpp:117
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition Wavefunction.hpp:37
Dirac Operators: General + derived.
Definition GenerateOperator.cpp:3
Calculates many-body corrections (RPA) to matrix elements of external field.
Definition calcMatrixElements.cpp:14
Many-body perturbation theory.
Definition CI_Integrals.hpp:9