22#include <nda/linalg.hpp>
26#include "chi_retime.hpp"
28#include "../fourier/fourier.hpp"
34 using namespace fourier;
40double fermi_scalar(
double e) {
42 return 1. / (exp(e) + 1.);
44 double exp_me = exp(-e);
45 return exp_me / (1 + exp_me);
49auto fermi_nda = nda::map([](
double e) {
return fermi_scalar(e); });
54std::tuple<g_Tk_t, g_Tk_t> g0_Tk_les_gtr_from_e_k(e_k_cvt e_k, mesh::retime Tmesh,
double beta) {
56 auto I = std::complex(0.,1.);
57 auto kmesh = e_k.mesh();
59 g_Tk_t g0_Tk_les({Tmesh, kmesh}, e_k.target_shape());
60 g_Tk_t g0_Tk_gtr({Tmesh, kmesh}, e_k.target_shape());
62 auto arr = mpi_view(kmesh);
64#pragma omp parallel for
65 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
68 matrix<std::complex<double>> e_k_mat(e_k[k]);
69 auto [ek, Uk] = linalg::eigh(e_k_mat);
71 auto occ = fermi_nda(beta*ek);
73 for (
auto T : Tmesh) {
74 auto exp_T = exp(-I * ek *
double(T));
75 auto occ_exp_les = +I * occ * exp_T;
76 auto occ_exp_gtr = -I * (1. - occ) * exp_T;
78 for (
auto [a, b] : g0_Tk_les.target_indices())
79 for (
auto c : range(ek.size())) {
80 g0_Tk_les[T, k](a, b) += Uk(a, c) * occ_exp_les(c) * dagger(Uk)(c, b);
81 g0_Tk_gtr[T, k](a, b) += Uk(a, c) * occ_exp_gtr(c) * dagger(Uk)(c, b);
86 g0_Tk_les = mpi::all_reduce(g0_Tk_les);
87 g0_Tk_gtr = mpi::all_reduce(g0_Tk_gtr);
89 return {g0_Tk_les, g0_Tk_gtr};
95chi_Tr_t chi0_Tr_from_g_Tr_PH(g_Tr_cvt g_Tr_les, g_Tr_cvt g_Tr_gtr) {
97 auto I = std::complex(0.,1.);
99 auto Tmesh = std::get<0>(g_Tr_les.mesh());
100 auto rmesh = std::get<1>(g_Tr_les.mesh());
102 int nb = g_Tr_les.target().shape()[0];
104 chi_Tr_t chi0_Tr{{Tmesh, rmesh}, {nb, nb, nb, nb}};
108 auto arr = mpi_view(Tmesh);
110#pragma omp parallel for
111 for (
unsigned int idx = 0; idx < arr.size(); idx++) {
115 for (
auto [a, b, c, d] : chi0_Tr.target_indices())
116 chi0_Tr[T, r](a, b, c, d) = +I * g_Tr_les[T, r](d, a) * conj(g_Tr_gtr(T.index(), -r)(b, c)) - I * g_Tr_gtr[T, r](d, a) * conj(g_Tr_les(T.index(), -r)(b, c));
119 chi0_Tr = mpi::all_reduce(chi0_Tr);