24#include <nda/linalg/eigh.hpp>
28#include "lattice_utility.hpp"
33#include "chi_imtime.hpp"
37 e_k_t rho_k_from_g_wk(g_wk_cvt g_wk) {
40 auto kmesh = std::get<1>(g_wk.mesh());
42 e_k_t rho_k(kmesh, g_wk.target_shape());
45 auto arr = mpi_view(kmesh);
46#pragma omp parallel for
47 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
49 auto g_w = g_wk[_, k];
50 rho_k[k] = density(g_w);
53 rho_k = mpi::all_reduce(rho_k);
57 e_k_t rho_k_from_g_wk(g_Dwk_cvt g_wk) {
60 auto wmesh = std::get<0>(g_wk.mesh());
61 auto kmesh = std::get<1>(g_wk.mesh());
63 e_k_t rho_k(kmesh, g_wk.target_shape());
66 auto arr = mpi_view(kmesh);
67#pragma omp parallel for
68 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
70 auto g_w = make_gf<dlr_imfreq>({wmesh}, g_wk.target());
72 rho_k[k] = density(make_gf_dlr(g_w));
75 rho_k = mpi::all_reduce(rho_k);
79 template<
typename W_t,
typename g_t>
80 auto gw_dynamic_sigma_impl(W_t W_tr, g_t g_tr) {
82 auto Wtm = std::get<0>(W_tr.mesh());
83 auto gtm = std::get<0>(g_tr.mesh());
85 if (Wtm.size() != gtm.size() || Wtm.beta() != gtm.beta()) TRIQS_RUNTIME_ERROR <<
"gw_sigma_tr: tau meshes are not the same.\n";
87 if (Wtm.statistic() != Boson || gtm.statistic() != Fermion) TRIQS_RUNTIME_ERROR <<
"gw_sigma_tr: statistics are incorrect.\n";
89 if (std::get<1>(W_tr.mesh()) != std::get<1>(g_tr.mesh())) TRIQS_RUNTIME_ERROR <<
"gw_sigma_tr: real-space meshes are not the same.\n";
91 auto sigma_tr = make_gf(g_tr);
94 auto arr = mpi_view(g_tr.mesh());
95#pragma omp parallel for
96 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
97 auto &[t, r] = arr[idx];
99 for (
auto [a, b, c, d] : W_tr.target_indices()) { sigma_tr[t, r](a, b) += -W_tr[t, r](a, c, d, b) * g_tr[t, r](c, d); }
102 sigma_tr = mpi::all_reduce(sigma_tr);
106 g_tr_t gw_dynamic_sigma(chi_tr_cvt W_tr, g_tr_cvt g_tr) {
107 return gw_dynamic_sigma_impl(W_tr, g_tr);
110 g_Dtr_t gw_dynamic_sigma(chi_Dtr_cvt W_tr, g_Dtr_cvt g_tr) {
111 return gw_dynamic_sigma_impl(W_tr, g_tr);
115 e_r_t hartree_sigma(chi_k_cvt v_k, e_r_cvt rho_r) {
117 e_r_t sigma_r(rho_r.mesh(), rho_r.target_shape());
120 for (
auto [a, b, c, d] : v_k.target_indices()) { sigma_r[{0, 0, 0}](a, b) += v_k[{0, 0, 0}](a, b, c, d) * rho_r[{0, 0, 0}](c, d); }
125 e_k_t hartree_sigma(chi_k_cvt v_k, g_wk_cvt g_wk) {
127 if (v_k.mesh() != std::get<1>(g_wk.mesh())) TRIQS_RUNTIME_ERROR <<
"hartree_sigma: k-space meshes are not the same.\n";
130 auto kmesh = std::get<1>(g_wk.mesh());
132 e_k_t sigma_k(kmesh, g_wk.target_shape());
135 auto arr = mpi_view(kmesh);
136#pragma omp parallel for
137 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
140 for (
auto q : kmesh) {
142 auto g_w = g_wk[_, k + q];
143 auto dens = density(gf{g_w});
145 for (
auto [a, b, c, d] : v_k.target_indices()) { sigma_k[k](a, b) += v_k[q](a, b, c, d) * dens(c, d) / kmesh.size(); }
148 sigma_k = mpi::all_reduce(sigma_k);
152 e_r_t fock_sigma(chi_r_cvt v_r, e_r_cvt rho_r) {
154 if (v_r.mesh() != rho_r.mesh()) TRIQS_RUNTIME_ERROR <<
"fock_sigma: r-space meshes are not the same.\n";
156 auto rmesh = rho_r.mesh();
158 e_r_t sigma_r(rmesh, rho_r.target_shape());
161 auto arr = mpi_view(rmesh);
162#pragma omp parallel for
163 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
166 for (
auto [a, b, c, d] : v_r.target_indices()) { sigma_r[r](a, b) += -v_r[r](a, c, d, b) * rho_r[r](d, c); }
168 sigma_r = mpi::all_reduce(sigma_r);
172 template<
typename g_t>
173 e_k_t fock_sigma_impl(chi_k_cvt v_k, g_t g_wk) {
174 auto v_r = make_gf_from_fourier(v_k);
175 auto rho_k = rho_k_from_g_wk(g_wk);
176 auto rho_r = make_gf_from_fourier(rho_k);
177 auto sigma_fock_r = fock_sigma(v_r, rho_r);
178 auto sigma_fock_k = make_gf_from_fourier(sigma_fock_r);
182 e_k_t fock_sigma(chi_k_cvt v_k, g_wk_cvt g_wk) {
183 return fock_sigma_impl(v_k, g_wk);
185 e_k_t fock_sigma(chi_k_cvt v_k, g_Dwk_cvt g_wk) {
186 return fock_sigma_impl(v_k, g_wk);
189 e_k_t gw_sigma(chi_k_cvt v_k, g_wk_cvt g_wk) {
190 return fock_sigma(v_k, g_wk);
192 e_k_t gw_sigma(chi_k_cvt v_k, g_Dwk_cvt g_wk) {
193 return fock_sigma(v_k, g_wk);
196 template<
typename W_dyn_t,
typename W_const_t,
typename g_t>
197 auto gw_sigma_impl(W_dyn_t W_dyn_wk, W_const_t W_const_k, g_t g_wk) {
199 auto Wwm = std::get<0>(W_dyn_wk.mesh());
200 auto gwm = std::get<0>(g_wk.mesh());
202 if (Wwm.beta() != gwm.beta())
203 TRIQS_RUNTIME_ERROR <<
"gw_sigma: inverse temperatures are not the same.\n";
204 if (Wwm.statistic() != Boson || gwm.statistic() != Fermion)
205 TRIQS_RUNTIME_ERROR <<
"gw_sigma: statistics are incorrect.\n";
206 if (std::get<1>(W_dyn_wk.mesh()) != std::get<1>(g_wk.mesh()))
207 TRIQS_RUNTIME_ERROR <<
"gw_sigma: k-space meshes are not the same.\n";
210 auto g_wr = fourier_wk_to_wr(g_wk);
211 auto g_tr = fourier_wr_to_tr(g_wr);
212 auto W_dyn_wr = chi_wr_from_chi_wk(W_dyn_wk);
213 auto W_dyn_tr = chi_tr_from_chi_wr(W_dyn_wr);
215 auto sigma_dyn_tr = gw_dynamic_sigma(W_dyn_tr, g_tr);
218 auto sigma_fock_k = fock_sigma(W_const_k, g_wk);
222 auto sigma_wr = fourier_tr_to_wr(sigma_dyn_tr);
223 auto sigma_wk = fourier_wr_to_wk(sigma_wr);
224 for (
auto w : gwm) sigma_wk[w, _] += sigma_fock_k;
229 g_wk_t gw_sigma(chi_wk_cvt W_wk, g_wk_cvt g_wk) {
230 auto [W_dyn_wk, W_const_k] = split_into_dynamic_wk_and_constant_k(W_wk);
231 return gw_sigma_impl(W_dyn_wk, W_const_k, g_wk);
234 g_Dwk_t gw_sigma(chi_Dwk_cvt W_wk, chi_k_cvt v_k, g_Dwk_cvt g_wk) {
235 auto wmesh = std::get<0>(W_wk.mesh());
237 chi_Dwk_t W_dyn_wk(W_wk.mesh(), W_wk.target_shape());
238 for (
auto w : wmesh) W_dyn_wk[w, _] = W_wk[w,_] - v_k;
240 return gw_sigma_impl(W_dyn_wk, v_k, g_wk);
247 g_f_t g0w_dynamic_sigma(
double mu,
double beta, e_k_cvt e_k, chi_fk_cvt W_fk, chi_k_cvt v_k,
double delta, mesh::brzone::value_t kpoint) {
249 if (std::get<1>(W_fk.mesh()) != e_k.mesh()) TRIQS_RUNTIME_ERROR <<
"g0w_sigma: k-space meshes are not the same.\n";
250 if (e_k.mesh() != v_k.mesh()) TRIQS_RUNTIME_ERROR <<
"g0w_sigma: k-space meshes are not the same.\n";
252 auto fmesh = std::get<0>(W_fk.mesh());
253 auto kmesh = e_k.mesh();
254 int nb = e_k.target().shape()[0];
256 std::complex<double> idelta(0.0, delta);
258 g_f_t sigma_f(fmesh, e_k.target_shape());
261 for (
auto q : kmesh) {
262 auto qpoint = mesh::brzone::value_t{q};
263 auto kpqpoint = qpoint + kpoint;
264 auto kpqvec = std::array<double, 3>{kpqpoint(0), kpqpoint(1), kpqpoint(2)};
266 array<std::complex<double>, 2> e_kq_mat(e_k(kpqvec) - mu);
267 auto eig_kq = linalg::eigh(e_kq_mat);
268 auto ekq = eig_kq.first;
269 auto Ukq = eig_kq.second;
271 for (
int l : range(nb)) {
273 for (
auto f : fmesh) {
275 for (
auto fp : fmesh) {
277 auto num = bose(fp * beta) + fermi(ekq(l) * beta);
278 auto den = f + idelta + fp - ekq(l);
280 for (
auto [a, b] : sigma_f.target_indices()) {
281 auto W_spec = -1.0 / M_PI * (W_fk[fp, q](a, a, b, b) - v_k[q](a, a, b, b)).imag();
282 sigma_f[f](a, b) = sigma_f[f](a, b)
283 + Ukq(a, l) * dagger(Ukq)(l, b) * (W_spec * num / den * fmesh.delta() / kmesh.size());
293 g_fk_t g0w_dynamic_sigma(
double mu,
double beta, e_k_cvt e_k, chi_fk_cvt W_fk, chi_k_cvt v_k,
double delta, mesh::brzone kmesh) {
295 if (std::get<1>(W_fk.mesh()) != e_k.mesh()) TRIQS_RUNTIME_ERROR <<
"g0w_sigma: k-space meshes are not the same.\n";
296 if (e_k.mesh() != v_k.mesh()) TRIQS_RUNTIME_ERROR <<
"g0w_sigma: k-space meshes are not the same.\n";
298 auto fmesh = std::get<0>(W_fk.mesh());
300 g_fk_t sigma_fk({fmesh, kmesh}, e_k.target_shape());
303 auto arr = mpi_view(kmesh);
304#pragma omp parallel for
305 for (
unsigned int kidx = 0; kidx < arr.size(); kidx++) {
307 auto kpoint = mesh::brzone::value_t{k};
308 auto sigma_f = g0w_dynamic_sigma(mu, beta, e_k, W_fk, v_k, delta, kpoint);
309 for (
auto f : fmesh) { sigma_fk[f, k] = sigma_f[f]; }
312 sigma_fk = mpi::all_reduce(sigma_fk);
316 g_fk_t g0w_dynamic_sigma(
double mu,
double beta, e_k_cvt e_k, chi_fk_cvt W_fk, chi_k_cvt v_k,
double delta) {
317 return g0w_dynamic_sigma(mu, beta, e_k, W_fk, v_k, delta, e_k.mesh());
322 array<std::complex<double>, 2> g0w_sigma(
double mu,
double beta, e_k_cvt e_k, chi_k_cvt v_k, mesh::brzone::value_t kpoint) {
324 if (e_k.mesh() != v_k.mesh()) TRIQS_RUNTIME_ERROR <<
"g0w_sigma: k-space meshes are not the same.\n";
326 auto kmesh = e_k.mesh();
327 int nb = e_k.target().shape()[0];
329 array<std::complex<double>, 2> sigma_k(nb ,nb);
332 for (
auto q : kmesh) {
333 auto qpoint = mesh::brzone::value_t{q};
334 auto kpqpoint = qpoint + kpoint;
335 auto kpqvec = std::array<double, 3>{kpqpoint(0), kpqpoint(1), kpqpoint(2)};
337 array<std::complex<double>, 2> e_kq_mat(e_k(kpqvec) - mu);
338 auto eig_kq = linalg::eigh(e_kq_mat);
339 auto ekq = eig_kq.first;
340 auto Ukq = eig_kq.second;
342 for (
int l : range(nb)) {
343 for (
int a : range(nb)) {
344 for (
int b : range(nb)) {
345 sigma_k(a, b) = sigma_k(a, b) - Ukq(a, l) * dagger(Ukq)(l, b) * v_k[q](a, a, b, b) * fermi(ekq(l) * beta) / kmesh.size();
354 e_k_t g0w_sigma(
double mu,
double beta, e_k_cvt e_k, chi_k_cvt v_k, mesh::brzone kmesh) {
356 e_k_t sigma_k(kmesh, e_k.target_shape());
359 auto arr = mpi_view(kmesh);
360#pragma omp parallel for
361 for (
unsigned int kidx = 0; kidx < arr.size(); kidx++) {
363 auto kpoint = mesh::brzone::value_t{k};
364 sigma_k[k] = g0w_sigma(mu, beta, e_k, v_k, kpoint);
367 sigma_k = mpi::all_reduce(sigma_k);
371 e_k_t g0w_sigma(
double mu,
double beta, e_k_cvt e_k, chi_k_cvt v_k) {
372 return g0w_sigma(mu, beta, e_k, v_k, e_k.mesh());
377 g_f_t g0w_sigma(
double mu,
double beta, e_k_cvt e_k, chi_fk_cvt W_fk, chi_k_cvt v_k,
double delta, mesh::brzone::value_t kpoint) {
378 auto sigma_stat_k = g0w_sigma(mu, beta, e_k, v_k, kpoint);
379 auto sigma_dyn_fk = g0w_dynamic_sigma(mu, beta, e_k, W_fk, v_k, delta, kpoint);
381 auto fmesh = std::get<0>(W_fk.mesh());
382 g_f_t sigma_fk(fmesh, e_k.target_shape());
384 for (
auto f : fmesh) { sigma_fk[f] = sigma_stat_k + sigma_dyn_fk[f]; }
389 g_fk_t g0w_sigma(
double mu,
double beta, e_k_cvt e_k, chi_fk_cvt W_fk, chi_k_cvt v_k,
double delta, mesh::brzone kmesh) {
390 auto sigma_stat_k = g0w_sigma(mu, beta, e_k, v_k, kmesh);
391 auto sigma_dyn_fk = g0w_dynamic_sigma(mu, beta, e_k, W_fk, v_k, delta, kmesh);
392 auto sigma_fk = add_dynamic_and_static(sigma_dyn_fk, sigma_stat_k);
396 g_fk_t g0w_sigma(
double mu,
double beta, e_k_cvt e_k, chi_fk_cvt W_fk, chi_k_cvt v_k,
double delta) {
397 return g0w_sigma(mu, beta, e_k, W_fk, v_k, delta, e_k.mesh());