High-precision calculations for one- and two-valence atomic systems
TDHF.hpp
1#pragma once
2#include "CorePolarisation.hpp"
3#include <string>
4#include <vector>
5class DiracSpinor;
6namespace DiracOperator {
7class TensorOperator;
8}
9namespace MBPT {
10class CorrelationPotential;
11}
12
13namespace HF {
14class HartreeFock;
15class Breit;
16} // namespace HF
17
18namespace ExternalField {
19
20/*!
21 @brief Uses TDHF to include core-polarisation (RPA) corrections to matrix
22 elements of an external field operator.
23
24 @details
25 Solves the TDHF equations for each core orbital \f$ \phi_a \f$,
26 \f[
27 (h_{\rm HF} - \en_a \mp \omega)\varphi^a_\pm
28 = -(t_\pm + \delta V_\pm - \delta\en^a_\pm)\phi_a,
29 \f]
30 self-consistently to determine \f$ \delta V_\pm \f$.
31 See the @ref ExternalField namespace documentation for full physics description.
32
33 Each core orbital acquires both a forward (\f$ \varphi^a_+ \f$, stored as X)
34 and backward (\f$ \varphi^a_- \f$, stored as Y) correction. Both contribute
35 to \f$ \delta V_\pm \f$:
36 \f[
37 \delta V_\pm \phi_i =
38 \sum_a^{\rm core} \left[
39 \matel{\phi_a}{Q}{\varphi^a_+}\phi_i - \matel{\phi_a}{Q}{\phi_i}\varphi^a_+
40 + \matel{\varphi^a_-}{Q}{\phi_a}\phi_i - \matel{\varphi^a_-}{Q}{\phi_i}\phi_a
41 \right].
42 \f]
43 It is via \f$ \delta V_\pm \f$ that the \f$ e^{\pm i\omega t} \f$ terms are mixed.
44
45 \par Construction
46 Requires a pointer to the forward operator (\f$ t_+ \f$), a const
47 @ref HF::HartreeFock object, and an optional pointer to the backward
48 operator (\f$ t_- \f$). If @p h_minus is omitted, \f$ t_- \f$ is taken
49 to be the same pointer as \f$ t_+ \f$.
50 The user is responsible for updating operator frequencies externally
51 before calling solve_core().
52 Note: Only need \f$t_-\f$ for operators that depend on the sign of the frequency (e.g., E1v). Most depend only on magnitude, in which case \f$t_- = t_+^\dag \f$, which is dealt with automatically.
53
54 \par Usage
55 @ref solve_core (omega) solves the TDHF equations for a given frequency.
56 @ref dV (Fa, Fb) then returns the RPA correction to the reduced matrix element
57 \f$ \redmatel{a}{\delta V}{b} \f$.
58*/
59class TDHF : public CorePolarisation {
60
61protected:
62 // dPhi = X exp(-iwt) + Y exp(+iwt)
63 // (H - e - w)X = -(h + dV - de)Phi
64 // (H - e + w)Y = -(h* + dV* - de)Phi
65 // X_c = sum_x X_x,
66 // j(x)=j(c)-k,...,j(c)+k. And: pi(x) = pi(c)*pi(h)
67 std::vector<std::vector<DiracSpinor>> m_X{};
68 std::vector<std::vector<DiracSpinor>> m_Y{};
69 std::vector<std::vector<DiracSpinor>> m_hFcore{};
70 std::vector<std::vector<DiracSpinor>> m_hFcore_minus{};
71 // can just write these to disk! Read them in, continue as per normal
72
73 const HF::HartreeFock *const p_hf;
74 const std::vector<DiracSpinor> m_core;
75 // const std::vector<double> m_Hmag;
76 const double m_alpha;
77 const HF::Breit *const p_VBr;
78 // nb: m_h_plus := m_h is the one in CorePolarisation
79 const DiracOperator::TensorOperator *const m_h_minus;
80
81 // If true, eps is the relative change |dPsi| (sqrt of the ratio); if false,
82 // the squared ratio. See eps_dPsi().
83 bool m_eps_sqrt{false};
84
85public:
86 /*!
87 @brief Constructs TDHF for operator h.
88
89 @param h_plus Forward operator \f$ t_+ \f$; must be set to positive
90 frequency before each call to solve_core().
91 @param hf @ref HF::HartreeFock object defining the core.
92 @param h_minus Backward operator \f$ t_- \f$; if nullptr (default), uses
93 @p h_plus. Only needed when the operator is frequency-dependent
94 *and* depends on the **sign** of \f$ \omega \f$ (e.g. E1
95 velocity form). For operators that depend only on
96 \f$ |\omega| \f$ (e.g. M1), the default suffices.
97 */
98 TDHF(const DiracOperator::TensorOperator *const h_plus,
99 const HF::HartreeFock *const hf,
100 const DiracOperator::TensorOperator *const h_minus = nullptr);
101
102 /*!
103 @brief Solves TDHF equations self-consistently for core electrons at frequency omega.
104 @details
105 Iterates the TDHF equations until \f$ \delta V_\pm \f$ converges to within
106 eps_target(), or @p max_its iterations have been performed.
107 Can be re-run at a different frequency without restarting from scratch.
108
109 @param omega External-field frequency \f$ \omega \f$ in atomic units.
110 @param max_its Maximum number of iterations.
111 Set to 1 to get the first-order correction (no damping on
112 first iteration).
113 @param print If true, write convergence progress to screen.
114
115 @note Frequency should be positive; negative is allowed but use with care.
116 Unlike @ref DiagramRPA, TDHF solves for both \f$ \varphi^a_+ \f$ and
117 \f$ \varphi^a_- \f$ simultaneously (see class docs), so a single call
118 covers both contributions to \f$ \delta V_\pm \f$.
119
120 ---
121
122 @note Does not update the frequency of the operator itself; for frequency-dependent
123 operators, update the operator frequency externally before calling.
124 */
125 virtual void solve_core(double omega, int max_its = 100,
126 bool print = true) override;
127
128 virtual Method method() const override { return Method::TDHF; }
129
130 virtual void clear() override final;
131
132 //! Returns reduced matrix element \f$\redmatel{a}{\delta V}{b}\f$,
133 //! or the conjugate \f$\redmatel{a}{\delta V^\dagger}{b}\f$ if conj=true.
134 double dV(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj) const;
135
136 virtual double dV(const DiracSpinor &Fa,
137 const DiracSpinor &Fb) const override final;
138
139 DiracSpinor dV_rhs(int kappa_n, const DiracSpinor &Fm,
140 bool conj = false) const override;
141
142 //! Returns const ref to dPsi orbitals for given core orbital Fc.
143 const std::vector<DiracSpinor> &get_dPsis(const DiracSpinor &Fc,
144 dPsiType XorY) const;
145 //! Returns const ref to dPsi orbital of given kappa.
146 const DiracSpinor &get_dPsi_x(const DiracSpinor &Fc, dPsiType XorY,
147 const int kappa_x) const;
148
149 /*!
150 @brief Forms \f$\varphi^v_\pm\f$ for valence state Fv (including core pol.):
151 single kappa channel.
152 @details
153 Solves
154 \f[ (h_{\rm HF} + \Sigma - \en_v - \omega)\varphi^v_+
155 = -(t + \delta V - \delta\en^v)\phi_v \f]
156 or
157 \f[ (h_{\rm HF} + \Sigma - \en_v + \omega)\varphi^v_-
158 = -(t^\dagger + \delta V^\dagger - \delta\en^v)\phi_v \f]
159 Returns \f$ \chi_\beta \f$ for given kappa_beta, where
160 \f[ X_{j,m} = (-1)^{j_\beta-m}tjs(j,k,j;-m,0,m)\chi_j \f]
161
162 @param Fv Valence state \f$\phi_v\f$.
163 @param omega Perturbation frequency \f$\omega\f$.
164 @param XorY Selects X or Y solution; see @ref dPsiType.
165 @param kappa_beta Kappa quantum number of the target channel.
166 @param Sigma Optional correlation potential; see @ref MBPT::CorrelationPotential.
167 @param st Bra or ket convention; see @ref StateType.
168 @param incl_dV Include the induced potential \f$\delta V\f$ if true.
169 */
171 solve_dPsi(const DiracSpinor &Fv, const double omega, dPsiType XorY,
172 const int kappa_beta,
173 const MBPT::CorrelationPotential *const Sigma = nullptr,
174 StateType st = StateType::ket, bool incl_dV = true) const;
175
176 //! Forms \f$\varphi^v_\pm\f$ for all kappa channels; see @ref solve_dPsi.
177 std::vector<DiracSpinor>
178 solve_dPsis(const DiracSpinor &Fv, const double omega, dPsiType XorY,
179 const MBPT::CorrelationPotential *const Sigma = nullptr,
180 StateType st = StateType::ket, bool incl_dV = true) const;
181
182 // //! Writes dPsi (f-component) to textfile
183 // void print(const std::string &ofname = "dPsi.txt") const;
184
185private:
186 void initialise_dPsi();
187
188 // Single iteration of TDHF equations
189 std::pair<double, std::string> tdhf_core_it(double omega, double eta_damp);
190 // Forms set of h*Fc for all core orbitals and all projections
191 std::vector<std::vector<DiracSpinor>>
192 form_hFcore(const DiracOperator::TensorOperator *h) const;
193 // Solves the MS equations for all projections, single core state
194 void solve_ms_core(std::vector<DiracSpinor> &dFb, const DiracSpinor &Fb,
195 const std::vector<DiracSpinor> &hFbs, const double omega,
196 dPsiType XorY, double eps_ms = 1.0e-9) const;
197 // As solve_ms_core(), but a single channel (one projection). Thread-safe;
198 // used to parallelise tdhf_core_it() over (orbital x channel x X/Y).
199 void solve_ms_core_b(DiracSpinor &dF_beta, const DiracSpinor &Fb,
200 const DiracSpinor &hFb, const double omega,
201 dPsiType XorY, double eps_ms = 1.0e-9) const;
202
203 // Convergence (eps): the relative L2 change of the (undamped) X spinors,
204 // Sum|dX|^2 / Sum|X_new|^2 (summed over all channels); returns its sqrt
205 // -- the relative change -- if @p relative. Returns {eps, worst-channel}.
206 std::pair<double, std::string>
207 eps_dPsi(const std::vector<std::vector<DiracSpinor>> &Xnew,
208 bool relative) const;
209
210public:
211 TDHF &operator=(const TDHF &) = delete;
212 TDHF(const TDHF &) = default;
213 ~TDHF() = default;
214};
215
216} // 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
Uses TDHF to include core-polarisation (RPA) corrections to matrix elements of an external field oper...
Definition TDHF.hpp:59
virtual void clear() override final
Clears the internal state back to pre solve_core()
Definition TDHF.cpp:74
const DiracSpinor & get_dPsi_x(const DiracSpinor &Fc, dPsiType XorY, const int kappa_x) const
Returns const ref to dPsi orbital of given kappa.
Definition TDHF.cpp:91
double dV(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj) const
Returns reduced matrix element , or the conjugate if conj=true.
Definition TDHF.cpp:388
std::vector< DiracSpinor > solve_dPsis(const DiracSpinor &Fv, const double omega, dPsiType XorY, const MBPT::CorrelationPotential *const Sigma=nullptr, StateType st=StateType::ket, bool incl_dV=true) const
Forms for all kappa channels; see solve_dPsi.
Definition TDHF.cpp:100
const std::vector< DiracSpinor > & get_dPsis(const DiracSpinor &Fc, dPsiType XorY) const
Returns const ref to dPsi orbitals for given core orbital Fc.
Definition TDHF.cpp:81
virtual void solve_core(double omega, int max_its=100, bool print=true) override
Solves TDHF equations self-consistently for core electrons at frequency omega.
Definition TDHF.cpp:334
virtual Method method() const override
Returns RPA method.
Definition TDHF.hpp:128
DiracSpinor dV_rhs(int kappa_n, const DiracSpinor &Fm, bool conj=false) const override
Returns [dV_pm * phi_m]_kappa: RHS of TDHF eq., projected onto kappa (see namespace doc)
Definition TDHF.cpp:400
DiracSpinor solve_dPsi(const DiracSpinor &Fv, const double omega, dPsiType XorY, const int kappa_beta, const MBPT::CorrelationPotential *const Sigma=nullptr, StateType st=StateType::ket, bool incl_dV=true) const
Forms for valence state Fv (including core pol.): single kappa channel.
Definition TDHF.cpp:113
Breit potentials for one- (Hartree-Fock Breit) and two-body Breit integrals.
Definition Breit.hpp:88
Solves relativistic Hartree-Fock equations for core and valence. Optionally includes Breit and QED ef...
Definition HartreeFock.hpp:92
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
StateType
Whether the state is a bra or ket.
Definition CorePolarisation.hpp:112
dPsiType
Selects the perturbed orbital: X = varphi_+, Y = varphi_-.
Definition CorePolarisation.hpp:110
Method
Available RPA/core-polarisation methods.
Definition CorePolarisation.hpp:82
Functions and classes for Hartree-Fock.
Definition CI_Integrals.hpp:13
Many-body perturbation theory.
Definition CI_Integrals.hpp:10
void Breit(const IO::InputBlock &input, const Wavefunction &wf)
Breit corrections to HF energies and matrix elements.
Definition Breit.cpp:38