High-precision calculations for one- and two-valence atomic systems
DiagramRPA.hpp
1#pragma once
2#include "CorePolarisation.hpp"
3#include "Coulomb/QkTable.hpp"
4#include "HF/Breit.hpp"
5#include "IO/FRW_fileReadWrite.hpp"
6#include "Wavefunction/DiracSpinor.hpp"
7#include <vector>
8class Wavefunction;
9class DiracSpinor;
10namespace DiracOperator {
11class TensorOperator;
12}
13namespace HF {
14class HartreeFock;
15}
16
17namespace ExternalField {
18
19/*!
20 @brief RPA correction to matrix elements using the diagram technique.
21 @details
22 The basic equation is:
23
24 \f[
25 \langle{w}|{\delta V_{\pm}}|{v}\rangle =
26 \sum_{na}\frac{t_{na}\,\widetilde g_{wavn}}{\varepsilon_a - \varepsilon_n \pm \omega}
27 +
28 \sum_{na}\frac{t_{an}\,\widetilde g_{wnva}}{\varepsilon_a - \varepsilon_n \mp \omega},
29 \f]
30
31 These should be solved self-consistently for all core-excited matrix elements.
32 Should be solved independently for each frequency, including negative frequencies. To maintain Hermicity:
33
34 \f[
35 [\delta V_{\pm}(\omega)]^\dag = \delta V_{\mp}(-\omega).
36 \f]
37
38 The reduced matrix elements are:
39
40 \f[
41 \langle{w}\|{\delta V_{\pm}}\|{v}\rangle =
42 \sum_{na}\frac{(-1)^{k+w-n}}{[k]}\Bigg(
43 \frac{T_{na}\,W^k_{wavn}}{\varepsilon_a - \varepsilon_n \pm \omega}
44 +
45 \frac{(-1)^{a-n}T_{an}\,W^k_{wnva}}{\varepsilon_a - \varepsilon_n \mp \omega}
46 \Bigg).
47 \f]
48
49 @note
50 Stores a pointer to the external field operator.
51 That operator must remain alive for life of DiagramRPA object.
52 Also, for frequency-dependent operators, updating the frequency of the operator externally will affect
53 the results from this class (as it should).
54 The DiagramRPA::solve_core() function should be re called if the external operator is updated.
55
56 ---
57
58 @note
59 Stores required W^k integrals (only those which are required).
60 Writes them to disk by default.
61 This can use significant memory, particularly for large basis.
62 At the moment, always uses full basis -- this may optionally change in the future.
63
64 ---
65
66 @note
67 Calling DiagramRPA::dV() without calling DiagramRPA::solve_core() will return 0.
68 This is different from previous behaviour, where it returned dV^1, but in line with others.
69 Call with max_its = 0 will also return 0.
70 Call with max_its = 1 will return lowest-order dV correction.
71
72 ---
73
74 @note
75 @ref solve_core() solves at \f$ |\omega| \f$ for both components at once
76 (\f$ t_{am} \f$ and \f$ t_{ma} \f$, with the \f$ \mp\omega \f$
77 denominators), as TDHF does. dV(a, b, conj) returns the component at
78 \f$ +|\omega| \f$ (absorption; conj = false) or at \f$ -|\omega| \f$
79 (emission; conj = true), the latter being the Hermitian conjugate:
80 \f$ [\delta V_\pm(\omega)]^\dag = \delta V_\mp(-\omega) \f$.
81*/
83
84private:
85 const HF::HartreeFock *p_hf;
86 std::optional<HF::Breit> m_Br{};
87 std::vector<DiracSpinor> m_holes{};
88 std::vector<DiracSpinor> m_excited{};
89
90 // t0 (no RPA). These stay constant for frequency-independent operators
91 // But change for f-dependent. Set during solve_core
92 std::vector<std::vector<double>> m_t0am{};
93 std::vector<std::vector<double>> m_t0ma{};
94 // t's updated each solve_core itteration
95 std::vector<std::vector<double>> m_tam{};
96 std::vector<std::vector<double>> m_tma{};
97
98 // Note: W's depend on rank (also parity)! Can re-use!?
99 // These are probably an excellent candidate for unordered_map?
100 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wanmb{};
101 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wabmn{};
102 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wmnab{};
103 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wmban{};
104
105public:
106 /*!
107 @brief Constructs DiagramRPA from a basis and a Hartree-Fock object.
108 @details
109 Splits @p basis into core (hole) and excited states, then computes the
110 Coulomb W-matrix integrals required by the diagram RPA equations.
111 If @p atom is non-empty the W matrices are read from a binary cache file
112 (named from the atom label, operator rank, parity, and basis string) to
113 avoid recalculation; if no matching file exists the matrices are computed
114 and the file is written for future use.
115 The Breit interaction is included automatically when present in @p in_hf.
116 @param h Pointer to the external-field tensor operator; must not be null
117 @param basis Complete single-particle basis (holes and excited states)
118 @param in_hf Pointer to the Hartree-Fock object; must not be null
119 @param atom Atom label used to form the W-matrix cache filename;
120 pass an empty string to disable file I/O
121 @param print If true, prints progress information to stdout
122 */
124 const std::vector<DiracSpinor> &basis,
125 const HF::HartreeFock *in_hf, const std::string &atom = "",
126 bool print = true);
127
128 //! @brief Constructs DiagramRPA by reusing W matrices from an existing instance
130 const DiagramRPA *const drpa);
131
132public:
133 /*!
134 @brief Iterates the RPA equations to convergence for the core electrons.
135 @details
136 Performs a self-consistent iterative solution of the diagram-method RPA
137 equations at external-field frequency @p omega.
138 The zeroth-order matrix elements \f$ t^{(0)}_{am} \f$ are calculated (so long as max_its>0).
139 Each iteration updates the RPA matrix elements \f$ t_{am} \f$ and
140 \f$ t_{ma} \f$ using the precomputed Coulomb W-matrix integrals until the
141 maximum relative change falls below eps_target(), or @p max_its iterations
142 have been performed.
143 @param omega External-field frequency in atomic units
144 @param max_its Maximum number of iterations (default 200)
145 @param print If true, prints per-iteration progress to stdout
146
147 @note
148 Calling DiagramRPA::dV() without calling DiagramRPA::solve_core() will return 0.
149 Call with max_its = 0 will mean that dV() also returns 0.
150 Call with max_its = 1 will mean that dV() returns the lowest-order dV correction.
151
152 ---
153
154 @note
155 Solved at \f$ |\omega| \f$: the sign of @p omega is ignored, both
156 components being found together; see dV() for selecting between them.
157
158 ---
159
160 @note
161 Does not update the frequency of the operator itself; for frequency-dependent
162 operators, update the operator frequency externally before calling.
163 */
164 void solve_core(double omega, int max_its = 200,
165 bool print = true) override final;
166
167 //! @brief Returns the RPA method identifier (diagram)
168 Method method() const final { return Method::diagram; }
169
170 /*!
171 @brief Returns the RPA correction to a reduced matrix element,
172 <a||dV||b>; see CorePolarisation::dV.
173 @details
174 Uses the converged RPA matrix elements \f$ t_{am} \f$ (and
175 \f$ t_{ma} \f$) from the most recent solve_core() call.
176 @param Fa Bra state
177 @param Fb Ket state
178 @param conj false: dV at +|omega| (absorption); true: at -|omega|
179 (emission, the Hermitian conjugate)
180 */
181 double dV(const DiracSpinor &Fa, const DiracSpinor &Fb,
182 bool conj = false) const override final;
183
184 //! @brief Calculates reduced right-hand-side, projected onto kappa: [dV|phi_m]_kappa
185 DiracSpinor dV_rhs(int kappa, const DiracSpinor &Fm,
186 bool conj = false) const final;
187
188 /*!
189 @brief Resets the RPA matrix elements to their unperturbed (zeroth-order) values.
190 @details
191 Clears the \f$ t_{am} \f$ and \f$ t_{ma} \f$ matrices (which encode the
192 hole-excited RPA corrections) back to the state prior to any
193 solve_core() call.
194 Use this to discard a failed or poorly converged solution before restarting,
195 for example with a different frequency or damping parameter.
196 */
197 void clear() final;
198
199 /*!
200 @brief Updates the zeroth-order matrix elements and resets the RPA solution.
201 @details
202 Recomputes the lowest-order (no-RPA) matrix elements \f$ t^{(0)}_{am} \f$
203 for operator @p h . Does not update the rpa T_am values.
204 If @p h is null the currently stored operator is used unchanged.
205 @param h Optional replacement tensor operator; pass nullptr to keep the
206 current operator
207 */
208 void update_t0s(const DiracOperator::TensorOperator *const h = nullptr);
209
210private:
211 // Note: only writes W (depends on k/pi, and basis). Do not write t's, since
212 // they depend on operator. This makes it very fast when making small changes
213 // to operator (don't need to re-calc W)
214 // Note: doesn't depend on grid!
215 bool read_write(const std::string &fname, IO::FRW::RoW rw, bool print = true);
216
217 // Calculates all required W^k integrals (uses rank, parity of h)
218 void fill_W_matrix(const DiracOperator::TensorOperator *const h, bool print);
219 // Calculates all t_am matrix elements (without RPA)
220 void setup_ts(const DiracOperator::TensorOperator *const h);
221
222public:
223 DiagramRPA &operator=(const DiagramRPA &) = delete;
224 DiagramRPA(const DiagramRPA &) = default;
225 ~DiagramRPA() = default;
226};
227
228} // namespace ExternalField
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
RPA correction to matrix elements using the diagram technique.
Definition DiagramRPA.hpp:82
DiracSpinor dV_rhs(int kappa, const DiracSpinor &Fm, bool conj=false) const final
Calculates reduced right-hand-side, projected onto kappa: [dV|phi_m]_kappa.
Definition DiagramRPA.cpp:404
void solve_core(double omega, int max_its=200, bool print=true) override final
Iterates the RPA equations to convergence for the core electrons.
Definition DiagramRPA.cpp:465
void update_t0s(const DiracOperator::TensorOperator *const h=nullptr)
Updates the zeroth-order matrix elements and resets the RPA solution.
Definition DiagramRPA.cpp:321
Method method() const final
Returns the RPA method identifier (diagram)
Definition DiagramRPA.hpp:168
double dV(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj=false) const override final
Returns the RPA correction to a reduced matrix element, <a||dV||b>; see CorePolarisation::dV.
Definition DiagramRPA.cpp:358
void clear() final
Resets the RPA matrix elements to their unperturbed (zeroth-order) values.
Definition DiagramRPA.cpp:315
Solves relativistic Hartree-Fock equations for core and valence. Optionally includes Breit and QED ef...
Definition HartreeFock.hpp:114
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition Wavefunction.hpp:48
Dirac operators: TensorOperator base class and derived implementations for single-particle (one-body)...
Definition SecondOrder.hpp:7
Core-polarisation (RPA) corrections to matrix elements of an external field.
Definition MatrixElements.hpp:9
Method
Available RPA/core-polarisation methods.
Definition CorePolarisation.hpp:87
Functions and classes for Hartree-Fock.
Definition CI_Integrals.hpp:16
In-out (timers, profilers, and read/write data)
Definition ChronoTimer.hpp:9