High-precision calculations for one- and two-valence atomic systems
MatrixElements.hpp
1#pragma once
2#include "Coulomb/meTable.hpp"
3#include "DiracOperator/TensorOperator.hpp"
4#include <iostream>
5#include <string>
6#include <utility>
7#include <vector>
8class DiracSpinor;
9namespace ExternalField {
11}
12namespace MBPT {
13class StructureRad;
14}
15
16//! Physical amplitudes and observables (matrix elements, second-order
17//! amplitudes); testable functions, callable from any module.
18namespace Amplitudes {
19
20/*!
21 @brief Result of a single matrix element calculation: the lowest-order
22 value and each correction, separately.
23 @details
24 Holds \f$ \redmatel{a}{h}{b} \f$ and its corrections,
25 \f[
26 t^{\rm tot}_{ab} = t^{(0)}_{ab} + \delta V_{ab} + \delta t^{\rm SR}_{ab}
27 + \delta t^{\rm Norm}_{ab}.
28 \f]
29 Everything is stored unscaled; the
30 accessors apply the factor that converts the reduced matrix element to the
31 requested form (reduced, stretched, or hyperfine constant); see
32 DiracOperator::MatrixElementType.
33*/
34struct MEdata {
35 //! State labels (shortSymbol); a is the bra: <a||h||b>
36 std::string a{}, b{};
37 //! Transition frequency, e_a - e_b (0 for diagonal)
38 double omega{0.0};
39 //! Factor converting reduced ME to requested MatrixElementType (1 for Reduced)
40 double factor{1.0};
41 //! Lowest-order reduced matrix element <a||h||b>
42 double t0{0.0};
43 //! RPA correction <a||dV||b> (0 if no RPA)
44 double dv{0.0};
45 //! True if an RPA correction was calculated (distinguishes from dv = 0)
46 bool has_rpa{false};
47 //! Structure radiation: top + bottom + centre diagrams (0 if no SR)
48 double sr{0.0};
49 //! Normalisation of states factor, StructureRad::norm_factor (0 if no SR)
50 double norm_factor{0.0};
51 //! Normalisation of states: norm_factor * (t0 + dv) (0 if no SR)
52 double norm{0.0};
53
54 //! Lowest-order value: factor * t0
55 double value0() const { return factor * t0; }
56 //! Lowest-order + RPA: factor * (t0 + dv)
57 double value() const { return factor * (t0 + dv); }
58 //! Full corrected value: factor * (t0 + dv + sr + norm)
59 double total() const { return factor * (t0 + dv + sr + norm); }
60};
61
62/*!
63 @brief Which frequency the operator, or the RPA, is evaluated at.
64 @details
65 There is no obvious default: the right choice depends on the calculation,
66 so it must be given explicitly.
67
68 - `transition`: the driver sets the frequency itself, to each pair's own
69 transition frequency \f$ \omega_{ab} = \en_a - \en_b \f$; see
70 @ref solve_at_frequency. This is the physically correct frequency
71 for a transition.
72
73 - `fixed`: the driver does not touch the frequency. The operator is assumed
74 to already be at the intended frequency, and the RPA to already have been
75 solved there, by the caller (the structure radiation tables are then
76 built once, by the driver). Use
77 for a fixed external field, or to reproduce a fixed-frequency
78 calculation.
79*/
80enum class Frequency { transition, fixed };
81
82/*!
83 @brief Options for the matrix element drivers.
84 @details
85 The two frequency choices are independent and have no default: see
86 @ref Frequency. The operator frequency usually matters most; the RPA (and
87 structure radiation) frequency dependence is often very small, so `fixed`
88 is usually adequate there.
89*/
90struct MEoptions {
91 //! Frequency of the operator itself; see Frequency
93 //! Frequency the RPA (and the structure radiation tables) are solved at;
94 //! see Frequency. With transition and structure radiation, the SR tables
95 //! are re-built at each transition frequency, which is slow
97 //! Calculate diagonal matrix elements (only for even-parity operators)
98 bool diagonal{true};
99 //! Calculate off-diagonal matrix elements
100 bool off_diagonal{true};
101 //! Calculate both <a||h||b> and <b||h||a>
102 bool calculate_both{false};
103 //! Form of matrix element: Reduced, Stretched, or HFConstant
105 DiracOperator::MatrixElementType::Reduced};
106 //! Maximum RPA iterations (1 corresponds to first-order RPA)
108 //! Print RPA solve progress
109 bool print{true};
110
111 //! The frequency choices must be made explicitly; there is no default
112 MEoptions(Frequency t_operator_omega, Frequency t_rpa_omega)
113 : operator_omega(t_operator_omega), rpa_omega(t_rpa_omega) {}
114};
115
116/*!
117 @brief Sets the operator frequency, solves the RPA, and re-builds the
118 structure radiation tables, for a transition at frequency omega, as the
119 options ask. The one place the frequencies are handled.
120 @details
121 In this order:
122 - with operator_omega = transition: the operator is set to
123 \f$ +|\omega| \f$, since the RPA must be solved with the operator at
124 positive frequency;
125 - with rpa_omega = transition: the RPA is re-solved at @p omega (cleared
126 first if the previous solution is poorly converged, or if first-order
127 RPA was asked for, which must not iterate from a previous solution);
128 - with operator_omega = transition: the operator is then set to the
129 signed @p omega, its physical frequency for this transition;
130 - with structure radiation, and either of the above: the SR tables are
131 re-built, so that their internal lines carry the operator and the RPA
132 as just set.
133
134 With both frequencies fixed, nothing is touched: the caller has set the
135 operator, solved the RPA, and built the SR tables.
136
137 @param h The operator (frequency updated if frequency-dependent).
138 @param dV RPA; nullptr for none.
139 @param sr Structure radiation; nullptr for none.
140 @param omega The transition frequency, signed: e_a - e_b for <a||h||b>.
141 @param options See MEoptions (the two Frequency choices, rpa_iterations,
142 print).
143*/
146 MBPT::StructureRad *sr, double omega,
147 const MEoptions &options);
148
149/*!
150 @brief Single matrix element of h between states a and b, with its RPA and
151 structure radiation corrections.
152 @details
153 Pure evaluation: assumes @p h is at the signed transition frequency, and
154 @p dV and @p sr solved there (see @ref solve_at_frequency). The RPA
155 correction is the component at the transition frequency: the emission one
156 (\f$ \delta V^\dagger \f$) if @p omega is negative; see
157 CorePolarisation::dV. The structure radiation denominators are taken at
158 @p omega_sr: its frequency dependence is very weak, so when the RPA is at
159 a fixed frequency this is usually the frequency the RPA was solved at
160 (see @ref sr_frequency). The Brueckner orbital correction
161 (MBPT::StructureRad::BO) is not included here.
162
163 The MatrixElementType factor is calculated with @p h (it is purely
164 angular), and stored in the returned MEdata rather than applied.
165
166 @param a,b States: <a||h||b>.
167 @param h The tensor operator.
168 @param dV RPA correction, already solved; nullptr for none.
169 @param sr Structure radiation, tables already built; nullptr for none.
170 @param type Form of matrix element (Reduced, Stretched, HFConstant).
171 @param omega Transition frequency, e_a - e_b: selects the RPA component,
172 and is recorded in the output.
173 @param omega_sr Frequency for the structure radiation denominators.
174 @return MEdata holding t0, dv, sr, norm, factor, omega, labels.
175*/
176[[nodiscard]] MEdata
177matrix_element(const DiracSpinor &a, const DiracSpinor &b,
179 const ExternalField::CorePolarisation *dV = nullptr,
180 const MBPT::StructureRad *sr = nullptr,
182 DiracOperator::MatrixElementType::Reduced,
183 double omega = 0.0, double omega_sr = 0.0);
184
185/*!
186 @brief The frequency for the structure radiation denominators of a
187 transition at omega: the transition frequency if the RPA follows each
188 transition, otherwise the frequency the RPA was solved at (zero if there
189 is no RPA).
190 @details
191 The structure radiation follows the RPA: its frequency dependence is very
192 weak, so it is taken at the same frequency.
193*/
194double sr_frequency(const ExternalField::CorePolarisation *dV, double omega,
195 const MEoptions &options);
196
197/*!
198 @brief Frequency-derivative term of <a||h||b> for a frequency-dependent
199 operator: (dt/dw) dw2, the shift from the second-order energy shifts
200 dw2 moving the transition frequency.
201 @details
202 \f$ \delta t = ({\rm d}t/{\rm d}\omega)\,\delta\omega^{(2)} \f$.
203 Off-diagonal elements only; zero for a frequency-independent operator.
204 The derivative is taken numerically, which is why the operator is not
205 const. It is left as it was, at @p omega.
206
207 @param a,b States: <a||h||b>.
208 @param h The operator, at the signed transition frequency @p omega.
209 @param sr Structure radiation (holds Sigma for the energy shifts).
210 @param omega Transition frequency, e_a - e_b.
211*/
212[[nodiscard]] double frequency_derivative_term(const DiracSpinor &a,
213 const DiracSpinor &b,
215 const MBPT::StructureRad *sr,
216 double omega);
217
218/*!
219 @brief The pairs of orbitals (a, b) of <a||h||b> that the drivers
220 calculate, in order.
221 @details
222 Diagonal elements first (only for even-parity operators, and only for
223 states in both lists), then off-diagonal; pairs forbidden by the selection
224 rules are skipped. When @p a_orbs and @p b_orbs are the same list, each
225 pair is calculated once: for odd-parity operators only elements with the
226 even-parity state on the right, for even-parity operators only the upper
227 triangle (unless calculate_both). Two distinct lists have no such pairing,
228 so every pair is included.
229
230 @param a_orbs Bra states (a).
231 @param b_orbs Ket states (b).
232 @param h The tensor operator (selection rules).
233 @param options diagonal, off_diagonal, calculate_both.
234 @return Pointers into @p a_orbs and @p b_orbs: {a, b} for each element.
235*/
236[[nodiscard]] std::vector<std::pair<const DiracSpinor *, const DiracSpinor *>>
237orbital_pairs(const std::vector<DiracSpinor> &a_orbs,
238 const std::vector<DiracSpinor> &b_orbs,
239 const DiracOperator::TensorOperator *h, const MEoptions &options);
240
241/*!
242 @brief Matrix elements of h for all allowed pairs from two lists of
243 orbitals, with optional RPA and structure radiation; owns all frequency
244 updates and RPA solves.
245 @details
246 For each pair of @ref orbital_pairs: @ref solve_at_frequency, then
247 @ref matrix_element. Nothing is printed beyond the RPA progress (if
248 options.print, which also prints each transition as the RPA is
249 re-solved).
250
251 @param a_orbs Bra states (index a).
252 @param b_orbs Ket states (index b).
253 @param h The tensor operator.
254 @param dV RPA. nullptr for no RPA.
255 @param sr Structure radiation (mutated: its tables are built).
256 nullptr for none.
257 @param options See MEoptions.
258 @param outstream Stream for progress output.
259 @return Vector of MEdata, one per calculated matrix element.
260*/
261[[nodiscard]] std::vector<MEdata>
262matrix_elements(const std::vector<DiracSpinor> &a_orbs,
263 const std::vector<DiracSpinor> &b_orbs,
266 const MEoptions &options, std::ostream &outstream = std::cout);
267
268/*!
269 @brief Matrix elements of h for all pairs from a single list of orbitals.
270 @details
271 Convenience overload; calls matrix_elements(orbs, orbs, ...) with both
272 bra and ket taken from @p orbs, so each pair is calculated once.
273*/
274[[nodiscard]] inline std::vector<MEdata>
275matrix_elements(const std::vector<DiracSpinor> &orbs,
278 const MEoptions &options, std::ostream &outstream = std::cout) {
279 return matrix_elements(orbs, orbs, h, dV, sr, options, outstream);
280}
281
282//==============================================================================
283
284/*!
285 @brief Builds a lookup table of reduced matrix elements <a||h||b>.
286 @details
287 Fills and returns a `Coulomb::meTable<double>` with the bare reduced
288 matrix elements \f$ \redmatel{a}{h}{b} \f$ for all non-zero pairs from
289 @p a_orbs and @p b_orbs. The symmetry-conjugate \f$ \redmatel{b}{h}{a} \f$
290 is also stored, via `symm_sign()`. Filled with OpenMP parallelisation.
291 @p h must already be at the intended frequency. For a table with RPA (and
292 structure radiation), use the overload taking @p omega.
293
294 @param a_orbs Bra states.
295 @param b_orbs Ket states.
296 @param h Pointer to the (const) tensor operator.
297
298 @return meTable containing t_ab for all non-zero pairs (and conjugates).
299*/
300[[nodiscard]] Coulomb::meTable<double>
301me_table(const std::vector<DiracSpinor> &a_orbs,
302 const std::vector<DiracSpinor> &b_orbs,
304
305/*!
306 @brief Builds a matrix element table for a single set of orbitals.
307 @details
308 Convenience overload; calls me_table(a_orbs, a_orbs, ...) with both
309 bra and ket taken from @p a_orbs.
310*/
311[[nodiscard]] inline Coulomb::meTable<double>
312me_table(const std::vector<DiracSpinor> &a_orbs,
314 return me_table(a_orbs, a_orbs, h);
315}
316
317/*!
318 @brief Builds a table of reduced matrix elements, including structure
319 radiation and (optionally) the normalisation of states.
320 @details
321 As above, but each element also carries the second-order corrections,
322 \f[ t_{ab} = \redmatel{a}{h}{b} + \delta V_{ab} + \delta_{\rm SR}^{ab}, \f]
323 and every element is at the one frequency @p omega: the RPA correction is
324 \f$ \delta V(\omega) \f$ throughout (the emission component,
325 \f$ \delta V^\dagger \f$, for negative @p omega; see
326 CorePolarisation::dV), and the structure radiation is at @p omega,
327 absorbed by the ket. The reversed pair \f$ (b, a) \f$ is then
328 not the symmetry conjugate of \f$ (a, b) \f$, and is calculated as well
329 (except at \f$ \omega = 0 \f$, where it is).
330
331 @param a_orbs Bra states.
332 @param b_orbs Ket states.
333 @param h Pointer to the (const) tensor operator.
334 @param dV Optional RPA correction. If nullptr, not applied.
335 @param srn Structure radiation/normalisation. If nullptr, not applied
336 (and the table is as the plain overload above).
337 @param omega Frequency of the table: that of the operator component the
338 table stands for. Sets the sign of the RPA correction, and
339 the structure radiation denominators.
340 @param sr_n_max SR+N is applied only to pairs with both n <= @p sr_n_max.
341 SR+N is meaningful only between physical states, so this
342 limits it to the low-n part of a large basis, where the
343 states are not cavity states. Does not affect the internal
344 lines of the diagrams (see MBPT::StructureRad) [999].
345 @param sr_norm If false, only the structure radiation is added, not the
346 normalisation of states [true].
347
348 @return meTable containing t_ab for all non-zero pairs, both orderings.
349*/
350[[nodiscard]] Coulomb::meTable<double>
351me_table(const std::vector<DiracSpinor> &a_orbs,
352 const std::vector<DiracSpinor> &b_orbs,
355 const MBPT::StructureRad *srn, double omega, int sr_n_max = 999,
356 bool sr_norm = true);
357
358/*!
359 @brief Builds a SR+N matrix element table for a single set of orbitals.
360 @details
361 Convenience overload; calls me_table(a_orbs, a_orbs, ...) with both
362 bra and ket taken from @p a_orbs.
363*/
364[[nodiscard]] inline Coulomb::meTable<double>
365me_table(const std::vector<DiracSpinor> &a_orbs,
368 const MBPT::StructureRad *srn, double omega, int sr_n_max = 999,
369 bool sr_norm = true) {
370 return me_table(a_orbs, a_orbs, h, dV, srn, omega, sr_n_max, sr_norm);
371}
372
373//==============================================================================
374
375} // namespace Amplitudes
Look-up table for matrix elements. Note: does not assume any symmetry: (a,b) is stored independantly ...
Definition meTable.hpp:17
General tensor operator (virtual base class); all single-particle (one-body) tenosor operators derive...
Definition TensorOperator.hpp:198
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:55
Virtual base class for core-polarisation (RPA); computes dV corrections.
Definition CorePolarisation.hpp:147
Structure Radiation and Normalisation of states, using diagram method.
Definition StructureRad.hpp:66
Physical amplitudes and observables (matrix elements, second-order amplitudes); testable functions,...
Definition MatrixElements.cpp:15
MEdata matrix_element(const DiracSpinor &a, const DiracSpinor &b, const DiracOperator::TensorOperator *h, const ExternalField::CorePolarisation *dV, const MBPT::StructureRad *sr, DiracOperator::MatrixElementType type, double omega, double omega_sr)
Single matrix element of h between states a and b, with its RPA and structure radiation corrections.
Definition MatrixElements.cpp:55
std::vector< MEdata > matrix_elements(const std::vector< DiracSpinor > &a_orbs, const std::vector< DiracSpinor > &b_orbs, DiracOperator::TensorOperator *h, ExternalField::CorePolarisation *dV, MBPT::StructureRad *sr, const MEoptions &options, std::ostream &outstream)
Matrix elements of h for all allowed pairs from two lists of orbitals, with optional RPA and structur...
Definition MatrixElements.cpp:162
Frequency
Which frequency the operator, or the RPA, is evaluated at.
Definition MatrixElements.hpp:80
Coulomb::meTable< double > me_table(const std::vector< DiracSpinor > &a_orbs, const std::vector< DiracSpinor > &b_orbs, const DiracOperator::TensorOperator *h)
Builds a lookup table of reduced matrix elements <a||h||b>.
Definition MatrixElements.cpp:214
double frequency_derivative_term(const DiracSpinor &a, const DiracSpinor &b, DiracOperator::TensorOperator *h, const MBPT::StructureRad *sr, double omega)
Frequency-derivative term of <a||h||b> for a frequency-dependent operator: (dt/dw) dw2,...
Definition MatrixElements.cpp:89
void solve_at_frequency(DiracOperator::TensorOperator *h, ExternalField::CorePolarisation *dV, MBPT::StructureRad *sr, double omega, const MEoptions &options)
Sets the operator frequency, solves the RPA, and re-builds the structure radiation tables,...
Definition MatrixElements.cpp:18
double sr_frequency(const ExternalField::CorePolarisation *dV, double omega, const MEoptions &options)
The frequency for the structure radiation denominators of a transition at omega: the transition frequ...
Definition MatrixElements.cpp:82
std::vector< std::pair< const DiracSpinor *, const DiracSpinor * > > orbital_pairs(const std::vector< DiracSpinor > &a_orbs, const std::vector< DiracSpinor > &b_orbs, const DiracOperator::TensorOperator *h, const MEoptions &options)
The pairs of orbitals (a, b) of <a||h||b> that the drivers calculate, in order.
Definition MatrixElements.cpp:108
MatrixElementType
Type of matrix element returned.
Definition TensorOperator.hpp:82
Core-polarisation (RPA) corrections to matrix elements of an external field.
Definition MatrixElements.hpp:9
Many-body perturbation theory.
Definition MatrixElements.hpp:12
Result of a single matrix element calculation: the lowest-order value and each correction,...
Definition MatrixElements.hpp:34
double norm_factor
Normalisation of states factor, StructureRad::norm_factor (0 if no SR)
Definition MatrixElements.hpp:50
double sr
Structure radiation: top + bottom + centre diagrams (0 if no SR)
Definition MatrixElements.hpp:48
double norm
Normalisation of states: norm_factor * (t0 + dv) (0 if no SR)
Definition MatrixElements.hpp:52
double total() const
Full corrected value: factor * (t0 + dv + sr + norm)
Definition MatrixElements.hpp:59
double t0
Lowest-order reduced matrix element <a||h||b>
Definition MatrixElements.hpp:42
double value() const
Lowest-order + RPA: factor * (t0 + dv)
Definition MatrixElements.hpp:57
std::string a
State labels (shortSymbol); a is the bra: <a||h||b>
Definition MatrixElements.hpp:36
double value0() const
Lowest-order value: factor * t0.
Definition MatrixElements.hpp:55
double dv
RPA correction <a||dV||b> (0 if no RPA)
Definition MatrixElements.hpp:44
double factor
Factor converting reduced ME to requested MatrixElementType (1 for Reduced)
Definition MatrixElements.hpp:40
double omega
Transition frequency, e_a - e_b (0 for diagonal)
Definition MatrixElements.hpp:38
bool has_rpa
True if an RPA correction was calculated (distinguishes from dv = 0)
Definition MatrixElements.hpp:46
Options for the matrix element drivers.
Definition MatrixElements.hpp:90
bool diagonal
Calculate diagonal matrix elements (only for even-parity operators)
Definition MatrixElements.hpp:98
bool print
Print RPA solve progress.
Definition MatrixElements.hpp:109
int rpa_iterations
Maximum RPA iterations (1 corresponds to first-order RPA)
Definition MatrixElements.hpp:107
MEoptions(Frequency t_operator_omega, Frequency t_rpa_omega)
The frequency choices must be made explicitly; there is no default.
Definition MatrixElements.hpp:112
bool calculate_both
Calculate both <a||h||b> and <b||h||a>
Definition MatrixElements.hpp:102
bool off_diagonal
Calculate off-diagonal matrix elements.
Definition MatrixElements.hpp:100
Frequency operator_omega
Frequency of the operator itself; see Frequency.
Definition MatrixElements.hpp:92
DiracOperator::MatrixElementType type
Form of matrix element: Reduced, Stretched, or HFConstant.
Definition MatrixElements.hpp:104
Frequency rpa_omega
Frequency the RPA (and the structure radiation tables) are solved at; see Frequency....
Definition MatrixElements.hpp:96