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 <optional>
6#include <string>
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.
22 @details
23 Holds \f$ \redmatel{a}{h}{b} \f$: the lowest-order value, the RPA (core
24 polarisation) correction, the transition frequency, and the factor that
25 converts the reduced matrix element to the requested form (reduced,
26 stretched, or hyperfine constant); see DiracOperator::MatrixElementType.
27
28 Everything is stored unscaled; value() and value0() apply the factor.
29*/
30struct MEdata {
31 //! State labels (shortSymbol); a is the bra: <a||h||b>
32 std::string a{}, b{};
33 //! Transition frequency, e_a - e_b (0 for diagonal)
34 double omega{0.0};
35 //! Factor converting reduced ME to requested MatrixElementType (1 for Reduced)
36 double factor{1.0};
37 //! Lowest-order reduced matrix element <a||h||b>
38 double t0{0.0};
39 //! RPA correction <a||dV||b> (0 if no RPA)
40 double dv{0.0};
41 //! True if an RPA correction was calculated (distinguishes from dv = 0)
42 bool has_rpa{false};
43
44 //! Full value: factor * (t0 + dv)
45 double value() const { return factor * (t0 + dv); }
46 //! Lowest-order value: factor * t0
47 double value0() const { return factor * t0; }
48};
49
50/*!
51 @brief Which frequency the operator, or the RPA, is evaluated at.
52 @details
53 There is no obvious default: the right choice depends on the calculation,
54 so it must be given explicitly.
55
56 - `transition`: the driver sets the frequency itself, to each pair's own
57 transition frequency \f$ \omega_{ab} = \en_a - \en_b \f$. The operator is
58 updated (h at \f$ +|\omega_{ab}| \f$, h_minus at \f$ -|\omega_{ab}| \f$),
59 and the RPA is re-solved, at every element. This is the physically
60 correct frequency for a transition.
61
62 - `fixed`: the driver does not touch the frequency. The operator is assumed
63 to already be at the intended frequency, and the RPA to already have been
64 solved there, by the caller. Use for a fixed external field, or to
65 reproduce a fixed-frequency calculation.
66*/
67enum class Frequency { transition, fixed };
68
69/*!
70 @brief Options for the matrix_elements() list driver.
71 @details
72 The two frequency choices are independent and have no default: see
73 @ref Frequency. The operator frequency usually matters most; the RPA
74 frequency dependence is often very small, so `fixed` is usually adequate
75 there.
76*/
77struct MEoptions {
78 //! Frequency of the operator itself; see Frequency
80 //! Frequency the RPA is solved at; see Frequency
82 //! Calculate diagonal matrix elements (only for even-parity operators)
83 bool diagonal{true};
84 //! Calculate off-diagonal matrix elements
85 bool off_diagonal{true};
86 //! Calculate both <a||h||b> and <b||h||a>
87 bool calculate_both{false};
88 //! Form of matrix element: Reduced, Stretched, or HFConstant
90 DiracOperator::MatrixElementType::Reduced};
91 //! Maximum RPA iterations (1 corresponds to first-order RPA)
93 //! Print RPA solve progress
94 bool print{true};
95
96 //! The frequency choices must be made explicitly; there is no default
97 MEoptions(Frequency t_operator_omega, Frequency t_rpa_omega)
98 : operator_omega(t_operator_omega), rpa_omega(t_rpa_omega) {}
99};
100
101/*!
102 @brief Sets the \f$ t_\pm \f$ operator pair to the frequency w.
103 @details
104 Sets @p h to \f$ +|\omega| \f$ and, if given, @p h_minus to
105 \f$ -|\omega| \f$; does nothing for frequency-independent operators, for
106 which updateFrequency() must not be called.
107 Call this before @ref matrix_elements when using Frequency::fixed.
108
109 @note Only for the \f$ t_\pm \f$ pair. Where there is no \f$ t_- \f$
110 (e.g. @ref sr_matrix_elements), the operator takes the signed
111 frequency directly, not \f$ |\omega| \f$.
112*/
115 double omega);
116
117/*!
118 @brief Single matrix element of h between states a and b, with optional RPA.
119 @details
120 Pure evaluation: assumes @p h, @p h_minus, and @p dV are already at the
121 correct frequency. If @p omega is negative and @p h_minus is given,
122 @p h_minus is used for the matrix element (sign-sensitive
123 frequency-dependent operators, e.g. E1v: h holds \f$ t_+ \f$ at
124 \f$ +|\omega| \f$, h_minus holds \f$ t_- \f$ at \f$ -|\omega| \f$).
125
126 The MatrixElementType factor is calculated with @p h (it is purely
127 angular), and stored in the returned MEdata rather than applied.
128
129 @param a,b States: <a||h||b>.
130 @param h The tensor operator.
131 @param h_minus Operator at negative frequency; nullptr if not required.
132 @param dV RPA correction, already solved; nullptr for none.
133 @param type Form of matrix element (Reduced, Stretched, HFConstant).
134 @param omega Transition frequency (only selects h vs h_minus, and is
135 recorded in the output).
136 @return MEdata holding t0, dv, factor, omega, and labels.
137*/
138[[nodiscard]] MEdata
139matrix_element(const DiracSpinor &a, const DiracSpinor &b,
141 const DiracOperator::TensorOperator *h_minus = nullptr,
142 const ExternalField::CorePolarisation *dV = nullptr,
144 DiracOperator::MatrixElementType::Reduced,
145 double omega = 0.0);
146
147/*!
148 @brief Matrix elements of h for all allowed pairs from two lists of
149 orbitals, with optional RPA; owns all frequency updates and RPA solves.
150 @details
151 Calculates \f$ \redmatel{a}{h}{b} \f$ for each pair allowed by the
152 selection rules, with the bra states taken from @p a_orbs and the ket
153 states from @p b_orbs, diagonal first, then off-diagonal.
154
155 Selection rules: pairs with isZero() are skipped; diagonal elements only
156 for even-parity operators.
157
158 When @p a_orbs and @p b_orbs are the same list (as in the single-list
159 overload below), each pair is calculated once: for odd-parity operators,
160 only elements with the even-parity state on the right are included
161 (unless calculate_both); for even-parity operators, only the upper
162 triangle. Two distinct lists have no such pairing, so every pair is
163 calculated and calculate_both has no effect.
164
165 Frequency handling (see @ref Frequency): with `transition`, the operator
166 is updated at each pair's transition frequency, @p h at
167 \f$ +|\omega_{ab}| \f$ and @p h_minus at \f$ -|\omega_{ab}| \f$, and the
168 RPA is re-solved there (cleared first when poorly converged, or when
169 rpa_iterations is 1 so that first-order RPA is not iterated from a
170 previous solution). With `fixed`, neither is touched: the caller must set
171 the operator frequency (see @ref set_operator_frequency) and solve the
172 RPA before calling.
173
174 @param a_orbs Bra states (index a).
175 @param b_orbs Ket states (index b).
176 @param h The tensor operator.
177 @param h_minus Operator at negative frequency (e.g. a clone of @p h for
178 E1v); nullptr if not required.
179 @param dV RPA. nullptr for no RPA.
180 @param options See MEoptions.
181 @param outstream Stream for progress output.
182 @return Vector of MEdata, one per calculated matrix element.
183*/
184[[nodiscard]] std::vector<MEdata> matrix_elements(
185 const std::vector<DiracSpinor> &a_orbs,
186 const std::vector<DiracSpinor> &b_orbs, DiracOperator::TensorOperator *h,
188 const MEoptions &options, std::ostream &outstream = std::cout);
189
190/*!
191 @brief Matrix elements of h for all pairs from a single list of orbitals.
192 @details
193 Convenience overload; calls matrix_elements(orbs, orbs, ...) with both
194 bra and ket taken from @p orbs, so each pair is calculated once.
195*/
196[[nodiscard]] inline std::vector<MEdata> matrix_elements(
197 const std::vector<DiracSpinor> &orbs, DiracOperator::TensorOperator *h,
199 const MEoptions &options, std::ostream &outstream = std::cout) {
200 return matrix_elements(orbs, orbs, h, h_minus, dV, options, outstream);
201}
202
203//==============================================================================
204
205/*!
206 @brief Builds a lookup table of reduced matrix elements <a||h||b>.
207 @details
208 Fills and returns a `Coulomb::meTable<double>` with reduced matrix elements
209 \f[ t_{ab} = \redmatel{a}{h}{b} + \delta V_{ab} \f]
210 for all non-zero pairs from @p a_orbs and @p b_orbs.
211
212 The symmetry-conjugate \f$ \redmatel{b}{h}{a} \f$ is also stored, via
213 `symm_sign()`. Filled with OpenMP parallelisation.
214
215 This is a pure table builder: @p h must already be at the intended
216 frequency, and @p dV already solved there.
217
218 @param a_orbs Bra states.
219 @param b_orbs Ket states.
220 @param h Pointer to the (const) tensor operator.
221 @param dV Optional RPA correction. If nullptr, not applied.
222
223 @return meTable containing t_ab for all non-zero pairs (and conjugates).
224*/
225[[nodiscard]] Coulomb::meTable<double>
226me_table(const std::vector<DiracSpinor> &a_orbs,
227 const std::vector<DiracSpinor> &b_orbs,
229 const ExternalField::CorePolarisation *dV = nullptr);
230
231/*!
232 @brief Builds a matrix element table for a single set of orbitals.
233 @details
234 Convenience overload; calls me_table(a_orbs, a_orbs, ...) with both
235 bra and ket taken from @p a_orbs.
236*/
237[[nodiscard]] inline Coulomb::meTable<double>
238me_table(const std::vector<DiracSpinor> &a_orbs,
240 const ExternalField::CorePolarisation *dV = nullptr) {
241 return me_table(a_orbs, a_orbs, h, dV);
242}
243
244/*!
245 @brief Builds a table of reduced matrix elements, including structure
246 radiation and (optionally) the normalisation of states.
247 @details
248 As above, but each element also carries the second-order corrections,
249 \f[ t_{ab} = \redmatel{a}{h}{b} + \delta V_{ab} + \delta_{\rm SR}^{ab}. \f]
250
251 @param a_orbs Bra states.
252 @param b_orbs Ket states.
253 @param h Pointer to the (const) tensor operator.
254 @param dV Optional RPA correction. If nullptr, not applied.
255 @param srn Structure radiation/normalisation. If nullptr, not applied
256 (and the table is as the plain overload above).
257 @param omega Frequency for the structure radiation denominators. Their
258 frequency dependence is very weak, so in practice this is
259 usually taken as the frequency the RPA was solved at.
260 @param sr_n_max SR+N is applied only to pairs with both n <= @p sr_n_max.
261 SR+N is meaningful only between physical states, so this
262 limits it to the low-n part of a large basis, where the
263 states are not cavity states. Does not affect the internal
264 lines of the diagrams (see MBPT::StructureRad) [999].
265 @param sr_norm If false, only the structure radiation is added, not the
266 normalisation of states [true].
267
268 @return meTable containing t_ab for all non-zero pairs (and conjugates).
269*/
270[[nodiscard]] Coulomb::meTable<double>
271me_table(const std::vector<DiracSpinor> &a_orbs,
272 const std::vector<DiracSpinor> &b_orbs,
275 const MBPT::StructureRad *srn, double omega, int sr_n_max = 999,
276 bool sr_norm = true);
277
278/*!
279 @brief Builds a SR+N matrix element table for a single set of orbitals.
280 @details
281 Convenience overload; calls me_table(a_orbs, a_orbs, ...) with both
282 bra and ket taken from @p a_orbs.
283*/
284[[nodiscard]] inline Coulomb::meTable<double>
285me_table(const std::vector<DiracSpinor> &a_orbs,
288 const MBPT::StructureRad *srn, double omega, int sr_n_max = 999,
289 bool sr_norm = true) {
290 return me_table(a_orbs, a_orbs, h, dV, srn, omega, sr_n_max, sr_norm);
291}
292
293//==============================================================================
294
295/*!
296 @brief Result of a matrix element calculation with second-order MBPT
297 corrections: structure radiation, normalisation, Brueckner orbital.
298 @details
299 Everything is stored unscaled; the accessors apply the MatrixElementType
300 factor. The total corrected matrix element is
301 \f[
302 t^{\rm tot}_{ab} = t^{(0)}_{ab} + \delta V_{ab} + \delta t^{\rm SR}_{ab}
303 + \delta t^{\rm Norm}_{ab} + \delta t^{\rm BO}_{ab}.
304 \f]
305*/
306struct SRNdata {
307 //! State labels (shortSymbol); a is the bra: <a||h||b>
308 std::string a{}, b{};
309 //! Frequency the corrections were evaluated at
310 double omega{0.0};
311 //! Factor converting reduced ME to requested MatrixElementType
312 double factor{1.0};
313 //! Lowest-order reduced matrix element <a||h||b>
314 double t0{0.0};
315 //! RPA correction (0 if no RPA)
316 double dv{0.0};
317 //! Structure radiation (top + bottom + centre diagrams)
318 double sr{0.0};
319 //! Normalisation of states: (f_norm_a + f_norm_b) * (t0 + dv)
320 double norm{0.0};
321 //! Brueckner orbital correction (0 if legs are already Brueckner);
322 //! includes the frequency-derivative term for freq-dependent operators
323 double bo{0.0};
324 //! True if an RPA correction was calculated
325 bool has_rpa{false};
326
327 //! Lowest-order + RPA: factor * (t0 + dv)
328 double value0() const { return factor * (t0 + dv); }
329 //! Full corrected value: factor * (t0 + dv + sr + norm + bo)
330 double total() const { return factor * (t0 + dv + sr + norm + bo); }
331};
332
333/*!
334 @brief Options for sr_matrix_elements()
335 @details
336 As MEoptions; see @ref Frequency. The structure radiation follows the RPA
337 choice: its frequency dependence is very weak, so with `fixed` the SR
338 denominators are evaluated at the frequency the RPA was solved at
339 (zero if there is no RPA).
340*/
342 //! Frequency of the operator itself; see Frequency
344 //! Frequency the RPA, and hence the structure radiation, is evaluated at.
345 //! With transition, the SR matrix element tables are re-built at each
346 //! transition frequency, which is slow
348 //! Calculate diagonal matrix elements (only for even-parity operators)
349 bool diagonal{true};
350 //! Calculate off-diagonal matrix elements
351 bool off_diagonal{true};
352 //! Calculate both <a||h||b> and <b||h||a>
353 bool calculate_both{false};
354 //! Form of matrix element: Reduced, Stretched, or HFConstant
356 DiracOperator::MatrixElementType::Reduced};
357 //! Include the Brueckner orbital correction (set false when the external
358 //! legs are already Brueckner orbitals)
359 bool include_bo{true};
360 //! Print per-element progress (SR is slow)
361 bool print{true};
362
363 //! The frequency choices must be made explicitly; there is no default
364 SRNoptions(Frequency t_operator_omega, Frequency t_rpa_omega)
365 : operator_omega(t_operator_omega), rpa_omega(t_rpa_omega) {}
366};
367
368/*!
369 @brief Matrix elements with structure radiation, normalisation, and
370 Brueckner orbital corrections, for all pairs from a list of orbitals.
371 @details
372 For each pair allowed by the selection rules (as @ref matrix_elements),
373 evaluates the lowest-order matrix element, RPA, and the second-order MBPT
374 corrections via MBPT::StructureRad: SR (top+bottom+centre diagrams),
375 normalisation of states, and (optionally) the Brueckner orbital
376 correction.
377
378 Frequency handling (see @ref Frequency): with operator_omega = transition,
379 the operator is evaluated at each pair's transition frequency, where its
380 frequency dependence is important, and its BO term then includes the
381 frequency-derivative correction
382 \f$ ({\rm d}t/{\rm d}\omega)\,\delta\omega^{(2)} \f$ for off-diagonal
383 elements. With rpa_omega = transition, the RPA and the SR tables are
384 re-solved at each transition frequency; with fixed, the caller must have
385 solved the RPA already, and the SR denominators are taken at the frequency
386 it was solved at (zero if there is no RPA).
387
388 The caller constructs (and owns) the MBPT::StructureRad object, which
389 holds the basis, Qk integrals, and screening options; solve_core is called
390 here, and re-called whenever the frequency changes.
391
392 @param orbs Orbitals for the external legs; all pairs considered.
393 @param h The tensor operator.
394 @param sr StructureRad object (mutated: solve_core is called).
395 @param dV RPA. nullptr for no RPA.
396 @param options See SRNoptions.
397 @param outstream Stream for per-element progress output.
398 @return Vector of SRNdata, one per calculated matrix element.
399*/
400[[nodiscard]] std::vector<SRNdata> sr_matrix_elements(
401 const std::vector<DiracSpinor> &orbs, DiracOperator::TensorOperator *h,
403 const SRNoptions &options, std::ostream &outstream = std::cout);
404
405} // 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:44
Virtual base class for core-polarisation (RPA); computes dV corrections.
Definition CorePolarisation.hpp:145
Calculates Structure Radiation + Normalisation of states, using diagram method.
Definition StructureRad.hpp:65
Physical amplitudes and observables (matrix elements, second-order amplitudes); testable functions,...
Definition MatrixElements.cpp:15
std::vector< MEdata > matrix_elements(const std::vector< DiracSpinor > &a_orbs, const std::vector< DiracSpinor > &b_orbs, DiracOperator::TensorOperator *h, DiracOperator::TensorOperator *h_minus, ExternalField::CorePolarisation *dV, const MEoptions &options, std::ostream &outstream)
Matrix elements of h for all allowed pairs from two lists of orbitals, with optional RPA; owns all fr...
Definition MatrixElements.cpp:51
Frequency
Which frequency the operator, or the RPA, is evaluated at.
Definition MatrixElements.hpp:67
std::vector< SRNdata > sr_matrix_elements(const std::vector< DiracSpinor > &orbs, DiracOperator::TensorOperator *h, MBPT::StructureRad *sr, ExternalField::CorePolarisation *dV, const SRNoptions &options, std::ostream &outstream)
Matrix elements with structure radiation, normalisation, and Brueckner orbital corrections,...
Definition MatrixElements.cpp:222
Coulomb::meTable< double > me_table(const std::vector< DiracSpinor > &a_orbs, const std::vector< DiracSpinor > &b_orbs, const DiracOperator::TensorOperator *h, const ExternalField::CorePolarisation *dV)
Builds a lookup table of reduced matrix elements <a||h||b>.
Definition MatrixElements.cpp:159
void set_operator_frequency(DiracOperator::TensorOperator *h, DiracOperator::TensorOperator *h_minus, double omega)
Sets the operator pair to the frequency w.
Definition MatrixElements.cpp:39
MEdata matrix_element(const DiracSpinor &a, const DiracSpinor &b, const DiracOperator::TensorOperator *h, const DiracOperator::TensorOperator *h_minus, const ExternalField::CorePolarisation *dV, DiracOperator::MatrixElementType type, double omega)
Single matrix element of h between states a and b, with optional RPA.
Definition MatrixElements.cpp:18
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.
Definition MatrixElements.hpp:30
double t0
Lowest-order reduced matrix element <a||h||b>
Definition MatrixElements.hpp:38
double value() const
Full value: factor * (t0 + dv)
Definition MatrixElements.hpp:45
std::string a
State labels (shortSymbol); a is the bra: <a||h||b>
Definition MatrixElements.hpp:32
double value0() const
Lowest-order value: factor * t0.
Definition MatrixElements.hpp:47
double dv
RPA correction <a||dV||b> (0 if no RPA)
Definition MatrixElements.hpp:40
double factor
Factor converting reduced ME to requested MatrixElementType (1 for Reduced)
Definition MatrixElements.hpp:36
double omega
Transition frequency, e_a - e_b (0 for diagonal)
Definition MatrixElements.hpp:34
bool has_rpa
True if an RPA correction was calculated (distinguishes from dv = 0)
Definition MatrixElements.hpp:42
Options for the matrix_elements() list driver.
Definition MatrixElements.hpp:77
bool diagonal
Calculate diagonal matrix elements (only for even-parity operators)
Definition MatrixElements.hpp:83
bool print
Print RPA solve progress.
Definition MatrixElements.hpp:94
int rpa_iterations
Maximum RPA iterations (1 corresponds to first-order RPA)
Definition MatrixElements.hpp:92
MEoptions(Frequency t_operator_omega, Frequency t_rpa_omega)
The frequency choices must be made explicitly; there is no default.
Definition MatrixElements.hpp:97
bool calculate_both
Calculate both <a||h||b> and <b||h||a>
Definition MatrixElements.hpp:87
bool off_diagonal
Calculate off-diagonal matrix elements.
Definition MatrixElements.hpp:85
Frequency operator_omega
Frequency of the operator itself; see Frequency.
Definition MatrixElements.hpp:79
DiracOperator::MatrixElementType type
Form of matrix element: Reduced, Stretched, or HFConstant.
Definition MatrixElements.hpp:89
Frequency rpa_omega
Frequency the RPA is solved at; see Frequency.
Definition MatrixElements.hpp:81
Result of a matrix element calculation with second-order MBPT corrections: structure radiation,...
Definition MatrixElements.hpp:306
double value0() const
Lowest-order + RPA: factor * (t0 + dv)
Definition MatrixElements.hpp:328
double t0
Lowest-order reduced matrix element <a||h||b>
Definition MatrixElements.hpp:314
double norm
Normalisation of states: (f_norm_a + f_norm_b) * (t0 + dv)
Definition MatrixElements.hpp:320
std::string a
State labels (shortSymbol); a is the bra: <a||h||b>
Definition MatrixElements.hpp:308
double sr
Structure radiation (top + bottom + centre diagrams)
Definition MatrixElements.hpp:318
double bo
Brueckner orbital correction (0 if legs are already Brueckner); includes the frequency-derivative ter...
Definition MatrixElements.hpp:323
double factor
Factor converting reduced ME to requested MatrixElementType.
Definition MatrixElements.hpp:312
double total() const
Full corrected value: factor * (t0 + dv + sr + norm + bo)
Definition MatrixElements.hpp:330
double dv
RPA correction (0 if no RPA)
Definition MatrixElements.hpp:316
bool has_rpa
True if an RPA correction was calculated.
Definition MatrixElements.hpp:325
double omega
Frequency the corrections were evaluated at.
Definition MatrixElements.hpp:310
Options for sr_matrix_elements()
Definition MatrixElements.hpp:341
DiracOperator::MatrixElementType type
Form of matrix element: Reduced, Stretched, or HFConstant.
Definition MatrixElements.hpp:355
bool calculate_both
Calculate both <a||h||b> and <b||h||a>
Definition MatrixElements.hpp:353
bool include_bo
Include the Brueckner orbital correction (set false when the external legs are already Brueckner orbi...
Definition MatrixElements.hpp:359
Frequency operator_omega
Frequency of the operator itself; see Frequency.
Definition MatrixElements.hpp:343
bool print
Print per-element progress (SR is slow)
Definition MatrixElements.hpp:361
SRNoptions(Frequency t_operator_omega, Frequency t_rpa_omega)
The frequency choices must be made explicitly; there is no default.
Definition MatrixElements.hpp:364
bool diagonal
Calculate diagonal matrix elements (only for even-parity operators)
Definition MatrixElements.hpp:349
bool off_diagonal
Calculate off-diagonal matrix elements.
Definition MatrixElements.hpp:351
Frequency rpa_omega
Frequency the RPA, and hence the structure radiation, is evaluated at. With transition,...
Definition MatrixElements.hpp:347