24#include <triqs/utility/timer.hpp>
25#include <triqs/utility/timestamp.hpp>
28#include "../fourier/fourier.hpp"
29#include "../linalg.hpp"
32#include "chi_imfreq.hpp"
38using fourier::_fourier_plan;
39using fourier::_fourier_with_plan;
63chi_wnr_t chi0r_from_gr_PH(
int nw,
int nn, g_wr_cvt g_nr) {
65 mpi::communicator comm;
67 triqs::utility::timer t_alloc, t_calc, t_mpi_all_reduce;
71 int nb = g_nr.target().shape()[0];
72 auto const &rmesh = std::get<1>(g_nr.mesh());
74 double beta = std::get<0>(g_nr.mesh()).beta();
76 auto wmesh = mesh::imfreq{beta, Boson, nw};
77 auto nmesh = mesh::imfreq{beta, Fermion, nn};
80 chi0r_t chi0_wnr{{wmesh, nmesh, rmesh}, {nb, nb, nb, nb}};
84 auto chi_target = chi0_wnr.target();
85 auto g_target = g_nr.target();
87 auto arr = mpi_view(rmesh);
89 std::cout <<
"rank " << comm.rank() <<
" has arr.size() = "
90 << arr.size() <<
" of " << rmesh.size() << std::endl;
93#pragma omp parallel for
94 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
98 make_gf<prod<imfreq, imfreq>>({wmesh, nmesh}, chi_target);
99 auto g_pr_n = make_gf<imfreq>(nmesh, g_target);
100 auto g_mr_n = make_gf<imfreq>(nmesh, g_target);
105 g_mr_n = g_nr(_, -r);
109 for (
auto n : nmesh) chi0_wn[w, n](a, b, c, d) << -beta * g_pr_n(n)(d, a) * g_mr_n(n + w)(b, c);
112 chi0_wnr[_, _, r] = chi0_wn;
119 t_mpi_all_reduce.start();
130 for (
auto n : nmesh) chi0_wnr[w, n, _] = mpi::all_reduce(chi0_wnr[w, n, _]);
132 t_mpi_all_reduce.stop();
134 std::cout <<
"--> chi0r_from_gr_PH: alloc " << double(t_alloc)
135 <<
" s, calc " << double(t_calc) <<
" s, mpi::all_reduce "
136 << double(t_mpi_all_reduce) <<
" s." << std::endl;
141chi_nr_t chi0_nr_from_gr_PH_at_specific_w(
int nw_index,
int nn, g_wr_cvt g_nr) {
145 int nb = g_nr.target().shape()[0];
146 auto &rmesh = std::get<1>(g_nr.mesh());
148 double beta = std::get<0>(g_nr.mesh()).beta();
149 auto w = matsubara_freq{nw_index, beta, Boson};
151 auto nmesh = mesh::imfreq{beta, Fermion, nn};
152 chi_nr_t chi0_nr{{nmesh, rmesh}, {nb, nb, nb, nb}};
155 auto chi_target = chi0_nr.target();
156 auto g_target = g_nr.target();
158 auto arr = mpi_view(rmesh);
159#pragma omp parallel for
160 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
163 auto chi0_n = make_gf<imfreq>(nmesh, chi_target);
164 auto g_pr_n = make_gf<imfreq>(nmesh, g_target);
165 auto g_mr_n = make_gf<imfreq>(nmesh, g_target);
170 g_mr_n = g_nr(_, -r);
173 for (
auto n : nmesh) chi0_n[n](a, b, c, d) << -beta * g_pr_n(n)(d, a) * g_mr_n(n + w)(b, c);
176 chi0_nr[_, r] = chi0_n;
179 for (
auto n : nmesh) chi0_nr[n, _] = mpi::all_reduce(chi0_nr[n, _]);
188chi_wnr_t chi0r_from_gr_PH_nompi(
int nw,
int nn, g_wr_cvt g_nr) {
190 triqs::utility::timer t_alloc, t_calc, t_mpi_all_reduce;
194 int nb = g_nr.target().shape()[0];
195 auto const &rmesh = std::get<1>(g_nr.mesh());
197 double beta = std::get<0>(g_nr.mesh()).beta();
199 auto wmesh = mesh::imfreq{beta, Boson, nw};
200 auto nmesh = mesh::imfreq{beta, Fermion, nn};
203 chi0r_t chi0_wnr{{wmesh, nmesh, rmesh}, {nb, nb, nb, nb}};
207 auto chi_target = chi0_wnr.target();
208 auto g_target = g_nr.target();
212#pragma omp parallel for
213 for (
unsigned int idx = 0; idx < rmesh.size(); idx++) {
214 auto r = *std::next(rmesh.begin(), idx);
217 make_gf<prod<imfreq, imfreq>>({wmesh, nmesh}, chi_target);
218 auto g_pr_n = make_gf<imfreq>(nmesh, g_target);
219 auto g_mr_n = make_gf<imfreq>(nmesh, g_target);
224 g_mr_n = g_nr(_, -r);
228 for (
auto n : nmesh) chi0_wn[w, n](a, b, c, d) << -beta * g_pr_n(n)(d, a) * g_mr_n(n + w)(b, c);
231 chi0_wnr[_, _, r] = chi0_wn;
238 t_mpi_all_reduce.start();
240 t_mpi_all_reduce.stop();
242 std::cout <<
"--> chi0r_from_gr_PH: alloc " << double(t_alloc)
243 <<
" s, calc " << double(t_calc) <<
" s, mpi::all_reduce "
244 << double(t_mpi_all_reduce) <<
" s." << std::endl;
254gf<imfreq, tensor_valued<4>> chi0_n_from_g_wk_PH(mesh::imfreq::mesh_point_t w, mesh::brzone::mesh_point_t q, mesh::imfreq fmesh, g_wk_cvt g_wk) {
256 int nb = g_wk.target().shape()[0];
257 auto const &kmesh = std::get<1>(g_wk.mesh());
259 double beta = fmesh.beta();
261 gf<imfreq, tensor_valued<4>> chi0_n{fmesh, {nb, nb, nb, nb}};
267 for (
auto n : fmesh) {
268 for (
auto k : kmesh) {
269 auto g_da = g_wk[n.value(), k.index()];
270 auto g_bc = g_wk(n + w, k - q);
271 for (
auto a : range(nb))
272 for (
auto b : range(nb))
273 for (
auto c : range(nb))
274 for (
auto d : range(nb))
275 chi0_n[n](a, b, c, d) -= g_da(d, a) * g_bc(b, c);
279 chi0_n *= beta / kmesh.size();
290gf<imfreq, tensor_valued<4>> chi0_n_from_e_k_sigma_w_PH(mesh::imfreq::mesh_point_t w, mesh::brzone::mesh_point_t q, mesh::imfreq fmesh,
double mu,
291 e_k_cvt e_k, g_w_cvt sigma_w) {
293 int nb = e_k.target().shape()[0];
294 auto kmesh = e_k.mesh();
296 auto fmesh_large = sigma_w.mesh();
298 assert(fmesh.size() < fmesh_large.size());
300 double beta = fmesh.beta();
301 auto I = nda::eye<ek_vt::scalar_t>(e_k.target_shape()[0]);
303 gf<imfreq, tensor_valued<4>> chi0_n{fmesh, {nb, nb, nb, nb}};
305 for (
auto k : kmesh) {
306 for (
auto n : fmesh) {
308 auto g_da = nda::linalg::inv((n + mu) * I - e_k[k] - sigma_w[matsubara_freq(n)]);
309 auto g_bc = nda::linalg::inv((n + mu) * I - e_k[k - q] - sigma_w[n + w]);
311 for (
auto a : range(nb))
312 for (
auto b : range(nb))
313 for (
auto c : range(nb))
314 for (
auto d : range(nb))
315 chi0_n[n](a, b, c, d) -= g_da(d, a) * g_bc(b, c);
319 chi0_n *= beta / kmesh.size();
326chi_wnk_t chi0q_from_g_wk_PH(
int nw,
int nn, g_wk_cvt g_wk) {
328 auto const &kmesh = std::get<1>(g_wk.mesh());
330 int nb = g_wk.target().shape()[0];
331 double beta = std::get<0>(g_wk.mesh()).beta();
333 mesh::imfreq bmesh{beta, Boson, nw};
334 mesh::imfreq fmesh{beta, Fermion, nn};
336 chi0q_t chi0_wnk({bmesh, fmesh, kmesh}, {nb, nb, nb, nb});
339 for (
auto [w, q] : prod{bmesh, kmesh}) { chi0_wnk[w, _, q] = chi0_n_from_g_wk_PH(w, q, fmesh, g_wk); }
365chi_wnr_t chi0r_from_chi0q(chi_wnk_cvt chi_wnk) {
368 auto target = chi_wnk.target();
371 auto &bmesh = std::get<0>(chi_wnk.mesh());
372 auto &fmesh = std::get<1>(chi_wnk.mesh());
373 auto &kmesh = std::get<2>(chi_wnk.mesh());
374 auto rmesh = make_adjoint_mesh(kmesh);
376 chi_wnr_t chi_wnr({bmesh, fmesh, rmesh}, chi_wnk.target_shape());
378 auto w0 = *bmesh.begin();
379 auto n0 = *fmesh.begin();
380 auto p = _fourier_plan<0>(gf_const_view(chi_wnk[w0, n0, _]),
381 gf_view(chi_wnr[w0, n0, _]));
383 auto arr = mpi_view(prod{bmesh, fmesh});
384#pragma omp parallel for shared(kmesh, rmesh)
385 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
386 auto &[w, n] = arr[idx];
388 auto chi_r = make_gf<cyclat>(rmesh, target);
389 auto chi_k = make_gf<brzone>(kmesh, target);
392 chi_k = chi_wnk[w, n, _];
394 _fourier_with_plan<0>(gf_const_view(chi_k), gf_view(chi_r), p);
397 chi_wnr[w, n, _] = chi_r;
404 for (
auto n : fmesh) chi_wnr[w, n, _] = mpi::all_reduce(chi_wnr[w, n, _]);
428chi_wnk_t chi0q_from_chi0r(chi_wnr_cvt chi_wnr) {
430 triqs::utility::timer t_alloc, t_calc, t_mpi_all_reduce;
433 auto target = chi_wnr.target();
436 auto &bmesh = std::get<0>(chi_wnr.mesh());
437 auto &fmesh = std::get<1>(chi_wnr.mesh());
438 auto &rmesh = std::get<2>(chi_wnr.mesh());
439 auto kmesh = make_adjoint_mesh(rmesh);
442 chi_wnk_t chi_wnk({bmesh, fmesh, kmesh}, chi_wnr.target_shape());
444 auto w0 = *bmesh.begin();
445 auto n0 = *fmesh.begin();
446 auto p = _fourier_plan<0>(gf_const_view(chi_wnr[w0, n0, _]),
447 gf_view(chi_wnk[w0, n0, _]));
452 auto arr = mpi_view(prod{bmesh, fmesh});
453#pragma omp parallel for
454 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
455 auto &[w, n] = arr[idx];
457 auto chi_r = make_gf<cyclat>(rmesh, target);
458 auto chi_k = make_gf<brzone>(kmesh, target);
461 chi_r = chi_wnr[w, n, _];
463 _fourier_with_plan<0>(gf_const_view(chi_r), gf_view(chi_k), p);
466 chi_wnk[w, n, _] = chi_k;
470 t_mpi_all_reduce.start();
476 for (
auto n : fmesh) chi_wnk[w, n, _] = mpi::all_reduce(chi_wnk[w, n, _]);
478 t_mpi_all_reduce.stop();
480 std::cout <<
"--> chi0q_from_chi0r: alloc " << double(t_alloc)
481 <<
" s, calc " << double(t_calc) <<
" s, mpi::all_reduce "
482 << double(t_mpi_all_reduce) <<
" s." << std::endl;
489chi_wk_t chi0q_sum_nu(chi_wnk_cvt chi_wnk) {
492 auto &wmesh = std::get<0>(chi_wnk.mesh());
493 auto &nmesh = std::get<1>(chi_wnk.mesh());
494 auto &kmesh = std::get<2>(chi_wnk.mesh());
496 chi_wk_t chi_wk({wmesh, kmesh}, chi_wnk.target_shape());
499 double beta = wmesh.beta();
501 auto arr = mpi_view(chi_wk.mesh());
502#pragma omp parallel for
503 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
504 auto &[w, k] = arr[idx];
506 for (
auto n : nmesh) chi_wk[w, k] += chi_wnk[w, n, k];
507 chi_wk[w, k] /= beta * beta;
512 chi_wk = mpi::all_reduce(chi_wk);
518chi_wk_t chi0q_sum_nu_tail_corr_PH(chi_wnk_cvt chi_wnk) {
523 auto &wmesh = std::get<0>(chi_wnk.mesh());
524 auto &nmesh = std::get<1>(chi_wnk.mesh());
525 auto &qmesh = std::get<2>(chi_wnk.mesh());
527 chi_wk_t chi_wk({wmesh, qmesh}, chi_wnk.target_shape());
529 int nb = chi_wnk.target_shape()[0];
530 double beta = wmesh.beta();
532 auto chi_target = chi_wnk.target();
537 auto arr = mpi_view(chi_wk.mesh());
538#pragma omp parallel for
539 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
540 auto &[w, q] = arr[idx];
542 auto chi = make_gf<imfreq>(nmesh, chi_target);
543 array<std::complex<double>, 4> dens(nb, nb, nb, nb);
546 chi = chi_wnk[w, _, q];
548 for (
auto a : range(nb)) {
549 for (
auto b : range(nb)) {
550 for (
auto c : range(nb)) {
551 for (
auto d : range(nb)) {
552 auto chi_abcd = slice_target_to_scalar(chi, a, b, c, d);
554 dens(a, b, c, d) = density(chi_abcd) / beta;
564 chi_wk = mpi::all_reduce(chi_wk);
570chi_w_t chi0q_sum_nu_q(chi_wnk_cvt chi_wnk) {
572 auto const &[mesh_b, mesh_f, mesh_k] = chi_wnk.mesh();
573 chi_w_t chi_w(mesh_b, chi_wnk.target_shape());
575 for (
auto [w, n, k] : chi_wnk.mesh()) chi_w[w] += chi_wnk[w, n, k];
577 double nk = mesh_k.size();
578 double beta = mesh_f.beta();
579 chi_w = chi_w / nk / (beta * beta);
623chi_kwnn_t chiq_from_chi0q_and_gamma_PH(chi_wnk_cvt chi0_wnk, chi_wnn_cvt gamma_ph_wnn) {
627 auto &mb = std::get<0>(chi0_wnk.mesh());
628 auto &mf = std::get<1>(chi0_wnk.mesh());
629 auto &mbz = std::get<2>(chi0_wnk.mesh());
631 chi_kwnn_t chi_kwnn({mbz, mb, mf, mf}, chi0_wnk.target_shape());
633#pragma omp parallel for
634 for (
unsigned int idx = 0; idx < mbz.size(); idx++) {
635 auto k = *std::next(mbz.begin(), idx);
637 auto chi0 = make_gf<g2_nn_t::mesh_t>({mf, mf}, chi0_wnk.target());
638 auto I = identity<Channel_t::PH>(chi0);
643 for (
auto n : mf) { chi0[n, n] = chi0_wnk[w, n, k]; }
646 auto denom = chi_nn_t{I - product<Channel_t::PH>(chi0, gamma_ph_wnn[w, _, _])};
649 chi_nn_t chi = product<Channel_t::PH>(inverse<Channel_t::PH>(denom), chi0);
652 chi_kwnn[k, w, _, _] = chi;
661chi_kw_t chiq_sum_nu_from_chi0q_and_gamma_and_L_wn_PH(chi_wnk_cvt chi0_wnk, chi_wnn_cvt gamma_ph_wnn, chi_nn_cvt L_wn) {
665 mpi::communicator comm;
667 auto target_shape = chi0_wnk.target_shape();
669 auto &bmesh = std::get<0>(chi0_wnk.mesh());
670 auto &fmesh = std::get<1>(chi0_wnk.mesh());
671 auto &kmesh = std::get<2>(chi0_wnk.mesh());
673 chi_kw_t chi_kw({kmesh, bmesh}, target_shape);
675 auto arr = mpi_view(chi_kw.mesh());
676 std::cout <<
"DBSE rank " << comm.rank() <<
" of " << comm.size() <<
" has "
677 << arr.size() <<
" jobs." << std::endl;
679 triqs::utility::timer t;
682#pragma omp parallel for
683 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
684 auto &[k, w] = arr[idx];
691 chi_w_t chi0_n(fmesh, target_shape);
694 chi0_n = chi0_wnk[w, _, k];
701 chi_nn_t chi0_nn({fmesh, fmesh}, target_shape);
704 for (
auto n : fmesh) chi0_nn[n, n] = chi0_n[n];
711 auto I = identity<Channel_t::PH>(chi0_nn);
713 chi_nn_t gamma_nn({fmesh, fmesh}, target_shape);
716 gamma_nn = gamma_ph_wnn[w, _, _];
719 auto denom = chi_nn_t{I - product<Channel_t::PH>(chi0_nn, gamma_nn)};
722 auto chi = chi_nn_t{product<Channel_t::PH>(inverse<Channel_t::PH>(denom), chi0_nn)};
730 array<std::complex<double>, 4> tr_chi(target_shape);
731 tr_chi = scalar_product_PH(L_wn[w, _], chi, L_wn[w, _]);
767 chi_kw[k, w] = tr_chi;
773 if(comm.rank() == 0 && omp_get_thread_num() == 0) {
775 int Nomp = omp_get_num_threads();
776 int N = int(floor(arr.size() /
double(Nomp)));
779 int done_percent = (N == 0) ? 100 : int(floor(100 * double(idx + 1) / N));
781 std::cout <<
"DBSE " << triqs::utility::timestamp() <<
" "
782 << std::setfill(
' ') << std::setw(3) << done_percent <<
"% "
783 <<
"ETA " << triqs::utility::estimate_time_left(N, idx, t)
785 << std::setfill(
' ') << std::setw(5) << int(idx)
786 <<
" of approx " << N <<
" jobs/thread/rank." << std::endl;
791 chi_kw = mpi::all_reduce(chi_kw);
794 if(comm.rank() == 0 )
795 std::cout <<
"DBSE TIME: " << double(t) <<
" s" << std::endl;
802chi_kw_t chiq_sum_nu_from_chi0q_and_gamma_PH(chi_wnk_cvt chi0_wnk, chi_wnn_cvt gamma_ph_wnn) {
808 auto target_shape = chi0_wnk.target_shape();
810 auto &bmesh = std::get<0>(chi0_wnk.mesh());
811 auto &fmesh = std::get<1>(chi0_wnk.mesh());
812 auto &kmesh = std::get<2>(chi0_wnk.mesh());
814 double beta = fmesh.beta();
816 chi_kw_t chi_kw({kmesh, bmesh}, target_shape);
818 auto arr = mpi_view(chi_kw.mesh());
819 std::cout <<
"BSE rank " << c.rank() <<
" of " << c.size() <<
" has "
820 << arr.size() <<
" jobs." << std::endl;
822 triqs::utility::timer t;
825#pragma omp parallel for
826 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
827 auto &[k, w] = arr[idx];
834 chi_w_t chi0_n(fmesh, target_shape);
837 chi0_n = chi0_wnk[w, _, k];
844 chi_nn_t chi0_nn({fmesh, fmesh}, target_shape);
847 for (
auto n : fmesh) chi0_nn[n, n] = chi0_n[n];
854 auto I = identity<Channel_t::PH>(chi0_nn);
856 chi_nn_t gamma_nn({fmesh, fmesh}, target_shape);
859 gamma_nn = gamma_ph_wnn[w, _, _];
862 auto denom = chi_nn_t{I - product<Channel_t::PH>(chi0_nn, gamma_nn)};
865 auto chi = chi_nn_t{product<Channel_t::PH>(inverse<Channel_t::PH>(denom), chi0_nn)};
873 array<std::complex<double>, 4> tr_chi(target_shape);
876 for (
auto n1 : fmesh)
877 for (
auto n2 : fmesh) tr_chi += chi[n1, n2];
879 tr_chi /= beta * beta;
887 chi_kw[k, w] = tr_chi;
893 if(c.rank() == 0 && omp_get_thread_num() == 0) {
895 int Nomp = omp_get_num_threads();
896 int N = int(floor(arr.size() /
double(Nomp)));
899 int done_percent = (N == 0) ? 100 : int(floor(100 * double(idx + 1) / N));
901 std::cout <<
"BSE " << triqs::utility::timestamp() <<
" "
902 << std::setfill(
' ') << std::setw(3) << done_percent <<
"% "
903 <<
"ETA " << triqs::utility::estimate_time_left(N, idx, t)
905 << std::setfill(
' ') << std::setw(5) << int(idx)
906 <<
" of approx " << N <<
" jobs/thread/rank." << std::endl;
911 chi_kw = mpi::all_reduce(chi_kw);
915 std::cout <<
"BSE TIME: " << double(t) <<
" s" << std::endl;
922gf<prod<brzone, imfreq>, tensor_valued<4>>
923chiq_sum_nu_from_g_wk_and_gamma_PH(gk_iw_t g_wk, g2_iw_vt gamma_ph_wnn,
928 auto target = gamma_ph_wnn.target();
929 auto const &kmesh = std::get<1>(g_wk.mesh());
930 auto const &bmesh = std::get<0>(gamma_ph_wnn.mesh());
931 auto const &fmesh = std::get<1>(gamma_ph_wnn.mesh());
933 double beta = fmesh.beta();
935 auto chi_kw = make_gf<prod<brzone, imfreq>>(
936 {kmesh, bmesh}, target);
938 auto chi0_n = make_gf<imfreq>(fmesh, target);
939 auto chi0_nn = make_gf<g2_nn_t::mesh_t>({fmesh, fmesh}, target);
940 auto I = identity<Channel_t::PH>(chi0_nn);
942 int nb = gamma_ph_wnn.target_shape()[0];
944 mesh::imfreq fmesh_tail;
945 if (tail_corr_nwf > 0)
946 fmesh_tail = mesh::imfreq{beta, Fermion, tail_corr_nwf};
950 if (fmesh_tail.size() < fmesh.size())
952 <<
"BSE: tail size has to be larger than gamma fermi mesh.\n";
954 array<std::complex<double>, 4> tr_chi(gamma_ph_wnn.target_shape());
955 array<std::complex<double>, 4> tr_chi0(gamma_ph_wnn.target_shape());
956 array<std::complex<double>, 4> tr_chi0_tail_corr(gamma_ph_wnn.target_shape());
958 for (
auto [k, w] : mpi::chunk(chi_kw.mesh())) {
960 triqs::utility::timer t_chi0_n, t_chi0_tr, t_bse_1, t_bse_2, t_bse_3;
966 std::cout <<
"BSE: chi0_n ";
968 auto chi0_n_tail = chi0_n_from_g_wk_PH(w, k, fmesh_tail, g_wk);
969 for (
auto n : fmesh) chi0_n[n] = chi0_n_tail(n);
971 std::cout << double(t_chi0_n) <<
" s\n";
977 std::cout <<
"BSE: Tr[chi0_n] ";
982 for (
auto a : range(nb)) {
983 for (
auto b : range(nb)) {
984 for (
auto c : range(nb)) {
985 for (
auto d : range(nb)) {
986 tr_chi0_tail_corr(a, b, c, d) =
987 density(slice_target_to_scalar(chi0_n_tail, a, b, c, d)) / beta;
993 tr_chi0(a, b, c, d) << sum(chi0_n(inu)(a, b, c, d), inu = fmesh) /
996 std::cout << double(t_chi0_tr) <<
" s\n";
1002 std::cout <<
"BSE: chi0_nn ";
1004 for (
auto n : fmesh) chi0_nn[n, n] = chi0_n[n];
1006 std::cout << double(t_bse_1) <<
" s\n";
1011 std::cout <<
"BSE: I - chi0 * gamma ";
1013 auto denom = g2_nn_t{I - product<Channel_t::PH>(chi0_nn, gamma_ph_wnn[w, _, _])};
1015 std::cout << double(t_bse_2) <<
" s\n";
1018 std::cout <<
"BSE: chi = [I - chi0 * gamma]^{-1} chi0 ";
1020 auto chi_nn = g2_nn_t{product<Channel_t::PH>(inverse<Channel_t::PH>(denom), chi0_nn)};
1022 std::cout << double(t_bse_3) <<
" s\n";
1025 std::cout <<
"BSE: Tr[chi] \n";
1027 for (
auto [n1, n2] : chi_nn.mesh()) tr_chi += chi_nn[n1, n2];
1028 tr_chi /= beta * beta;
1031 tr_chi += tr_chi0_tail_corr - tr_chi0;
1033 chi_kw[k, w] = tr_chi;
1036 chi_kw = mpi::all_reduce(chi_kw);
1041gf<prod<brzone, imfreq>, tensor_valued<4>>
1042chiq_sum_nu_from_e_k_sigma_w_and_gamma_PH(
double mu, ek_vt e_k, g_iw_vt sigma_w,
1043 g2_iw_vt gamma_ph_wnn,
1044 int tail_corr_nwf) {
1048 auto target = gamma_ph_wnn.target();
1051 auto const &kmesh = e_k.mesh();
1052 auto const &[bmesh, fmesh, f2mesh] = gamma_ph_wnn.mesh();
1054 double beta = fmesh.beta();
1056 auto chi_kw = make_gf<prod<brzone, imfreq>>(
1057 {kmesh, bmesh}, target);
1059 auto chi0_n = make_gf<imfreq>(fmesh, target);
1060 auto chi0_nn = make_gf<g2_nn_t::mesh_t>({fmesh, fmesh}, target);
1061 auto I = identity<Channel_t::PH>(chi0_nn);
1063 int nb = gamma_ph_wnn.target_shape()[0];
1065 mesh::imfreq fmesh_tail;
1066 if (tail_corr_nwf > 0)
1067 fmesh_tail = mesh::imfreq{beta, Fermion, tail_corr_nwf};
1071 if (fmesh_tail.size() < fmesh.size())
1073 <<
"BSE: tail size has to be larger than gamma fermi mesh.\n";
1075 array<std::complex<double>, 4> tr_chi(gamma_ph_wnn.target_shape());
1076 array<std::complex<double>, 4> tr_chi0(gamma_ph_wnn.target_shape());
1077 array<std::complex<double>, 4> tr_chi0_tail_corr(gamma_ph_wnn.target_shape());
1079 for (
auto [k, w] : mpi_view(chi_kw.mesh())) {
1081 triqs::utility::timer t_chi0_n, t_chi0_tr, t_bse_1, t_bse_2, t_bse_3;
1087 std::cout <<
"BSE: chi0_n ";
1092 chi0_n_from_e_k_sigma_w_PH(w, k, fmesh_tail, mu, e_k, sigma_w);
1094 for (
auto n : fmesh) chi0_n[n] = chi0_n_tail(n);
1096 std::cout << double(t_chi0_n) <<
" s\n";
1102 std::cout <<
"BSE: Tr[chi0_n] ";
1107 for (
auto a : range(nb)) {
1108 for (
auto b : range(nb)) {
1109 for (
auto c : range(nb)) {
1110 for (
auto d : range(nb)) {
1111 tr_chi0_tail_corr(a, b, c, d) =
1112 density(slice_target_to_scalar(chi0_n_tail, a, b, c, d)) / beta;
1118 tr_chi0(a, b, c, d) << sum(chi0_n(inu)(a, b, c, d), inu = fmesh) /
1121 std::cout << double(t_chi0_tr) <<
" s\n";
1127 std::cout <<
"BSE: chi0_nn ";
1129 for (
auto n : fmesh) chi0_nn[n, n] = chi0_n[n];
1131 std::cout << double(t_bse_1) <<
" s\n";
1136 std::cout <<
"BSE: I - chi0 * gamma ";
1138 auto denom = g2_nn_t{I - product<Channel_t::PH>(chi0_nn, gamma_ph_wnn[w, _, _])};
1140 std::cout << double(t_bse_2) <<
" s\n";
1143 std::cout <<
"BSE: chi = [I - chi0 * gamma]^{-1} chi0 ";
1146 product<Channel_t::PH>(inverse<Channel_t::PH>(denom), chi0_nn);
1148 std::cout << double(t_bse_3) <<
" s\n";
1151 std::cout <<
"BSE: Tr[chi] \n";
1153 for (
auto [n1, n2] : chi_nn.mesh()) tr_chi += chi_nn[n1, n2];
1154 tr_chi /= beta * beta;
1157 tr_chi += tr_chi0_tail_corr - tr_chi0;
1159 chi_kw[k, w] = tr_chi;
1162 chi_kw = mpi::all_reduce(chi_kw);
1167gf<prod<brzone, imfreq>, tensor_valued<4>>
1168chiq_sum_nu(chiq_t chiq) {
1170 auto &mesh_k = std::get<0>(chiq.mesh());
1171 auto &mesh_b = std::get<1>(chiq.mesh());
1172 auto &mesh_f = std::get<2>(chiq.mesh());
1173 auto chiq_w = make_gf<prod<brzone, imfreq>>(
1174 {mesh_k, mesh_b}, chiq.target());
1179 for (
auto [k, w, n1, n2] : chiq.mesh()) chiq_w[k, w] += chiq[k, w, n1, n2];
1181 double beta = mesh_f.beta();
1182 chiq_w = chiq_w / (beta * beta);
1187gf<imfreq, tensor_valued<4>> chiq_sum_nu_q(chiq_t chiq) {
1189 auto &mesh_k = std::get<0>(chiq.mesh());
1190 auto &mesh_b = std::get<1>(chiq.mesh());
1191 auto &mesh_f = std::get<2>(chiq.mesh());
1192 auto chi_w = make_gf<imfreq>(mesh_b, chiq.target());
1194 for (
auto [k, w, n1, n2] : chiq.mesh()) chi_w[w] += chiq[k, w, n1, n2];
1196 double nk = mesh_k.size();
1197 double beta = mesh_f.beta();
1198 chi_w = chi_w / nk / (beta * beta);
1203chi_wk_t attatch_tri_vert(chi_nn_cvt L_wn, chi_kwnn_cvt chi_kwnn) {
1207 auto &mesh_k = std::get<0>(chi_kwnn.mesh());
1208 auto &mesh_b = std::get<1>(chi_kwnn.mesh());
1210 auto chi_wk = make_gf<prod<imfreq, brzone>>({mesh_b, mesh_k}, chi_kwnn.target());
1212 std::cout <<
"--> attatch_tri_vert: Hybrid parallell OpenMP+MPI\n";
1214 auto arr = mpi_view(chi_wk.mesh());
1215#pragma omp parallel for
1216 for (
int idx = 0; idx < arr.size(); idx++) {
1217 auto &[w, k] = arr[idx];
1227 chi_wk[w, k] = scalar_product_PH(L_wn[w, _], chi_kwnn[k, w, _, _], L_wn[w, _]);
1230 chi_wk = mpi::all_reduce(chi_wk);