ampsci
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() must be called separately for positive and negative frequencies;
76 the solutions
77 are not related by simple conjugation. To maintain Hermiticity,
78 \f$ [\delta V_\pm(\omega)]^\dag = \delta V_\mp(-\omega) \f$,
79 so dV() is not Hermitian unless solve_core() has been run at the specific \f$\pm\omega\f$
80*/
82
83private:
84 const HF::HartreeFock *p_hf;
85 std::optional<HF::Breit> m_Br{};
86 std::vector<DiracSpinor> m_holes{};
87 std::vector<DiracSpinor> m_excited{};
88
89 // t0 (no RPA). These stay constant for frequency-independent operators
90 // But change for f-dependent. Set during solve_core
91 std::vector<std::vector<double>> m_t0am{};
92 std::vector<std::vector<double>> m_t0ma{};
93 // t's updated each solve_core itteration
94 std::vector<std::vector<double>> m_tam{};
95 std::vector<std::vector<double>> m_tma{};
96
97 // Note: W's depend on rank (also parity)! Can re-use!?
98 // These are probably an excellent candidate for unordered_map?
99 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wanmb{};
100 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wabmn{};
101 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wmnab{};
102 std::vector<std::vector<std::vector<std::vector<double>>>> m_Wmban{};
103
104public:
105 /*!
106 @brief Constructs DiagramRPA from a basis and a Hartree-Fock object.
107 @details
108 Splits @p basis into core (hole) and excited states, then computes the
109 Coulomb W-matrix integrals required by the diagram RPA equations.
110 If @p atom is non-empty the W matrices are read from a binary cache file
111 (named from the atom label, operator rank, parity, and basis string) to
112 avoid recalculation; if no matching file exists the matrices are computed
113 and the file is written for future use.
114 The Breit interaction is included automatically when present in @p in_hf.
115 @param h Pointer to the external-field tensor operator; must not be null
116 @param basis Complete single-particle basis (holes and excited states)
117 @param in_hf Pointer to the Hartree-Fock object; must not be null
118 @param atom Atom label used to form the W-matrix cache filename;
119 pass an empty string to disable file I/O
120 @param print If true, prints progress information to stdout
121 */
123 const std::vector<DiracSpinor> &basis,
124 const HF::HartreeFock *in_hf, const std::string &atom = "",
125 bool print = true);
126
127 //! @brief Constructs DiagramRPA by reusing W matrices from an existing instance
129 const DiagramRPA *const drpa);
130
131public:
132 /*!
133 @brief Iterates the RPA equations to convergence for the core electrons.
134 @details
135 Performs a self-consistent iterative solution of the diagram-method RPA
136 equations at external-field frequency @p omega.
137 The zeroth-order matrix elements \f$ t^{(0)}_{am} \f$ are calculated (so long as max_its>0).
138 Each iteration updates the RPA matrix elements \f$ t_{am} \f$ and
139 \f$ t_{ma} \f$ using the precomputed Coulomb W-matrix integrals until the
140 maximum relative change falls below eps_target(), or @p max_its iterations
141 have been performed.
142 @param omega External-field frequency in atomic units
143 @param max_its Maximum number of iterations (default 200)
144 @param print If true, prints per-iteration progress to stdout
145
146 @note
147 Calling DiagramRPA::dV() without calling DiagramRPA::solve_core() will return 0.
148 Call with max_its = 0 will mean that dV() also returns 0.
149 Call with max_its = 1 will mean that dV() returns the lowest-order dV correction.
150
151 ---
152
153 @note
154 Must be called separately for positive and negative frequencies; the solutions
155 are not related by simple conjugation. To maintain Hermiticity,
156 \f$ [\delta V_\pm(\omega)]^\dag = \delta V_\mp(-\omega) \f$,
157 so dV() is not Hermitian unless solve_core() has been run at both @p omega and -@p omega.
158
159 ---
160
161 @note
162 Does not update the frequency of the operator itself; for frequency-dependent
163 operators, update the operator frequency externally before calling.
164 */
165 void solve_core(double omega, int max_its = 200,
166 bool print = true) override final;
167
168 //! @brief Returns the RPA method identifier (diagram)
169 Method method() const final { return Method::diagram; }
170
171 /*!
172 @brief Returns the RPA correction to a reduced matrix element.
173 @details
174 Computes the many-body RPA correction to the reduced matrix element
175 \f[ \langle a \| \delta V \| b \rangle \f]
176 using the converged RPA matrix elements \f$ t_{am} \f$ from the most
177 recent solve_core() call. Should be called after solve_core() has
178 converged.
179 @param Fa Bra state
180 @param Fb Ket state
181 @return Reduced matrix element of the RPA correction
182
183 @note
184 Not Hermitian - solve_core() must be called with negaitve omega
185 */
186 double dV(const DiracSpinor &Fa, const DiracSpinor &Fb) const override final;
187
188 double dV(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj) const;
189
190 //! @brief Calculates reduced right-hand-side, projected onto kappa: [dV|phi_m]_kappa
191 DiracSpinor dV_rhs(int kappa, const DiracSpinor &Fm,
192 bool conj = false) const final;
193
194 /*!
195 @brief Resets the RPA matrix elements to their unperturbed (zeroth-order) values.
196 @details
197 Clears the \f$ t_{am} \f$ and \f$ t_{ma} \f$ matrices (which encode the
198 hole-excited RPA corrections) back to the state prior to any
199 solve_core() call.
200 Use this to discard a failed or poorly converged solution before restarting,
201 for example with a different frequency or damping parameter.
202 */
203 void clear() final;
204
205 /*!
206 @brief Updates the zeroth-order matrix elements and resets the RPA solution.
207 @details
208 Recomputes the lowest-order (no-RPA) matrix elements \f$ t^{(0)}_{am} \f$
209 for operator @p h . Does not update the rpa T_am values.
210 If @p h is null the currently stored operator is used unchanged.
211 @param h Optional replacement tensor operator; pass nullptr to keep the
212 current operator
213 */
214 void update_t0s(const DiracOperator::TensorOperator *const h = nullptr);
215
216private:
217 // Note: only writes W (depends on k/pi, and basis). Do not write t's, since
218 // they depend on operator. This makes it very fast when making small changes
219 // to operator (don't need to re-calc W)
220 // Note: doesn't depend on grid!
221 bool read_write(const std::string &fname, IO::FRW::RoW rw, bool print = true);
222
223 // Calculates all required W^k integrals (uses rank, parity of h)
224 void fill_W_matrix(const DiracOperator::TensorOperator *const h, bool print);
225 // Calculates all t_am matrix elements (without RPA)
226 void setup_ts(const DiracOperator::TensorOperator *const h);
227
228public:
229 DiagramRPA &operator=(const DiagramRPA &) = delete;
230 DiagramRPA(const DiagramRPA &) = default;
231 ~DiagramRPA() = default;
232};
233
234} // 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:42
Virtual base class for core-polarisation (RPA); computes dV corrections.
Definition CorePolarisation.hpp:140
RPA correction to matrix elements using the diagram technique.
Definition DiagramRPA.hpp:81
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:409
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:470
void update_t0s(const DiracOperator::TensorOperator *const h=nullptr)
Updates the zeroth-order matrix elements and resets the RPA solution.
Definition DiagramRPA.cpp:316
double dV(const DiracSpinor &Fa, const DiracSpinor &Fb) const override final
Returns the RPA correction to a reduced matrix element.
Definition DiagramRPA.cpp:352
Method method() const final
Returns the RPA method identifier (diagram)
Definition DiagramRPA.hpp:169
void clear() final
Resets the RPA matrix elements to their unperturbed (zeroth-order) values.
Definition DiagramRPA.cpp:310
Solves relativistic Hartree-Fock equations for core and valence. Optionally includes Breit and QED ef...
Definition HartreeFock.hpp:72
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition Wavefunction.hpp:37
Dirac operators: TensorOperator base class and derived implementations for single-particle (one-body)...
Definition GenerateOperator.cpp:6
Core-polarisation (RPA) corrections to matrix elements of an external field.
Definition calcMatrixElements.cpp:14
Method
Available RPA/core-polarisation methods.
Definition CorePolarisation.hpp:82
Functions and classes for Hartree-Fock.
Definition CI_Integrals.hpp:13
In-out (timers, profilers, and read/write data)
Definition ChronoTimer.hpp:9