25#include "eliashberg.hpp"
36template<
typename F_out_t,
typename g_t>
37F_out_t eliashberg_g_delta_g_product_template(g_t g_wk, g_t delta_wk) {
39 auto wmesh = std::get<0>(delta_wk.mesh());
40 auto kmesh = std::get<1>(delta_wk.mesh());
42 auto wmesh_gf = std::get<0>(g_wk.mesh());
44 if (wmesh.size() > wmesh_gf.size())
45 TRIQS_RUNTIME_ERROR <<
"The size of the Matsubara frequency mesh of the Green's function"
46 " (" << wmesh_gf.size() <<
") must be atleast the size of the mesh of Delta (" <<
49 auto F_wk = make_gf(delta_wk);
52 auto meshes_mpi = mpi_view(delta_wk.mesh());
53#pragma omp parallel for
54 for (
unsigned int idx = 0; idx < meshes_mpi.size(); idx++){
55 auto &[w, k] = meshes_mpi[idx];
57 for (
auto [d, c] : F_wk.target_indices()) {
58 for (
auto [e, f] : delta_wk.target_indices()) {
59 F_wk[w, k](d, c) += g_wk[w, k](c, f) * nda::conj(g_wk[w, -k](e, d)) * delta_wk[w, k](e, f);
64 F_wk = mpi::all_reduce(F_wk);
69g_wk_t eliashberg_g_delta_g_product(g_wk_vt g_wk, g_wk_vt delta_wk) {
70 return eliashberg_g_delta_g_product_template<g_wk_t, g_wk_vt>(g_wk, delta_wk);
73g_Dwk_t eliashberg_g_delta_g_product(g_Dwk_vt g_wk, g_Dwk_vt delta_wk) {
79 auto wmesh = std::get<0>(delta_wk.mesh());
80 auto kmesh = std::get<1>(delta_wk.mesh());
82 auto wmesh_gf = std::get<0>(g_wk.mesh());
84 if (wmesh.size() > wmesh_gf.size())
85 TRIQS_RUNTIME_ERROR <<
"The size of the Matsubara frequency mesh of the Green's function"
86 " (" << wmesh_gf.size() <<
") must be atleast the size of the mesh of Delta (" <<
89 auto F_wk = make_gf(delta_wk);
92 auto tmesh = dlr_imtime(wmesh);
93 tmesh.dlr_it().convolve_init();
95 auto mesh_mpi = mpi_view(kmesh);
96#pragma omp parallel for
97 for (
unsigned int idx = 0; idx < mesh_mpi.size(); idx++){
98 auto & k = mesh_mpi[idx];
100 for (
auto [d, c] : g_wk.target_indices()) {
101 for (
auto [e, f] : delta_wk.target_indices()) {
103 auto gg_w = gf(wmesh);
104 auto d_w = gf(wmesh);
106 for(
auto w : wmesh ) {
107 gg_w[w] = g_wk[w, k](c, f) * nda::conj(g_wk[w, -k](e, d));
108 d_w[w] = delta_wk[w, k](e, f);
111 auto gg_c = make_gf_dlr(gg_w);
112 auto d_c = make_gf_dlr(d_w);
114 auto f_t = gf(tmesh);
115 f_t.data() = tmesh.dlr_it().convolve(
116 tmesh.beta(), gg_c.data(), d_c.data());
118 auto f_c = make_gf_dlr(f_t);
119 auto f_w = make_gf_dlr_imfreq(f_c);
121 for(
auto w : wmesh ) {
122 F_wk[w, k](d, c) += f_w[w];
128 F_wk = mpi::all_reduce(F_wk);
133g_wk_t eliashberg_product(chi_wk_vt Gamma_pp, g_wk_vt g_wk,
137 auto wmesh = std::get<0>(delta_wk.mesh());
138 auto kmesh = std::get<1>(delta_wk.mesh());
140 auto gamma_wmesh = std::get<0>(Gamma_pp.mesh());
142 if (2*wmesh.size() > gamma_wmesh.size())
143 TRIQS_RUNTIME_ERROR <<
"The size of the Matsubara frequency mesh of Gamma"
144 " (" << gamma_wmesh.size() <<
") must be atleast TWICE the size of the mesh of Delta (" <<
145 wmesh.size() <<
").";
147 auto F_wk = eliashberg_g_delta_g_product(g_wk, delta_wk);
149 auto delta_wk_out = make_gf(delta_wk);
152 auto arr = mpi_view(kmesh);
153#pragma omp parallel for
154 for (
int kidx = 0; kidx < arr.size(); kidx++) {
156 for (
auto w : wmesh) {
157 for (
auto [n, q] : delta_wk.mesh())
158 for (
auto [c, a, d, b] : Gamma_pp.target_indices())
159 delta_wk_out[w, k](a, b) += -0.5 * Gamma_pp(w - n, k - q)(c, a, d, b) * F_wk[n, q](d, c);
163 delta_wk_out /= (wmesh.beta() * kmesh.size());
165 delta_wk_out = mpi::all_reduce(delta_wk_out);
170std::tuple<chi_tr_t, chi_r_t> dynamic_and_constant_to_tr(chi_wk_vt Gamma_pp_dyn_wk, chi_k_vt Gamma_pp_const_k) {
172 auto Gamma_pp_dyn_wr = fourier_wk_to_wr_general_target(Gamma_pp_dyn_wk);
173 auto Gamma_pp_dyn_tr = fourier_wr_to_tr_general_target(Gamma_pp_dyn_wr);
175 auto Gamma_pp_const_r = make_gf_from_fourier<0>(Gamma_pp_const_k);
177 return {Gamma_pp_dyn_tr, Gamma_pp_const_r};
180std::tuple<chi_Dtr_t, chi_r_t> dynamic_and_constant_to_tr(chi_Dwk_vt Gamma_pp_dyn_wk, chi_k_vt Gamma_pp_const_k) {
182 auto Gamma_pp_dyn_wr = fourier_wk_to_wr_general_target(Gamma_pp_dyn_wk);
183 auto Gamma_pp_dyn_tr = fourier_Dwr_to_Dtr_general_target(Gamma_pp_dyn_wr);
185 auto Gamma_pp_const_r = make_gf_from_fourier<0>(Gamma_pp_const_k);
187 return {Gamma_pp_dyn_tr, Gamma_pp_const_r};
190e_r_t eliashberg_constant_gamma_f_product(chi_r_vt Gamma_pp_const_r, g_tr_t F_tr) {
194 auto delta_r_out = make_gf(std::get<1>(F_tr.mesh()), F_tr.target());
197 for (
auto r : std::get<1>(F_tr.mesh())) {
198 auto F_t = F_tr[_, r];
199 for (
auto [c, a, d, b] : Gamma_pp_const_r.target_indices()) delta_r_out[r](a, b) += -0.5 * Gamma_pp_const_r[r](c, a, d, b) * F_t(0)(d, c);
205e_r_t eliashberg_constant_gamma_f_product(chi_r_vt Gamma_pp_const_r, g_Dtr_t F_tr) {
208 auto tmesh = std::get<0>(F_tr.mesh());
210 auto delta_r_out = make_gf(std::get<1>(F_tr.mesh()), F_tr.target());
213 for (
auto r : std::get<1>(F_tr.mesh())) {
214 g_Dt_t F_t({tmesh}, F_tr.target_shape());
216 auto F_Dc = make_gf_dlr(F_t);
217 for (
auto [c, a, d, b] : Gamma_pp_const_r.target_indices())
218 delta_r_out[r](a, b) += -0.5 * Gamma_pp_const_r[r](c, a, d, b) * F_Dc(0)(d, c);
224template<
typename delta_t,
typename chi_t,
typename F_t>
225delta_t eliashberg_dynamic_gamma_f_product_template(chi_t Gamma_pp_dyn_tr, F_t F_tr) {
228 auto tmesh = std::get<0>(F_tr.mesh());
229 auto rmesh = std::get<1>(F_tr.mesh());
231 auto delta_tr_out = make_gf(F_tr);
234 auto tmesh_gamma = std::get<0>(Gamma_pp_dyn_tr.mesh());
238 if (tmesh.size() != tmesh_gamma.size())
239 TRIQS_RUNTIME_ERROR <<
"The size of the imaginary time mesh of Gamma"
240 " (" << tmesh_gamma.size() <<
") must be the size of the mesh of Delta (" <<
241 tmesh.size() <<
").";
243 auto meshes_mpi = mpi_view(F_tr.mesh());
244#pragma omp parallel for
245 for (
unsigned int idx = 0; idx < meshes_mpi.size(); idx++){
246 auto &[t, r] = meshes_mpi[idx];
248 for (
auto [c, a, d, b] : Gamma_pp_dyn_tr.target_indices())
249 delta_tr_out[t, r](a, b) += -0.5 * Gamma_pp_dyn_tr[t, r](c, a, d, b) * F_tr[t, r](d, c);
252 delta_tr_out = mpi::all_reduce(delta_tr_out);
257g_tr_t eliashberg_dynamic_gamma_f_product(chi_tr_vt Gamma_pp_dyn_tr, g_tr_vt F_tr) {
258 return eliashberg_dynamic_gamma_f_product_template<g_tr_t, chi_tr_vt, g_tr_vt>(Gamma_pp_dyn_tr, F_tr);
261g_Dtr_t eliashberg_dynamic_gamma_f_product(chi_Dtr_vt Gamma_pp_dyn_tr, g_Dtr_vt F_tr) {
262 return eliashberg_dynamic_gamma_f_product_template<g_Dtr_t, chi_Dtr_vt, g_Dtr_vt>(Gamma_pp_dyn_tr, F_tr);
266template<
typename delta_out_t,
typename chi_t,
typename g_t>
267delta_out_t eliashberg_product_fft_template(chi_t Gamma_pp_dyn_tr, chi_r_vt Gamma_pp_const_r,
268 g_t g_wk, g_t delta_wk) {
270 auto F_wk = eliashberg_g_delta_g_product(g_wk, delta_wk);
271 auto F_wr = fourier_wk_to_wr(F_wk);
272 auto F_tr = fourier_wr_to_tr(F_wr);
274 auto delta_tr_out = eliashberg_dynamic_gamma_f_product(Gamma_pp_dyn_tr, F_tr);
275 auto delta_r_out = eliashberg_constant_gamma_f_product(Gamma_pp_const_r, F_tr);
279 auto delta_wr_out = fourier_tr_to_wr(delta_tr_out);
282 for (
auto w : std::get<0>(delta_wr_out.mesh())) delta_wr_out[w, _] += delta_r_out;
284 auto delta_wk_out = fourier_wr_to_wk(delta_wr_out);
288g_wk_t eliashberg_product_fft(chi_tr_vt Gamma_pp_dyn_tr, chi_r_vt Gamma_pp_const_r, g_wk_vt g_wk, g_wk_vt delta_wk) {
289 return eliashberg_product_fft_template<g_wk_t, chi_tr_vt, g_wk_vt>(Gamma_pp_dyn_tr, Gamma_pp_const_r, g_wk, delta_wk);
292g_Dwk_t eliashberg_product_fft(chi_Dtr_vt Gamma_pp_dyn_tr, chi_r_vt Gamma_pp_const_r, g_Dwk_vt g_wk, g_Dwk_vt delta_wk) {
293 return eliashberg_product_fft_template<g_Dwk_t, chi_Dtr_vt, g_Dwk_vt>(Gamma_pp_dyn_tr, Gamma_pp_const_r, g_wk, delta_wk);
298template<
typename delta_out_t,
typename g_t>
299delta_out_t eliashberg_product_fft_constant_template(chi_r_vt Gamma_pp_const_r,
300 g_t g_wk, g_t delta_wk) {
302 auto F_wk = eliashberg_g_delta_g_product(g_wk, delta_wk);
303 auto F_wr = fourier_wk_to_wr(F_wk);
304 auto F_tr = fourier_wr_to_tr(F_wr);
306 auto delta_r_out = eliashberg_constant_gamma_f_product(Gamma_pp_const_r, F_tr);
307 auto delta_k_out = make_gf_from_fourier<0>(delta_r_out);
309 auto delta_wk_out = make_gf(F_wk);
313 for (
auto w : std::get<0>(delta_wk_out.mesh())) delta_wk_out[w, _] += delta_k_out;
318g_wk_t eliashberg_product_fft_constant(chi_r_vt Gamma_pp_const_r, g_wk_vt g_wk, g_wk_vt delta_wk) {
319 return eliashberg_product_fft_constant_template<g_wk_t, g_wk_vt>(Gamma_pp_const_r, g_wk, delta_wk);
322g_Dwk_t eliashberg_product_fft_constant(chi_r_vt Gamma_pp_const_r, g_Dwk_vt g_wk, g_Dwk_vt delta_wk) {
323 return eliashberg_product_fft_constant_template<g_Dwk_t, g_Dwk_vt>(Gamma_pp_const_r, g_wk, delta_wk);
327chi_wk_t construct_phi_wk(chi_wk_vt chi, array_contiguous_view<std::complex<double>, 4> U) {
329 using scalar_t = chi_wk_t::scalar_t;
331 size_t nb = chi.target_shape()[0];
333 auto phi_wk = make_gf(chi);
337 auto U_matrix = make_matrix_view(group_indices_view(U, idx_group<0, 1>, idx_group<3, 2>));
339 auto meshes_mpi = mpi_view(phi_wk.mesh());
341#pragma omp parallel for
342 for (
unsigned int idx = 0; idx < meshes_mpi.size(); idx++){
343 auto &[w, k] = meshes_mpi[idx];
345 array<scalar_t, 4> phi_arr{nb, nb, nb, nb};
346 array<scalar_t, 4> chi_arr{chi[w, k]};
349 auto phi_matrix = make_matrix_view(group_indices_view(phi_arr, idx_group<0, 1>, idx_group<3, 2>));
351 auto chi_matrix = make_matrix_view(group_indices_view(chi_arr, idx_group<0, 1>, idx_group<3, 2>));
353 phi_matrix = U_matrix * chi_matrix * U_matrix;
355 phi_wk[w, k] = phi_arr;
357 phi_wk = mpi::all_reduce(phi_wk);