ampsci
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
7namespace MBPT {
8
9// // Weighted average:
10// fk = 0.714, 0.617, 0.832, 0.885, 0.941, 0.970, 0.987, 0.994
11// fk = 0.654, 0.514, 0.792, 0.857, 0.930, 0.967, 0.986, 0.994 // w/ hp
12// eta= 1.258, 1.511, 1.281, 1.175, 1.114, 1.073, 1.062, 1.066
13
14/*!
15 @brief Full ladder integral summed over all diagrams.
16 @details
17 Computes
18 \f[
19 L^k_{mnij} = L1^k_{mnij} + L2^k_{mnij} + L3^k_{mnij} [+ L4^k_{mnij}]
20 \f]
21 where \f$ L3^k_{mnij} = L2^k_{nmji} \f$ and \f$ L4 \f$ involves
22 core--core intermediate states. @p Lk points to the ladder table from
23 the previous iteration; pass nullptr on the first iteration.
24
25 @param k Multipole rank
26 @param m,n Excited (particle) orbitals
27 @param i,j Core (hole) or valence orbitals
28 @param qk Coulomb \f$ Q^k \f$ integral table
29 @param core Core orbitals
30 @param excited Excited orbitals
31 @param include_L4 Include the core--core diagram L4
32 @param SJ 6j symbol table
33 @param Lk Ladder table from previous iteration (nullptr on first)
34 @param fk Optional screening factors \f$ f_k \f$
35 @return \f$ L^k_{mnij} \f$
36*/
37double Lkmnij(int k, const DiracSpinor &m, const DiracSpinor &n,
38 const DiracSpinor &i, const DiracSpinor &j,
39 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &core,
40 const std::vector<DiracSpinor> &excited, bool include_L4,
41 const Angular::SixJTable &SJ,
42 const Coulomb::LkTable *const Lk = nullptr,
43 const std::vector<double> &fk = {});
44
45/*!
46 @brief Particle--particle ladder diagram L1.
47 @details
48 \f[
49 L1^k_{mnij} = \sum_{rs,ul} A^{kul}_{mnrsij}
50 \frac{Q^u_{mnrs}\,(Q+L)^l_{rsij}}{\epsilon_{ij} - \epsilon_{rs}}
51 \f]
52 with the angular coefficient
53 \f[
54 A^{kul}_{mnrsij} = (-1)^{m+n+r+s+i+j+1}\,[k]
55 \sixj{m}{i}{k}{l}{u}{r}\sixj{n}{j}{k}{l}{u}{s}
56 \f]
57 Intermediate states \f$ r,s \f$ run over excited orbitals.
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 excited Excited orbitals
64 @param SJ 6j symbol table
65 @param Lk Ladder table from previous iteration (nullptr on first)
66 @param fk Optional screening factors \f$ f_k \f$
67 @return \f$ L1^k_{mnij} \f$
68*/
69double L1(int k, const DiracSpinor &m, const DiracSpinor &n,
70 const DiracSpinor &i, const DiracSpinor &j,
71 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &excited,
72 const Angular::SixJTable &SJ,
73 const Coulomb::LkTable *const Lk = nullptr,
74 const std::vector<double> &fk = {});
75
76/*!
77 @brief Particle--hole ladder diagram L2.
78 @details
79 \f[
80 L2^k_{mnij} = \sum_{rc,ul} (-1)^{k+u+l+1} A^{klu}_{mjcrin}
81 \frac{Q^u_{cnir}\,(Q+L)^l_{mrcj}}{\epsilon_{cj} - \epsilon_{mr}}
82 \f]
83 Intermediate states: \f$ r \f$ runs over excited, \f$ c \f$ over core.
84 The diagram \f$ L3 \f$ is the exchange partner \f$ L3^k_{mnij} = L2^k_{nmji} \f$.
85
86 @param k Multipole rank
87 @param m,n Excited (particle) orbitals
88 @param i,j Core (hole) or valence orbitals
89 @param qk Coulomb \f$ Q^k \f$ integral table
90 @param core Core orbitals
91 @param excited Excited orbitals
92 @param SJ 6j symbol table
93 @param Lk Ladder table from previous iteration (nullptr on first)
94 @param fk Optional screening factors \f$ f_k \f$
95 @return \f$ L2^k_{mnij} \f$
96*/
97double L2(int k, const DiracSpinor &m, const DiracSpinor &n,
98 const DiracSpinor &i, const DiracSpinor &j,
99 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &core,
100 const std::vector<DiracSpinor> &excited, const Angular::SixJTable &SJ,
101 const Coulomb::LkTable *const Lk = nullptr,
102 const std::vector<double> &fk = {});
103
104/*!
105 @brief Exchange partner of L2; equals L2 with m,n and i,j swapped.
106 @details
107 \f[ L3^k_{mnij} = L2^k_{nmji} \f]
108*/
109inline double L3(int k, const DiracSpinor &m, const DiracSpinor &n,
110 const DiracSpinor &i, const DiracSpinor &j,
111 const Coulomb::QkTable &qk,
112 const std::vector<DiracSpinor> &core,
113 const std::vector<DiracSpinor> &excited,
114 const Angular::SixJTable &SJ,
115 const Coulomb::LkTable *const Lk = nullptr,
116 const std::vector<double> &fk = {}) {
117 return L2(k, n, m, j, i, qk, core, excited, SJ, Lk, fk);
118}
119
120/*!
121 @brief Core--core (hole--hole) ladder diagram L4.
122 @details
123 Intermediate states run over core orbitals only, making this the
124 hole--hole counterpart of the particle--particle diagram L1.
125 Typically small and omitted by default; enable via @p include_L4 in
126 Lkmnij().
127
128 @param k Multipole rank
129 @param m,n Excited (particle) orbitals
130 @param i,j Core (hole) or valence orbitals
131 @param qk Coulomb \f$ Q^k \f$ integral table
132 @param core Core orbitals
133 @param SJ 6j symbol table
134 @param Lk Ladder table from previous iteration (nullptr on first)
135 @param fk Optional screening factors \f$ f_k \f$
136 @return \f$ L4^k_{mnij} \f$
137*/
138double L4(int k, const DiracSpinor &m, const DiracSpinor &n,
139 const DiracSpinor &i, const DiracSpinor &j,
140 const Coulomb::QkTable &qk, const std::vector<DiracSpinor> &core,
141 const Angular::SixJTable &SJ,
142 const Coulomb::LkTable *const Lk = nullptr,
143 const std::vector<double> &fk = {});
144
145/*!
146 @brief Fills the ladder integral table for all required index combinations.
147 @details
148 Iterates over all combinations of excited pairs \f$ (m,n) \f$ and
149 orbitals in @p i_orbs, computing \f$ L^k_{mnib} \f$ and storing results
150 in @p lk.=
151
152 @param lk Output ladder table (written in place)
153 @param qk Coulomb \f$ Q^k \f$ integral table
154 @param excited Excited orbitals
155 @param core Core orbitals
156 @param i_orbs Orbitals for the \f$ i \f$ index
157 @param include_L4 Include core--core diagram L4
158 @param sjt 6j symbol table
159 @param print Print Qk info to screen
160 @param fk Optional screening factors \f$ f_k \f$
161*/
163 const std::vector<DiracSpinor> &excited,
164 const std::vector<DiracSpinor> &core,
165 const std::vector<DiracSpinor> &i_orbs, bool include_L4,
166 const Angular::SixJTable &sjt, bool print = true,
167 const std::vector<double> &fk = {});
168
169/*!
170 @brief Updates the ladder integral table with L(Q,Q) -> L(Q,Q+L)
171 @details
172 Iterates over all combinations of excited pairs \f$ (m,n) \f$ and
173 orbitals in @p i_orbs, computing \f$ L^k_{mnib} \f$ and storing results
174 in @p lk. Designed for iterative refinement: pass the previous iteration's
175 table as @p lk_prev.
176
177 @note Does not calculate any new integrals - assumes all already present.
178 Just updates them (based on iterative rule: L(Q,Q) -> L(Q,Q+L))
179
180 @param lk Output ladder table (written in place)
181 @param qk Coulomb \f$ Q^k \f$ integral table
182 @param excited Excited orbitals
183 @param core Core orbitals
184 @param i_orbs Orbitals for the \f$ i \f$ index
185 @param include_L4 Include core--core diagram L4
186 @param sjt 6j symbol table
187 @param lk_prev Ladder table from previous iteration
188 @param a_damp Damping factor [0,1) : 0 means no damping
189 @param print Print Qk info to screen
190 @param fk Optional screening factors \f$ f_k \f$
191*/
193 const std::vector<DiracSpinor> &excited,
194 const std::vector<DiracSpinor> &core,
195 const std::vector<DiracSpinor> &i_orbs, bool include_L4,
196 const Angular::SixJTable &sjt,
197 const Coulomb::LkTable *const lk_prev, double a_damp,
198 bool print, const std::vector<double> &fk);
199
200/*!
201 @brief Second-order (or ladder) correction to the valence energy.
202 @details
203 Computes the correlation energy shift
204 \f[
205 \delta\epsilon_v = \sum_{mnc} \frac{Q^k_{vmcn}\,L^k_{mncv}}{\epsilon_v
206 + \epsilon_c - \epsilon_m - \epsilon_n}
207 \f]
208 (schematic). When @p lk holds plain Coulomb integrals the result is the
209 MBPT(2) correction; when @p lk holds ladder integrals it is the full
210 ladder correction.
211
212 @param v Valence orbital
213 @param qk Coulomb \f$ Q^k \f$ integral table
214 @param lk \f$ Q^k \f$ or ladder \f$ L^k \f$ integral table
215 @param core Core orbitals
216 @param excited Excited orbitals
217 @param fk Optional screening factors \f$ f_k \f$
218 @param etak Optional enhancement factors \f$ \eta_k \f$
219 @return \f$ \delta\epsilon_v \f$
220*/
221template <typename Qintegrals, typename QorLintegrals>
222double de_valence(const DiracSpinor &v, const Qintegrals &qk,
223 const QorLintegrals &lk, const std::vector<DiracSpinor> &core,
224 const std::vector<DiracSpinor> &excited,
225 const std::vector<double> &fk = {},
226 const std::vector<double> &etak = {});
227
228/*!
229 @brief Second-order (or ladder) correction to the core energy.
230 @details
231 Sums the correlation energy shift over all core orbitals. When @p lk holds
232 plain Coulomb integrals the result is the MBPT(2) core correction; when
233 @p lk holds ladder integrals it is the ladder correction.
234
235 @param qk Coulomb \f$ Q^k \f$ integral table
236 @param lk \f$ Q^k \f$ or ladder \f$ L^k \f$ integral table
237 @param core Core orbitals
238 @param excited Excited orbitals
239 @return Total core correlation energy shift
240*/
241template <typename Qintegrals, typename QorLintegrals>
242double de_core(const Qintegrals &qk, const QorLintegrals &lk,
243 const std::vector<DiracSpinor> &core,
244 const std::vector<DiracSpinor> &excited);
245
246// template implementations:
247#include "Ladder.ipp"
248
249} // namespace MBPT
Lookup table for Wigner 6j symbols.
Definition SixJTable.hpp:68
Base class template to store Coulomb integrals, and similar. 3 specific cases (by template instantiat...
Definition QkTable.hpp:102
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
Many-body perturbation theory.
Definition CI_Integrals.hpp:10
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, const std::vector< double > &fk={})
Exchange partner of L2; equals L2 with m,n and i,j swapped.
Definition Ladder.hpp:109
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, bool print, const std::vector< double > &fk)
Fills the ladder integral table for all required index combinations.
Definition Ladder.cpp:257
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, const std::vector< double > &fk)
Particle–hole ladder diagram L2.
Definition Ladder.cpp:183
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, const std::vector< double > &fk)
Core–core (hole–hole) ladder diagram L4.
Definition Ladder.cpp:110
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.
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, const std::vector< double > &fk)
Full ladder integral summed over all diagrams.
Definition Ladder.cpp:12
double de_valence(const DiracSpinor &v, const Qintegrals &qk, const QorLintegrals &lk, const std::vector< DiracSpinor > &core, const std::vector< DiracSpinor > &excited, const std::vector< double > &fk={}, const std::vector< double > &etak={})
Second-order (or ladder) correction to the valence energy.
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, const std::vector< double > &fk)
Particle–particle ladder diagram L1.
Definition Ladder.cpp:31
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 > &i_orbs, bool include_L4, const Angular::SixJTable &sjt, const Coulomb::LkTable *const lk_prev, double a_damp, bool print, const std::vector< double > &fk)
Updates the ladder integral table with L(Q,Q) -> L(Q,Q+L)
Definition Ladder.cpp:314