High-precision calculations for one- and two-valence atomic systems
Ladder.hpp
1#pragma once
2#include "Angular/include.hpp"
3#include "Coulomb/include.hpp"
4#include "MBPT/SpinorMatrix.hpp"
5#include "Wavefunction/DiracSpinor.hpp"
6#include <optional>
7#include <string>
8#include <utility>
9
10namespace MBPT {
11
12//! Returns min and max k (multipolarity) allowed for ladder integral
13//! L^k_abcd. Triangle rules {a,c,k} and {b,d,k} apply, plus the combined
14//! parity rule (l_a+l_b+l_c+l_d even). Unlike Q^k, there is no
15//! individual-pair parity rule linking k to the orbital parities, so k takes
16//! both parities: NOT safe to call k+=2.
17inline std::pair<int, int> k_minmax_L(const DiracSpinor &a,
18 const DiracSpinor &b,
19 const DiracSpinor &c,
20 const DiracSpinor &d) {
21 // Combined parity rule: each (direct) Coulomb rung shifts the parity of
22 // both pair lines together, so only the total parity is constrained
23 if ((a.l() + b.l() + c.l() + d.l()) % 2 != 0) {
24 return {1, 0};
25 }
26 const auto [l1, u1] = Coulomb::k_minmax_tj(a.twoj(), c.twoj());
27 const auto [l2, u2] = Coulomb::k_minmax_tj(b.twoj(), d.twoj());
28 return {std::max(l1, l2), std::min(u1, u2)};
29}
30
31//! Returns min and max k (multipolarity) allowed for ladder integral L^k_abcd
32//! (kappa version) - see above. NOT safe to call k+=2.
33inline std::pair<int, int> k_minmax_L(int kap_a, int kap_b, int kap_c,
34 int kap_d) {
35 if ((Angular::l_k(kap_a) + Angular::l_k(kap_b) + Angular::l_k(kap_c) +
36 Angular::l_k(kap_d)) %
37 2 !=
38 0) {
39 return {1, 0};
40 }
41 const auto [l1, u1] =
43 const auto [l2, u2] =
45 return {std::max(l1, l2), std::min(u1, u2)};
46}
47
48/*!
49 @brief Full ladder integral summed over all diagrams.
50 @details
51 Computes
52 \f[
53 L^k_{mnij} = L1^k_{mnij} + L2^k_{mnij} + L3^k_{mnij} [+ L4^k_{mnij}]
54 \f]
55 where \f$ L3^k_{mnij} = L2^k_{nmji} \f$ and \f$ L4 \f$ involves
56 core--core intermediate states. @p Lk points to the ladder table from
57 the previous iteration; pass nullptr on the first iteration.
58
59 @param k Multipole rank
60 @param m,n Excited (particle) orbitals
61 @param i,j Core (hole) or valence orbitals
62 @param qk Coulomb \f$ Q^k \f$ integral table
63 @param core Core orbitals
64 @param excited Excited orbitals
65 @param include_L4 Include the core--core diagram L4
66 @param SJ 6j symbol table
67 @param Lk Ladder table from previous iteration (nullptr on first)
68 @param e_i Optional: used in place of i.en() in energy denominators
69 @param e_m Optional: used in place of m.en() in energy denominators
70 @return \f$ L^k_{mnij} \f$
71 @note To evaluate at a fixed external energy (for a correlation potential),
72 use @p e_i or @p e_m (for external line in the i or m slot): the energy
73 only enters the denominators, never the integral lookups.
74*/
75double Lkmnij(int k, const DiracSpinor &m, const DiracSpinor &n,
76 const DiracSpinor &i, const DiracSpinor &j,
77 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &core,
78 const std::vector<DiracSpinor> &excited, bool include_L4,
79 const Angular::SixJTable &SJ,
80 const Coulomb::LkTable *const Lk = nullptr,
81 std::optional<double> e_i = {}, std::optional<double> e_m = {});
82
83/*!
84 @brief Particle--particle ladder diagram L1.
85 @details
86 \f[
87 L1^k_{mnij} = \sum_{rs,ul} A^{kul}_{mnrsij}
88 \frac{Q^u_{mnrs}\,(Q+L)^l_{rsij}}{\epsilon_{ij} - \epsilon_{rs}}
89 \f]
90 with the angular coefficient
91 \f[
92 A^{kul}_{mnrsij} = (-1)^{m+n+r+s+i+j+1}\,[k]
93 \sixj{m}{i}{k}{l}{u}{r}\sixj{n}{j}{k}{l}{u}{s}
94 \f]
95 Intermediate states \f$ r,s \f$ run over excited orbitals.
96
97 @param k Multipole rank
98 @param m,n Excited (particle) orbitals
99 @param i,j Core (hole) or valence orbitals
100 @param qk Coulomb \f$ Q^k \f$ integral table
101 @param excited Excited orbitals
102 @param SJ 6j symbol table
103 @param Lk Ladder table from previous iteration (nullptr on first)
104 @param e_i Optional: used in place of i.en() in energy denominator
105 @return \f$ L1^k_{mnij} \f$
106*/
107double L1(int k, const DiracSpinor &m, const DiracSpinor &n,
108 const DiracSpinor &i, const DiracSpinor &j,
109 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &excited,
110 const Angular::SixJTable &SJ,
111 const Coulomb::LkTable *const Lk = nullptr,
112 std::optional<double> e_i = {});
113
114/*!
115 @brief Particle--hole ladder diagram L2.
116 @details
117 \f[
118 L2^k_{mnij} = \sum_{rc,ul} (-1)^{k+u+l+1} A^{klu}_{mjcrin}
119 \frac{Q^u_{cnir}\,(Q+L)^l_{mrcj}}{\epsilon_{cj} - \epsilon_{mr}}
120 \f]
121 Intermediate states: \f$ r \f$ runs over excited, \f$ c \f$ over core.
122 The diagram \f$ L3 \f$ is the exchange partner \f$ L3^k_{mnij} = L2^k_{nmji} \f$.
123
124 @param k Multipole rank
125 @param m,n Excited (particle) orbitals
126 @param i,j Core (hole) or valence orbitals
127 @param qk Coulomb \f$ Q^k \f$ integral table
128 @param core Core orbitals
129 @param excited Excited orbitals
130 @param SJ 6j symbol table
131 @param Lk Ladder table from previous iteration (nullptr on first)
132 @param e_j Optional: used in place of j.en() in energy denominator
133 @param e_m Optional: used in place of m.en() in energy denominator
134 @return \f$ L2^k_{mnij} \f$
135*/
136double L2(int k, const DiracSpinor &m, const DiracSpinor &n,
137 const DiracSpinor &i, const DiracSpinor &j,
138 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &core,
139 const std::vector<DiracSpinor> &excited, const Angular::SixJTable &SJ,
140 const Coulomb::LkTable *const Lk = nullptr,
141 std::optional<double> e_j = {}, std::optional<double> e_m = {});
142
143/*!
144 @brief Exchange partner of L2; equals L2 with m,n and i,j swapped.
145 @details
146 \f[ L3^k_{mnij} = L2^k_{nmji} \f]
147 (@p e_i optional: used in place of i.en() in energy denominator)
148*/
149inline double
150L3(int k, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &i,
151 const DiracSpinor &j, const Coulomb::QkTable &qk,
152 const std::vector<DiracSpinor> &core,
153 const std::vector<DiracSpinor> &excited, const Angular::SixJTable &SJ,
154 const Coulomb::LkTable *const Lk = nullptr, std::optional<double> e_i = {}) {
155 return L2(k, n, m, j, i, qk, core, excited, SJ, Lk, e_i);
156}
157
158/*!
159 @brief Core--core (hole--hole) ladder diagram L4.
160 @details
161 Intermediate states run over core orbitals only, making this the
162 hole--hole counterpart of the particle--particle diagram L1.
163 Enable via @p include_L4 in Lkmnij().
164
165 @param k Multipole rank
166 @param m,n Excited (particle) orbitals
167 @param i,j Core (hole) or valence orbitals
168 @param qk Coulomb \f$ Q^k \f$ integral table
169 @param core Core orbitals
170 @param SJ 6j symbol table
171 @param Lk Ladder table from previous iteration (nullptr on first)
172 @param e_m Optional: used in place of m.en() in energy denominator
173 @return \f$ L4^k_{mnij} \f$
174*/
175double L4(int k, const DiracSpinor &m, const DiracSpinor &n,
176 const DiracSpinor &i, const DiracSpinor &j,
177 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &core,
178 const Angular::SixJTable &SJ,
179 const Coulomb::LkTable *const Lk = nullptr,
180 std::optional<double> e_m = {});
181
182/*!
183 @brief Fills the ladder integral table for all _new_ index combinations.
184 @details
185 Iterates over all combinations of excited pairs \f$ (m,n) \f$ and
186 orbitals in @p i_orbs, computing \f$ L^k_{mnib} \f$ and storing results
187 in @p lk.
188 Only calculates new integrals. Only lowest-order.
189
190 @param lk Output ladder table (written in place)
191 @param qk Coulomb \f$ Q^k \f$ integral table
192 @param excited Excited orbitals
193 @param core Core orbitals
194 @param i_orbs Orbitals for the \f$ i \f$ index
195 @param include_L4 Include core-core diagram L4
196 @param sjt 6j symbol table
197 @param max_k Maximum multipolarity; -1 uses qk.max_k()
198 @param print Print Qk info to screen
199*/
201 const std::vector<DiracSpinor> &excited,
202 const std::vector<DiracSpinor> &core,
203 const std::vector<DiracSpinor> &i_orbs, bool include_L4,
204 const Angular::SixJTable &sjt, int max_k = -1,
205 bool print = true);
206
207/*!
208 @brief Updates the ladder integral table with L(Q,Q) -> L(Q,Q+L)
209 @details
210 Iterates over all combinations of excited pairs \f$ (m,n) \f$ and
211 orbitals in @p i_orbs, computing \f$ L^k_{mnib} \f$ and storing results
212 in @p lk. Designed for iterative refinement: pass the previous iteration's
213 table as @p lk_prev.
214
215 @note Does not calculate any new integrals - assumes all already present.
216 Just updates them (based on iterative rule: L(Q,Q) -> L(Q,Q+L))
217
218 @param lk Output ladder table (written in place)
219 @param qk Coulomb \f$ Q^k \f$ integral table
220 @param excited Excited orbitals
221 @param core Core orbitals
222 @param update_i Restrict re-iteration to entries whose i index is in this
223 set (b is always core). Empty => update all. Used to
224 converge core (update_i=core) before valence
225 (update_i=valence).
226 @param include_L4 Include core--core diagram L4
227 @param sjt 6j symbol table
228 @param lk_prev Ladder table from previous iteration
229 @param a_damp Damping factor [0,1) : 0 means no damping
230 @param print Print Qk info to screen
231*/
233 const std::vector<DiracSpinor> &excited,
234 const std::vector<DiracSpinor> &core,
235 const std::vector<DiracSpinor> &update_i, bool include_L4,
236 const Angular::SixJTable &sjt,
237 const Coulomb::LkTable *const lk_prev, double a_damp,
238 bool print);
239
240/*!
241 @brief Second-order (or ladder) correction to the valence energy.
242 @details
243 Computes the correlation energy shift
244 \f[
245 \delta\epsilon_v = \sum_{mnc} \frac{Q^k_{vmcn}\,L^k_{mncv}}{\epsilon_v
246 + \epsilon_c - \epsilon_m - \epsilon_n}
247 \f]
248 (schematic). When @p lk holds plain Coulomb integrals the result is the
249 MBPT(2) correction; when @p lk holds ladder integrals it is the full
250 ladder correction.
251
252 @param v Valence orbital
253 @param qk Coulomb \f$ Q^k \f$ integral table
254 @param lk \f$ Q^k \f$ or ladder \f$ L^k \f$ integral table
255 @param core Core orbitals
256 @param excited Excited orbitals
257 @return \f$ \delta\epsilon_v \f$
258*/
259template <typename Qintegrals, typename QorLintegrals>
260double de_valence(const DiracSpinor &v, const Qintegrals &qk,
261 const QorLintegrals &lk, const std::vector<DiracSpinor> &core,
262 const std::vector<DiracSpinor> &excited);
263
264/*!
265 @brief Ladder (or MBPT2) valence energy, antisymmetrising the FIRST integral.
266 @details
267 Computes
268 \f[
269 \delta\epsilon_v = \sum_{amn,k}\frac{W^k_{vamn}\,L^k_{mnva}}{[k]\,[j_v]\,\Delta\epsilon}
270 + \text{(c+d)},
271 \f]
272 with \f$ W = Q + P \f$ the antisymmetrised Coulomb integral (@p qk.W) and the
273 ladder @p lk entering only through the direct integral @p lk.Q. Equivalent to
274 de_valence() (which instead antisymmetrises the ladder via @p lk.P), since the
275 exchange symmetry holds under the full sum. Unlike de_valence(), this works
276 only with the Coulomb integrals in the first slot (the ladder lacks the
277 required symmetry). No screening/eta is applied.
278
279 @param v Valence orbital
280 @param qk Coulomb integrals supplying \f$ W = Q+P \f$ (first integral)
281 @param lk Ladder \f$ L^k \f$ integrals (second, direct integral)
282 @param core Core orbitals
283 @param excited Excited orbitals
284 @param sj Optional 6j table (speeds up the W exchange sum)
285 @return \f$ \delta\epsilon_v \f$
286*/
287template <typename Qintegrals, typename Lintegrals>
288double de_valence_w(const DiracSpinor &v, const Qintegrals &qk,
289 const Lintegrals &lk, const std::vector<DiracSpinor> &core,
290 const std::vector<DiracSpinor> &excited,
291 const Angular::SixJTable *sj = nullptr);
292
293/*!
294 @brief Second-order (or ladder) correction to the core energy.
295 @details
296 Sums the correlation energy shift over all core orbitals. When @p lk holds
297 plain Coulomb integrals the result is the MBPT(2) core correction; when
298 @p lk holds ladder integrals it is the ladder correction.
299
300 @param qk Coulomb \f$ Q^k \f$ integral table
301 @param lk \f$ Q^k \f$ or ladder \f$ L^k \f$ integral table
302 @param core Core orbitals
303 @param excited Excited orbitals
304 @return Total core correlation energy shift
305*/
306template <typename Qintegrals, typename QorLintegrals>
307double de_core(const Qintegrals &qk, const QorLintegrals &lk,
308 const std::vector<DiracSpinor> &core,
309 const std::vector<DiracSpinor> &excited);
310
311/*!
312 @brief Method used to construct the ladder correlation potential, Sigma_L.
313 @details
314 - basis : project onto the basis; requires extending Qk (slow)
315 [Sigma_ladder()]
316 - ratio : no projection; rescale each Sigma(2) term by L/Q
317 [Sigma_ladder(), empty projection basis]
318 - direct : no projection; open the external line exactly (ladder vertex)
319 [Sigma_ladder_direct()]
320*/
321enum class SigmaLMethod { basis, ratio, direct };
322
323//! Converts string (name) to SigmaLMethod enum (case-insensitive); warns and
324//! defaults to ladder if unknown
325SigmaLMethod parseSigmaLMethod(const std::string &method);
326//! Converts SigmaLMethod enum to string (name)
327std::string parseSigmaLMethod(SigmaLMethod method);
328
329/*!
330 @brief Ladder-diagram correction to the correlation potential, Sigma_L(e_v),
331 by projection (or, if @p projection is empty, by the L/Q ratio method).
332 @details
333 With a non-empty @p projection basis, forms the ladder correlation potential
334 by projecting the discrete ladder integrals onto the projection states of
335 kappa_v. The exchange is folded into the Coulomb vertex via
336 \f$ W = Q + P \f$ (as in de_valence_w):
337 \f[
338 \Sigma_L = \sum_{i,amn,k} |W^k_{\cdot amn}\rangle\,
339 \frac{L^k_{mn,i,a}}{[k][j_v]\,(\epsilon_v+\epsilon_a-\epsilon_m-\epsilon_n)}\,
340 \langle i|
341 + \sum_{i,nab,k} |W^k_{\cdot nab}\rangle\,
342 \frac{L^k_{i,n,a,b}}{[k][j_v]\,(\epsilon_v+\epsilon_n-\epsilon_a-\epsilon_b)}\,
343 \langle i| ,
344 \f]
345 (particle-particle (a+b) and particle-hole (c+d) diagrams). The bra index
346 \f$ i \f$ runs over the @p projection states of kappa_v (approximating
347 completeness). The ladder integrals are computed on-the-fly via Lkmnij()
348 evaluated at the fixed external energy \f$ \epsilon_v \f$ (via the e_i/e_m
349 energy overrides, since the energy enters only the denominators). Exception:
350 for the valence state itself, the stored table entries are used directly -
351 they are already at the correct energy, so the i = v term is essentially
352 free.
353
354 If @p projection is empty, instead uses the ratio method (following
355 V. A. Dzuba, Phys. Rev. A 78, 042502 (2008)): no projection; each term of
356 the regular second-order correlation potential (cf. Goldstone::Sigma_both)
357 is rescaled by the scalar ratio of ladder to Coulomb integrals:
358 \f[
359 \Sigma_L = \sum_{amn,k} |Q^k_{\cdot amn}\rangle\,
360 \frac{L^k_{mnva}/Q^k_{mnva}}{[k][j_v]\,(\epsilon_v+\epsilon_a-\epsilon_m-\epsilon_n)}\,
361 \langle W^k_{\cdot amn}|
362 + \sum_{nab,k} |Q^k_{\cdot nab}\rangle\,
363 \frac{L^k_{vnab}/Q^k_{vnab}}{[k][j_v]\,(\epsilon_v+\epsilon_n-\epsilon_a-\epsilon_b)}\,
364 \langle W^k_{\cdot nab}| .
365 \f]
366 By construction the diagonal reproduces the ladder energy exactly:
367 <v|Sigma_L|v> = de_valence_w(v). The off-diagonal (radial) structure is
368 approximate: each term keeps the shape of the corresponding second-order
369 term, rescaled by a scalar. All integrals come straight from the stored
370 tables (the L^k entries with i = v are already at the valence energy), so
371 nothing is computed on-the-fly: much faster than projection.
372
373 The sub-grid (@p r0, @p rmax, @p stride) defaults match Wavefunction::formSigma.
374
375 @param v Valence state (basis version; must be in the qk/lk tables)
376 @param core Core (hole) orbitals
377 @param excited Excited orbitals
378 @param projection Projection basis {|i>}; states of kappa_v are used. If
379 empty, the ratio method is used instead (no projection)
380 @param qk Converged Coulomb \f$ Q^k \f$ table
381 @param lk Converged ladder \f$ L^k \f$ table. For projection, it is
382 the internal-rung table forwarded to Lkmnij (nullptr for
383 L(Q,Q)=L^(1)); for ratio, it supplies the L^k integrals
384 (nullptr gives Sigma_L = 0)
385 @param sjt 6j symbol table
386 @param include_L4 Include core--core diagram in on-the-fly Lkmnij
387 (projection only; the ratio method never re-computes L)
388 @param r0,rmax,stride Sub-grid parameters
389 @param include_G Include the lower (g) component of Sigma_L
390 @return Sigma_L as a coordinate-space GMatrix
391
392 @note Ratio method: terms with \f$ Q^k_{mnva} = 0 \f$ (but \f$ L^k \ne 0 \f$)
393 cannot be rescaled and are dropped; inherent to the method. Note that
394 L^k exists at both parities of k (see k_minmax_L) while Q^k
395 exists only at Coulomb parity, so the exchange-only (wrong-parity)
396 k channels are always dropped here; the projection and direct methods
397 include them.
398*/
399GMatrix Sigma_ladder(const DiracSpinor &v, const std::vector<DiracSpinor> &core,
400 const std::vector<DiracSpinor> &excited,
401 const std::vector<DiracSpinor> &projection,
402 const Coulomb::QkTable &qk, const Coulomb::LkTable *lk,
403 const Angular::SixJTable &sjt, bool include_L4 = false,
404 double r0 = 1.0e-4, double rmax = 30.0,
405 std::size_t stride = 4, bool include_G = false);
406
407/*!
408 @brief Vertex (ket) form of the ladder integral L^k_mnia over the external
409 index i.
410 @details
411 Returns the radial spinor \f$ |L^k_{mn \cdot a}\rangle \f$ (kappa of @p v)
412 satisfying
413 \f[ \langle x|L^k_{mn\cdot a}\rangle = L^k_{mnxa}(\epsilon_v) \f]
414 for any \f$ x \f$ with \f$ \kappa_x = \kappa_v \f$, with the external energy
415 fixed at \f$ \epsilon_v \f$ (as the e_i override in Lkmnij).
416
417 In each diagram the external line attaches to a single bare Coulomb line;
418 that line is opened exactly as a radial function (Qkv_bcd). The exception is
419 the L-part of the internal (Q+L) rung in L1 and L3, where the external line
420 attaches to a dressed rung: for that piece we set i = v (scalar coefficient
421 times |v>), which is exact at x = v and is the same level of treatment the
422 scalar table gives it (entries exist only for stored orbitals).
423
424 @note All internal lines are Hartree-Fock basis states (from the tables);
425 only the external line is left open. This is the correct structure for
426 acting on Brueckner orbitals.
427*/
428DiracSpinor Lkv_mnia(int k, const DiracSpinor &v, const DiracSpinor &m,
429 const DiracSpinor &n, const DiracSpinor &a,
430 const Coulomb::QkTable &qk, const Coulomb::YkTable &yk,
431 const std::vector<DiracSpinor> &core,
432 const std::vector<DiracSpinor> &excited, bool include_L4,
433 const Angular::SixJTable &SJ,
434 const Coulomb::LkTable *const Lk = nullptr);
435
436/*!
437 @brief Vertex (ket) form of the ladder integral L^k_inab over the external
438 index i (the m-slot).
439 @details
440 Returns the radial spinor \f$ |L^k_{\cdot nab}\rangle \f$ (kappa of @p v)
441 satisfying
442 \f[ \langle x|L^k_{\cdot nab}\rangle = L^k_{xnab}(\epsilon_v) \f]
443 for any \f$ x \f$ with \f$ \kappa_x = \kappa_v \f$, with the external energy
444 fixed at \f$ \epsilon_v \f$ (as the e_m override in Lkmnij).
445
446 Mirror of Lkv_mnia() for the particle-hole (c+d) diagrams: here the external
447 line sits in the m-slot, so it is L2 and L4 whose internal (Q+L) rung
448 contains it (i = v used for the L-part), while L1 and L3 open exactly.
449*/
450DiracSpinor Lkv_inab(int k, const DiracSpinor &v, const DiracSpinor &n,
451 const DiracSpinor &a, const DiracSpinor &b,
452 const Coulomb::QkTable &qk, const Coulomb::YkTable &yk,
453 const std::vector<DiracSpinor> &core,
454 const std::vector<DiracSpinor> &excited, bool include_L4,
455 const Angular::SixJTable &SJ,
456 const Coulomb::LkTable *const Lk = nullptr);
457
458/*!
459 @brief Ladder correlation potential Sigma_L via the direct (open external
460 line) method.
461 @details
462 Forms the ladder correlation potential with the external line opened
463 exactly, rather than projected onto a basis:
464 \f[
465 \Sigma_L = \sum_{amn,k} |W^k_{\cdot amn}\rangle\,
466 \frac{1}{[k][j_v]\,(\epsilon_v+\epsilon_a-\epsilon_m-\epsilon_n)}\,
467 \langle L^k_{mn \cdot a}|
468 + \sum_{nab,k} |W^k_{\cdot nab}\rangle\,
469 \frac{1}{[k][j_v]\,(\epsilon_v+\epsilon_n-\epsilon_a-\epsilon_b)}\,
470 \langle L^k_{\cdot nab}| ,
471 \f]
472 with the bra-side ladder vertices from Lkv_mnia() / Lkv_inab(). All internal
473 lines are Hartree-Fock basis states; the external line is exact wherever it
474 attaches to a bare Coulomb line (everything at lowest order in L), and is
475 taken as |v><v| only for the dressed-rung (internal-L) attachment, which
476 enters the energy at 4th order. Consequently Sigma_L acts correctly on
477 Brueckner orbitals: (H + Sigma + Sigma_L)|psi_B> = e|psi_B>, rather than
478 merely shifting by <v|Sigma_L|v>.
479
480 <v|Sigma_L|v> reproduces the ladder energy de_valence_w (up to iteration
481 convergence of the L table). No projection basis, no Qk extension.
482
483 @param v Valence state (basis version; supplies kappa_v, en_v, and
484 the i=v dressed-rung piece)
485 @param core Core (hole) orbitals
486 @param excited Excited orbitals
487 @param qk Converged Coulomb \f$ Q^k \f$ table
488 @param yk Yk table spanning core+excited (radial vertex functions)
489 @param lk Converged ladder \f$ L^k \f$ table (nullptr: lowest-order L)
490 @param sjt 6j symbol table
491 @param include_L4 Include core--core diagram L4
492 @param r0,rmax,stride Sub-grid parameters
493 @param include_G Include the lower (g) component of Sigma_L
494 @return Sigma_L as a coordinate-space GMatrix
495*/
496GMatrix Sigma_ladder_direct(
497 const DiracSpinor &v, const std::vector<DiracSpinor> &core,
498 const std::vector<DiracSpinor> &excited, const Coulomb::QkTable &qk,
499 const Coulomb::YkTable &yk, const Coulomb::LkTable *lk,
500 const Angular::SixJTable &sjt, bool include_L4 = false, double r0 = 1.0e-4,
501 double rmax = 30.0, std::size_t stride = 4, bool include_G = false);
502
503//==============================================================================
504
505//! Ladder correlation potential matrix, Sigma_L, for a single (kappa, n)
506//! state, evaluated at energy en.
508 int kappa;
509 int n;
510 double en;
511 GMatrix SL;
512};
513
514/*!
515 @brief Writes Sigma_L (ladder) matrices to binary file.
516 @details
517 File contains the full-grid parameters (for checking on read), followed by
518 each Sigma_L matrix with its own sub-grid parameters and include_G flag.
519 Returns false (and writes nothing) if fname is empty or 'false'.
520*/
521bool write_SigmaL(const std::string &fname, const std::vector<SigmaLData> &SLs,
522 const Grid &grid);
523
524/*!
525 @brief Reads Sigma_L (ladder) matrices from binary file.
526 @details
527 Returns empty vector if file doesn't exist or on grid mismatch: @p grid must
528 match the full radial grid the matrices were calculated on. Each matrix
529 carries its own sub-grid parameters and include_G flag (they need not match
530 those of the base Sigma).
531*/
532std::vector<SigmaLData> read_SigmaL(const std::string &fname,
533 const std::shared_ptr<const Grid> &grid);
534
535// template implementations:
536#include "Ladder.ipp"
537
538} // namespace MBPT
Lookup table for Wigner 6j symbols.
Definition SixJTable.hpp:82
Base class template to store Coulomb integrals, and similar. 3 specific cases (by template instantiat...
Definition QkTable.hpp:118
Calculates + stores Hartree Y functions + Angular (w/ look-up), taking advantage of symmetry.
Definition YkTable.hpp:46
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:44
int twoj() const
2j (twice the total angular momentum)
Definition DiracSpinor.hpp:97
int l() const
Orbital angular momentum Q number.
Definition DiracSpinor.hpp:93
Non-uniform radial grid with Jacobian, suitable for atomic structure calculations.
Definition Grid.hpp:85
constexpr int l_k(int ka)
returns l given kappa
Definition Wigner369j.hpp:44
constexpr int twoj_k(int ka)
returns 2j given kappa
Definition Wigner369j.hpp:46
std::pair< int, int > k_minmax_tj(int tja, int tjb)
Returns min and max k (multipolarity) allowed for Triangle(k,a,b), NOT accounting for parity (2j only...
Definition CoulombIntegrals.hpp:104
Many-body perturbation theory.
Definition MatrixElements.hpp:12
double de_valence_w(const DiracSpinor &v, const Qintegrals &qk, const Lintegrals &lk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, const Angular::SixJTable *sj=nullptr)
Ladder (or MBPT2) valence energy, antisymmetrising the FIRST integral.
double L2(int k, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &i, const DiracSpinor &j, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk, std::optional< double > e_j, std::optional< double > e_m)
Particle–hole ladder diagram L2.
Definition Ladder.cpp:400
DiracSpinor Lkv_inab(int k, const DiracSpinor &v, const DiracSpinor &n, const DiracSpinor &a, const DiracSpinor &b, const Coulomb::QkTable &qk, const Coulomb::YkTable &yk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, bool include_L4, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk)
Vertex (ket) form of the ladder integral L^k_inab over the external index i (the m-slot).
Definition Ladder.cpp:1060
SigmaLMethod parseSigmaLMethod(const std::string &method)
Converts string (name) to SigmaLMethod enum (case-insensitive); warns and defaults to ladder if unkno...
Definition Ladder.cpp:24
void update_Lk_mnib(Coulomb::LkTable *lk, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &excited, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &update_i, bool include_L4, const Angular::SixJTable &sjt, const Coulomb::LkTable *const lk_prev, double a_damp, bool print)
Updates the ladder integral table with L(Q,Q) -> L(Q,Q+L)
Definition Ladder.cpp:1429
GMatrix Sigma_ladder_direct(const DiracSpinor &v, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, const Coulomb::QkTable &qk, const Coulomb::YkTable &yk, const Coulomb::LkTable *lk, const Angular::SixJTable &sjt, bool include_L4, double r0, double rmax, std::size_t stride, bool include_G)
Ladder correlation potential Sigma_L via the direct (open external line) method.
Definition Ladder.cpp:1341
std::pair< int, int > k_minmax_L(const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d)
Returns min and max k (multipolarity) allowed for ladder integral L^k_abcd. Triangle rules {a,...
Definition Ladder.hpp:17
double L1(int k, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &i, const DiracSpinor &j, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &excited, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk, std::optional< double > e_i)
Particle–particle ladder diagram L1.
Definition Ladder.cpp:126
GMatrix Sigma_ladder(const DiracSpinor &v, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, const std::vector< DiracSpinor > &projection, const Coulomb::QkTable &qk, const Coulomb::LkTable *lk, const Angular::SixJTable &sjt, bool include_L4, double r0, double rmax, std::size_t stride, bool include_G)
Ladder-diagram correction to the correlation potential, Sigma_L(e_v), by projection (or,...
Definition Ladder.cpp:574
std::vector< SigmaLData > read_SigmaL(const std::string &fname, const std::shared_ptr< const Grid > &grid)
Reads Sigma_L (ladder) matrices from binary file.
Definition Ladder.cpp:1528
DiracSpinor Lkv_mnia(int k, const DiracSpinor &v, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &a, const Coulomb::QkTable &qk, const Coulomb::YkTable &yk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, bool include_L4, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk)
Vertex (ket) form of the ladder integral L^k_mnia over the external index i.
Definition Ladder.cpp:777
double Lkmnij(int k, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &i, const DiracSpinor &j, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, bool include_L4, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk, std::optional< double > e_i, std::optional< double > e_m)
Full ladder integral summed over all diagrams.
Definition Ladder.cpp:107
double de_core(const Qintegrals &qk, const QorLintegrals &lk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited)
Second-order (or ladder) correction to the core energy.
void fill_Lk_mnib(Coulomb::LkTable *lk, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &excited, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &i_orbs, bool include_L4, const Angular::SixJTable &sjt, int max_k, bool print)
Fills the ladder integral table for all new index combinations.
Definition Ladder.cpp:499
SigmaLMethod
Method used to construct the ladder correlation potential, Sigma_L.
Definition Ladder.hpp:321
bool write_SigmaL(const std::string &fname, const std::vector< SigmaLData > &SLs, const Grid &grid)
Writes Sigma_L (ladder) matrices to binary file.
Definition Ladder.cpp:1479
double L3(int k, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &i, const DiracSpinor &j, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk=nullptr, std::optional< double > e_i={})
Exchange partner of L2; equals L2 with m,n and i,j swapped.
Definition Ladder.hpp:150
double de_valence(const DiracSpinor &v, const Qintegrals &qk, const QorLintegrals &lk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited)
Second-order (or ladder) correction to the valence energy.
double L4(int k, const DiracSpinor &m, const DiracSpinor &n, const DiracSpinor &i, const DiracSpinor &j, const Coulomb::QkTable &qk, const std::vector< DiracSpinor > &core, const Angular::SixJTable &SJ, const Coulomb::LkTable *const Lk, std::optional< double > e_m)
Core–core (hole–hole) ladder diagram L4.
Definition Ladder.cpp:272
Ladder correlation potential matrix, Sigma_L, for a single (kappa, n) state, evaluated at energy en.
Definition Ladder.hpp:507