void inverse(gf_view<imtime,scalar_valued> gt, gf_view<imfreq,scalar_valued> const gw){ using namespace impl_local_matsubara; static bool Green_Function_Are_Complex_in_time = false; // If the Green function are NOT complex, then one use the symmetry property // fold the sum and get a factor 2 auto ta = gw(freq_infty()); //TO BE MODIFIED AFTER SCALAR IMPLEMENTATION TODO dcomplex d= ta(1)(0,0), A= ta.get_or_zero(2)(0,0), B = ta.get_or_zero(3)(0,0); double b1, b2, b3; dcomplex a1, a2, a3; double beta=gw.domain().beta; size_t L= gt.mesh().size() - ( gt.mesh().kind() == full_bins ? 1 : 0); //L can be different from gt.mesh().size() (depending on the mesh kind) and is given to the FFT algorithm dcomplex iomega = dcomplex(0.0,1.0) * std::acos(-1) / beta; dcomplex iomega2 = -iomega * 2 * gt.mesh().delta() * (gt.mesh().kind() == half_bins ? 0.5 : 0.0) ; double fact = (Green_Function_Are_Complex_in_time ? 1 : 2)/beta; g_in.resize( gw.mesh().size()); g_out.resize(gt.mesh().size()); if (gw.domain().statistic == Fermion){ b1 = 0; b2 =1; b3 =-1; a1 = d-B; a2 = (A+B)/2; a3 = (B-A)/2; } else { b1 = -0.5; b2 =-1; b3 =1; a1=4*(d-B)/3; a2=B-(d+A)/2; a3=d/6+A/2+B/3; } g_in() = 0; for (auto & w: gw.mesh()) { g_in[ w.index() ] = fact * exp(w.index()*iomega2) * ( gw[w] - (a1/(w-b1) + a2/(w-b2) + a3/(w-b3)) ); } // for bosons GF(w=0) is divided by 2 to avoid counting it twice if (gw.domain().statistic == Boson && !Green_Function_Are_Complex_in_time ) g_in(0) *= 0.5; details::fourier_base(g_in, g_out, L, false); // CORRECT FOR COMPLEX G(tau) !!! typedef double gt_result_type; //typedef typename gf<imtime>::mesh_type::gf_result_type gt_result_type; if (gw.domain().statistic == Fermion){ for (auto & t : gt.mesh()){ gt[t] = convert_green<gt_result_type> ( g_out( t.index() == L ? 0 : t.index() ) * exp(-iomega*t) + oneFermion(a1,b1,t,beta) + oneFermion(a2,b2,t,beta)+ oneFermion(a3,b3,t,beta) ); } } else { for (auto & t : gt.mesh()) gt[t] = convert_green<gt_result_type> ( g_out( t.index() == L ? 0 : t.index() ) + oneBoson(a1,b1,t,beta) + oneBoson(a2,b2,t,beta) + oneBoson(a3,b3,t,beta) ); } if (gt.mesh().kind() == full_bins) gt.on_mesh(L) = -gt.on_mesh(0)-convert_green<gt_result_type>(ta(1)(0,0)); // set tail gt.singularity() = gw.singularity(); }
void legendre_matsubara_direct(gf_view<imtime> gt, gf_const_view<legendre> gl) { gt() = 0.0; legendre_generator L; for (auto t : gt.mesh()) { L.reset(2 * t / gt.domain().beta - 1); for (auto l : gl.mesh()) { gt[t] += sqrt(2 * l.index() + 1) / gt.domain().beta * gl[l] * L.next(); } } gt.singularity() = get_tail(gl, gt.singularity().size(), gt.singularity().order_min()); }
// compute a tail from the Legendre GF // this is Eq. 8 of our paper local::tail_view get_tail(gf_view<legendre> const & gl, int size = 10, int omin = -1) { auto sh = gl.data().shape().front_pop(); local::tail t(sh, size, omin); t.data() = 0.0; for (int p=1; p<=t.order_max(); p++) for (auto l : gl.mesh()) t(p) += (triqs::utility::legendre_t(l.index(),p)/pow(gl.domain().beta,p)) * gl[l]; return t; }
tqa::matrix<double> density( gf_view<legendre> const & gl) { auto sh = gl.data().shape().front_pop(); tqa::matrix<double> res(sh); res() = 0.0; for (auto l : gl.mesh()) { res -= sqrt(2*l.index()+1) * gl[l]; } res /= gl.domain().beta; return res; }
void direct (gf_view<imfreq,scalar_valued> gw, gf_view<imtime,scalar_valued> const gt) { using namespace impl_local_matsubara; auto ta = gt(freq_infty()); //TO BE MODIFIED AFTER SCALAR IMPLEMENTATION TODO dcomplex d= ta(1)(0,0), A= ta.get_or_zero(2)(0,0), B = ta.get_or_zero(3)(0,0); double b1=0, b2=0, b3=0; dcomplex a1, a2, a3; double beta=gt.mesh().domain().beta; auto L = ( gt.mesh().kind() == full_bins ? gt.mesh().size()-1 : gt.mesh().size()); double fact= beta/ gt.mesh().size(); dcomplex iomega = dcomplex(0.0,1.0) * std::acos(-1) / beta; dcomplex iomega2 = iomega * 2 * gt.mesh().delta() * ( gt.mesh().kind() == half_bins ? 0.5 : 0.0); g_in.resize(gt.mesh().size()); g_out.resize(gw.mesh().size()); if (gw.domain().statistic == Fermion){ b1 = 0; b2 =1; b3 =-1; a1 = d-B; a2 = (A+B)/2; a3 = (B-A)/2; } else { b1 = -0.5; b2 =-1; b3 =1; a1 = 4*(d-B)/3; a2 = B-(d+A)/2; a3 = d/6+A/2+B/3; } if (gw.domain().statistic == Fermion){ for (auto & t : gt.mesh()) g_in[t.index()] = fact * exp(iomega*t) * ( gt[t] - ( oneFermion(a1,b1,t,beta) + oneFermion(a2,b2,t,beta)+ oneFermion(a3,b3,t,beta) ) ); } else { for (auto & t : gt.mesh()) g_in[t.index()] = fact * ( gt[t] - ( oneBoson(a1,b1,t,beta) + oneBoson(a2,b2,t,beta) + oneBoson(a3,b3,t,beta) ) ); } details::fourier_base(g_in, g_out, L, true); for (auto & w : gw.mesh()) { gw[w] = g_out( w.index() ) * exp(iomega2*w.index() ) + a1/(w-b1) + a2/(w-b2) + a3/(w-b3); } gw.singularity() = gt.singularity();// set tail }
// Impose a discontinuity G(\tau=0)-G(\tau=\beta) void enforce_discontinuity(gf_view<legendre> & gl, arrays::array_view<double,2> disc) { double norm = 0.0; arrays::vector<double> t(gl.data().shape()[0]); for (int i=0; i<t.size(); ++i) { t(i) = triqs::utility::legendre_t(i,1) / gl.domain().beta; norm += t(i)*t(i); } arrays::array<dcomplex, 2> corr(disc.shape()); corr() = 0; for (auto const &l : gl.mesh()) corr += t(l.index()) * gl[l]; auto _ = arrays::range{}; for (auto const& l : gl.mesh()) gl.data()(l.index(), _, _) += (disc - corr) * t(l.index()) / norm; }
// Impose a discontinuity G(\tau=0)-G(\tau=\beta) void enforce_discontinuity(gf_view<legendre> & gl, tqa::array_view<double,2> disc) { double norm = 0.0; tqa::vector<double> t(gl.data().shape()[0]); for (int i=0; i<t.size(); ++i) { t(i) = triqs::utility::legendre_t(i,1) / gl.domain().beta; norm += t(i)*t(i); } tqa::array<double,2> corr(disc.shape()); corr() = 0; for (auto l : gl.mesh()) { corr += t(l.index()) * gl[l]; } tqa::range R; for (auto l : gl.mesh()) { gl.data()(l.index(),R,R) += (disc - corr) * t(l.index()) / norm; } }
//------------------------------------------------------- // For Imaginary Matsubara Frequency functions // ------------------------------------------------------ tqa::matrix<double> density( gf_view<imfreq> const & G) { dcomplex I(0,1); auto sh = G.data().shape().front_pop(); auto Beta = G.domain().beta; local::tail_view t = G(freq_infty()); if (!t.is_decreasing_at_infinity()) TRIQS_RUNTIME_ERROR<<" density computation : Green Function is not as 1/omega or less !!!"; const size_t N1=sh[0], N2 = sh[1]; tqa::array<dcomplex,2> dens_part(sh), dens_tail(sh), dens(sh); tqa::matrix<double> res(sh); dens_part()=0;dens()=0;dens_tail()=0; for (size_t n1=0; n1<N1;n1++) for (size_t n2=0; n2<N2;n2++) { dcomplex d= t(1)(n1,n2) , A=t(2)(n1,n2),B = t(3)(n1,n2) ; double b1 = 0,b2 =1, b3 =-1; dcomplex a1 = d-B, a2 = (A+B)/2, a3 = (B-A)/2; for (auto & w : G.mesh()) dens_part(n1,n2)+= G[w](n1,n2) - (a1/(w - b1) + a2 / (w-b2) + a3/(w-b3)); dens_part(n1,n2) = dens_part(n1,n2)/Beta; dens_tail(n1,n2) = d + F(a1,b1,Beta) + F(a2,b2,Beta)+ F(a3,b3,Beta); // If the Green function are NOT complex, then one use the symmetry property // fold the sum and get a factor 2 //double fact = (Green_Function_Are_Complex_in_time ? 1 : 2); //dens_part(n1,n2) = dens_part(n1,n2)*(fact/Beta) + (d + F(a1,b1,Beta) + F(a2,b2,Beta)+ F(a3,b3,Beta)); //if (!Green_Function_Are_Complex_in_time) dens_part = 0+real(dens_part); } for (size_t n1=0; n1<N1;n1++) for (size_t n2=0; n2<N2;n2++) { dens_part(n1,n2) = dens_part(n1,n2) + real(dens_part(n2,n1)) - I * imag(dens_part(n2,n1)) + dens_tail(n1,n2); // ?? STRANGE ?? dens_part(n2,n1) = real(dens_part(n1,n2)) - I * imag(dens_part(n1,n2)); } for (size_t n1=0; n1<N1;n1++) for (size_t n2=0; n2<N2;n2++) { res(n1,n2) = real(dens_part(n1,n2)); } return res; }