High-precision calculations for one- and two-valence atomic systems
TDHFcntm.hpp
1#pragma once
2#include "TDHF.hpp"
3#include <complex>
4#include <string>
5#include <utility>
6#include <vector>
7
8namespace ExternalField {
9
10/*!
11 @brief TDHF (RPA) core polarisation above ionisation threshold(s): the open
12 channels are solved with the outgoing-wave boundary condition, so the
13 corrections and the corrected matrix elements are complex.
14
15 @details
16 As @ref TDHF, for a frequency above the ionisation threshold of one or more
17 core orbitals,
18
19 \f[
20 \en^a_+ = \en_a + \omega > 0.
21 \f]
22
23 Every X (+) channel of such an orbital is open, and describes the ejected
24 electron. For it, the solution of the TDHF equation regular at the origin is
25 not unique (the continuum orbital at en_+ may be added freely);
26 the physical solution is the purely outgoing wave at large r,
27 which is complex.
28
29 All other channels (closed orbitals, and every Y (-) partner) are bound,
30 and are solved as in TDHF.
31 Through dV every correction is complex: the real and imaginary parts
32 are stored as separate sets (m_X, m_Y and m_Xi, m_Yi) and iterated
33 together. Below every threshold the imaginary sets are exactly zero and the
34 class reproduces TDHF.
35
36 In dV the (-) corrections enter as complex conjugates, so the Y sets store
37 \f$ (\varphi_-)^* \f$ and the (real-linear) dV builder of TDHF applies to
38 each set unchanged; the external field drives the real set only, and the
39 two sets couple solely through the outgoing boundary condition.
40
41 \par Open channels
42 The ejected electron moves in the field of the residual ion: the
43 self-interaction of one electron in the ionised orbital,
44 \f$ V^a_0 = y^0_{aa} + X_a \f$ (direct and one-electron exchange), is moved
45 from the HF Hamiltonian into the source. This is an exact rearrangement:
46 the channel Hamiltonian has the correct -1/r tail, and the source is short
47 ranged (the y^0_aa term cancels, pointwise, the 1/r tail of the a term of
48 dV phi_a).
49
50 With the real regular and irregular solutions F_reg, F_irr of the local
51 channel Hamiltonian at en_+ (F_reg + i F_irr is outgoing), the standing-wave
52 solve returns \f$ \varphi_P \to K F_{\rm irr} \f$, and the outgoing solution
53 is \f$ \varphi_+ = \varphi_P - iK F_{\rm reg} \f$.
54
55 With the non-local
56 exchange iterated in the source, F_reg is replaced by the exchange-dressed
57 regular solution \f$ F^{\rm HF} \to F_{\rm reg} + K_{\rm ex} F_{\rm irr} \f$
58 (built once per channel per omega), and
59
60 \f[ K_+ = \frac{K}{1 + iK_{\rm ex}}, \f]
61
62 and
63
64 \f[
65 \varphi_+ = \varphi_P - iK_+F^{\rm HF}
66 \to -iK_+\left(F_{\rm reg} + iF_{\rm irr}\right).
67 \f]
68
69 For a complex source, phi_P is two real standing-wave solves
70 (@ref solveContinuumMixedState).
71
72 \par Iteration
73 The TDHF map is linear in the corrections, and damped iteration diverges
74 near resonances (autoionising resonances, omega ~ en_b - en_a). The
75 self-consistency is therefore driven by Anderson mixing
76 (@ref anderson_coefficients) of the whole state, all corrections together
77 with the channel amplitudes K_+ (linear in the state), which converges
78 wherever the linear problem is non-singular.
79
80 \par Usage
81 As TDHF: @ref solve_core (omega), then
82 - @ref A_phys: the ionisation amplitude of each open channel,
83 \f$ A = K_+^* / \pi \f$, in @ref channel_list order. |A| replaces
84 \f$ |\redmatel{\en\kappa}{t}{a}| \f$ in cross-sections (energy-normalised
85 continuum states); the conjugate is the conventional normalisation of
86 the final state to incoming waves. The phase is relative to the regular
87 solution of the local channel potential: the relative phase of two
88 operators in the same channel is physical, absolute phases and phases
89 between channels are not.
90 - @ref dV_complex (Fa, Fb): the complex \f$ \redmatel{a}{\delta V}{b} \f$;
91 equals TDHF::dV below every threshold.
92*/
93class TDHFcntm : public TDHF {
94
95public:
96 //! Constructs for operator h; see TDHF::TDHF.
98 const HF::HartreeFock *const hf);
99
100 //! Open channel: core-orbital index, ejected-electron kappa, and its
101 //! energy en = en_a + omega
102 struct Channel {
103 std::size_t i_core;
104 int kappa;
105 double en;
106 };
107
108 /*!
109 @brief Solves the (complex) TDHF equations self-consistently at omega.
110 @details Re-solving at the same omega warm-starts from the previous
111 solution; the continuum data of the open channels is rebuilt only when
112 omega changes.
113 @param omega Frequency (atomic units); its magnitude is used.
114 @param max_its Maximum number of iterations; 1 gives the first-order
115 (outgoing-wave) correction.
116 @param print If true, write convergence progress to screen.
117 */
118 void solve_core(double omega, int max_its = 100, bool print = true) override;
119
120 //! Clears the corrections and the continuum channel data
121 void clear() override;
122
123 Method method() const override final { return Method::cntm; }
124
125 //! Open channels at the omega of the last solve_core(), in A_phys order;
126 //! empty before solve_core(), or if no channel is open
127 std::vector<Channel> channel_list() const;
128
129 //! Ionisation amplitude A = K_+^*/pi of every open channel (see class
130 //! description), in channel_list order. Requires solve_core().
131 std::vector<std::complex<double>> A_phys() const;
132
133 //! A (see A_phys) of the channel of core orbital Fa with ejected-electron
134 //! kappa; zero if that channel is closed
135 std::complex<double> A_phys(const DiracSpinor &Fa, int kappa) const;
136
137 /*!
138 @brief Reduced matrix element of the (complex) induced potential,
139 <a||dV||b>, or the conjugate <a||dV^dag||b> if conj.
140
141 @details The complex version of @ref TDHF::dV. Real, and equal to TDHF,
142 below every threshold. For a continuum
143 bra (en_a > 0), Fa must be the energy-normalised continuum state of hole
144 Fb in the V^{N-1} potential (direct y^0_bb and one-electron exchange of
145 Fb removed); the source then includes the hole term V^b_0 phi of the
146 rearranged channel equation, so that <Fa||t||b> + dV_complex(Fa, Fb) is
147 the outgoing-wave amplitude, |A| of @ref A_phys in the phase reference
148 of Fa.
149 */
150 std::complex<double> dV_complex(const DiracSpinor &Fa, const DiracSpinor &Fb,
151 bool conj = false) const;
152
153 /*!
154 @brief Real part of dV_complex, for bound Fa and Fb only.
155
156 @details
157 Exact below every threshold, where the class acts as TDHF.
158
159 @warning Asserts (and aborts) if either state is a continuum state
160 (en > 0): dV_complex must be used there.
161 */
162 double dV(const DiracSpinor &Fa, const DiracSpinor &Fb,
163 bool conj = false) const override;
164
165 //! Real part of dV_complex. Convenience only: the full complex element is
166 //! calculated, so prefer dV_complex if both parts are needed
167 double dV_re(const DiracSpinor &Fa, const DiracSpinor &Fb,
168 bool conj = false) const;
169 //! Imaginary part of dV_complex. Convenience only: the full complex element
170 //! is calculated, so prefer dV_complex if both parts are needed
171 double dV_im(const DiracSpinor &Fa, const DiracSpinor &Fb,
172 bool conj = false) const;
173
174private:
175 // Imaginary parts of the corrections, indexed as m_X / m_Y (the real
176 // parts). The Y sets store conj(Y) (see class description).
177 std::vector<std::vector<DiracSpinor>> m_Xi{};
178 std::vector<std::vector<DiracSpinor>> m_Yi{};
179
180 // Continuum data of one (core orbital x channel) at fixed omega: whether
181 // the channel is open (en_+ > 0 and resolvable on the grid); the
182 // homogeneous pair Freg/Firr at en_+ in the local channel potential
183 // (vlocal - y^0_aa + U_KS); the exchange-dressed regular solution
184 // F^HF ~ Freg + K_ex Firr; and the outgoing amplitude K_+ of the latest
185 // solve. Indexed as m_X.
186 struct ContinuumChannel {
187 bool open{false};
188 DiracSpinor Freg;
189 DiracSpinor Firr;
190 DiracSpinor Fhf;
191 double K_ex{0.0};
192 std::complex<double> K{0.0};
193 };
194 std::vector<std::vector<ContinuumChannel>> m_channels{};
195 // The omega m_channels was built at (rebuilt when it changes)
196 double m_omega{-1.0};
197
198 // (Re)shapes the imaginary sets to m_X / m_Y, zeroed
199 void zero_imaginary_sets();
200
201 // Builds m_channels for omega: for each open channel the pair Freg/Firr,
202 // then F^HF and K_ex
203 void prepare_channels(double omega);
204
205 // (i_core, i_channel) of the channel of core orbital Fb with kappa
206 std::pair<std::size_t, std::size_t> channel_index(const DiracSpinor &Fb,
207 int kappa) const;
208
209 // One (undamped) application of the complex TDHF map to the stored
210 // corrections, all (core orbital x channel x X/Y) solves task-flattened,
211 // each channel solved to relative accuracy eps_ms; returns the
212 // convergence measure {eps, worst channel}
213 std::pair<double, std::string> tdhf_core_it_complex(double omega,
214 double eps_ms);
215
216 // Outgoing-wave solve of one open X channel: real and imaginary parts of
217 // the previous iterate in, new iterate out; K_+ written to the channel
218 void solve_channel_outgoing(DiracSpinor *X_re, DiracSpinor *X_im,
219 ContinuumChannel *channel, const DiracSpinor &Fb,
220 const DiracSpinor &hFb, const DiracSpinor &dV_re,
221 const DiracSpinor &dV_im, double omega,
222 double eps_ms) const;
223
224 // Bound channel (closed orbital, or the Y partner of an ionised orbital),
225 // as TDHF. hFb may be nullptr (no external-field source: the imaginary
226 // part).
227 void solve_channel_bound(DiracSpinor *dF_beta, const DiracSpinor &Fb,
228 const DiracSpinor *hFb, const DiracSpinor &dV_src,
229 double omega, dPsiType XorY, double eps_ms) const;
230
231 // The hole term V^a_0 chi = (y^0_aa + X_a) chi of ionised orbital Fa: the
232 // one-electron self-interaction moved from the Hamiltonian of the open
233 // channels into their source
234 DiracSpinor hole_compensation(const DiracSpinor &Fa,
235 const DiracSpinor &chi) const;
236
237 // Convergence measure of one iteration: bound channels, the relative L2
238 // change of (X_re, X_im) over the norm of ALL X channels (a negligible
239 // bound remnant must not gate the iteration); open channels,
240 // |dK_+|^2 / max(|K_+|^2, floor). K_old indexed as m_channels.
241 std::pair<double, std::string> eps_complex(
242 const std::vector<std::vector<DiracSpinor>> &Xs_re,
243 const std::vector<std::vector<DiracSpinor>> &Xs_im,
244 const std::vector<std::vector<std::complex<double>>> &K_old) const;
245
246 // The full state (all corrections, real and imaginary, and the channel
247 // amplitudes) as one real vector, and back: the Anderson iterate
248 std::vector<double> state_vector() const;
249 void set_state(const std::vector<double> &state);
250
251public:
252 TDHFcntm &operator=(const TDHFcntm &) = delete;
253 TDHFcntm(const TDHFcntm &) = default;
254 ~TDHFcntm() = default;
255};
256
257} // 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
Uses TDHF to include core-polarisation (RPA) corrections to matrix elements of an external field oper...
Definition TDHF.hpp:58
TDHF (RPA) core polarisation above ionisation threshold(s): the open channels are solved with the out...
Definition TDHFcntm.hpp:93
double dV_re(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj=false) const
Real part of dV_complex. Convenience only: the full complex element is calculated,...
Definition TDHFcntm.cpp:599
TDHFcntm(const DiracOperator::TensorOperator *const h, const HF::HartreeFock *const hf)
Constructs for operator h; see TDHF::TDHF.
Definition TDHFcntm.cpp:24
void solve_core(double omega, int max_its=100, bool print=true) override
Solves the (complex) TDHF equations self-consistently at omega.
Definition TDHFcntm.cpp:139
double dV(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj=false) const override
Real part of dV_complex, for bound Fa and Fb only.
Definition TDHFcntm.cpp:591
double dV_im(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj=false) const
Imaginary part of dV_complex. Convenience only: the full complex element is calculated,...
Definition TDHFcntm.cpp:605
std::complex< double > dV_complex(const DiracSpinor &Fa, const DiracSpinor &Fb, bool conj=false) const
Reduced matrix element of the (complex) induced potential, <a||dV||b>, or the conjugate <a||dV^dag||b...
Definition TDHFcntm.cpp:568
std::vector< std::complex< double > > A_phys() const
Ionisation amplitude A = K_+^*‍/pi of every open channel (see class description), in channel_list ord...
Definition TDHFcntm.cpp:543
Method method() const override final
Returns RPA method.
Definition TDHFcntm.hpp:123
std::vector< Channel > channel_list() const
Open channels at the omega of the last solve_core(), in A_phys order; empty before solve_core(),...
Definition TDHFcntm.cpp:515
void clear() override
Clears the corrections and the continuum channel data.
Definition TDHFcntm.cpp:40
Open channel: core-orbital index, ejected-electron kappa, and its energy en = en_a + omega.
Definition TDHFcntm.hpp:102
Solves relativistic Hartree-Fock equations for core and valence. Optionally includes Breit and QED ef...
Definition HartreeFock.hpp:114
Core-polarisation (RPA) corrections to matrix elements of an external field.
Definition MatrixElements.hpp:9
dPsiType
Selects the perturbed orbital: X = varphi_+, Y = varphi_-.
Definition CorePolarisation.hpp:117
Method
Available RPA/core-polarisation methods.
Definition CorePolarisation.hpp:87