3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 03:33:50 +01:00

Fix bug with full bins in Fourier transforms

I also added a test to make sure the time mesh is twice as
long as the frequency mesh. Obviously now some tests don't
pass... I will fix them in the next commit.
This commit is contained in:
Michel Ferrero 2014-07-01 18:04:30 +02:00
parent 76798cf6a2
commit 88f8e4cce4

View File

@ -66,10 +66,11 @@ namespace gfs {
dcomplex a1, a2, a3; dcomplex a1, a2, a3;
double beta = gt.mesh().domain().beta; double beta = gt.mesh().domain().beta;
auto L = (gt.mesh().kind() == full_bins ? gt.mesh().size() - 1 : gt.mesh().size()); auto L = (gt.mesh().kind() == full_bins ? gt.mesh().size() - 1 : gt.mesh().size());
double fact = beta / gt.mesh().size(); if (L < 2*gw.mesh().size()) TRIQS_RUNTIME_ERROR << "The time mesh mush be at least twice as long as the freq mesh";
double fact = beta / L;
dcomplex iomega = dcomplex(0.0, 1.0) * std::acos(-1) / beta; 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); dcomplex iomega2 = iomega * 2 * gt.mesh().delta() * (gt.mesh().kind() == half_bins ? 0.5 : 0.0);
g_in.resize(gt.mesh().size()); g_in.resize(L);
g_out.resize(gw.mesh().size()); g_out.resize(gw.mesh().size());
if (gw.domain().statistic == Fermion) { if (gw.domain().statistic == Fermion) {
b1 = 0; b1 = 0;
@ -88,12 +89,16 @@ namespace gfs {
} }
if (gw.domain().statistic == Fermion) { if (gw.domain().statistic == Fermion) {
for (auto& t : gt.mesh()) for (auto& t : gt.mesh())
if(t.index() < L) {
g_in[t.index()] = fact * exp(iomega * t) * 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))); (gt[t] - (oneFermion(a1, b1, t, beta) + oneFermion(a2, b2, t, beta) + oneFermion(a3, b3, t, beta)));
}
} else { } else {
for (auto& t : gt.mesh()) for (auto& t : gt.mesh())
if(t.index() < L) {
g_in[t.index()] = fact * (gt[t] - (oneBoson(a1, b1, t, beta) + oneBoson(a2, b2, t, beta) + oneBoson(a3, b3, t, beta))); 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); details::fourier_base(g_in, g_out, L, true);
for (auto& w : gw.mesh()) { 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[w] = g_out(w.index()) * exp(iomega2 * w.index()) + a1 / (w - b1) + a2 / (w - b2) + a3 / (w - b3);
@ -116,11 +121,12 @@ namespace gfs {
double beta = gw.domain().beta; 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 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 // on the mesh kind) and is given to the FFT algorithm
if (L < 2*gw.mesh().size()) TRIQS_RUNTIME_ERROR << "The time mesh mush be at least twice as long as the freq mesh";
dcomplex iomega = dcomplex(0.0, 1.0) * std::acos(-1) / beta; 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); 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; double fact = (Green_Function_Are_Complex_in_time ? 1 : 2) / beta;
g_in.resize(gw.mesh().size()); g_in.resize(gw.mesh().size());
g_out.resize(gt.mesh().size()); g_out.resize(L);
if (gw.domain().statistic == Fermion) { if (gw.domain().statistic == Fermion) {
b1 = 0; b1 = 0;
@ -151,15 +157,19 @@ namespace gfs {
// typedef typename gf<imtime>::mesh_type::gf_result_type gt_result_type; // typedef typename gf<imtime>::mesh_type::gf_result_type gt_result_type;
if (gw.domain().statistic == Fermion) { if (gw.domain().statistic == Fermion) {
for (auto& t : gt.mesh()) { for (auto& t : gt.mesh()) {
if (t.index() < L) {
gt[t] = gt[t] =
convert_green<gt_result_type>(g_out(t.index() == L ? 0 : t.index()) * exp(-iomega * t) + oneFermion(a1, b1, t, beta) + convert_green<gt_result_type>(g_out(t.index()) * exp(-iomega * t) + oneFermion(a1, b1, t, beta) +
oneFermion(a2, b2, t, beta) + oneFermion(a3, b3, t, beta)); oneFermion(a2, b2, t, beta) + oneFermion(a3, b3, t, beta));
} }
}
} else { } else {
for (auto& t : gt.mesh()) 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) + if (t.index() < L) {
gt[t] = convert_green<gt_result_type>(g_out(t.index()) + oneBoson(a1, b1, t, beta) +
oneBoson(a2, b2, t, beta) + oneBoson(a3, b3, t, beta)); oneBoson(a2, b2, t, beta) + oneBoson(a3, b3, t, beta));
} }
}
double pm = (gw.domain().statistic == Fermion ? -1.0 : 1.0); double pm = (gw.domain().statistic == Fermion ? -1.0 : 1.0);
if (gt.mesh().kind() == full_bins) gt.on_mesh(L) = pm * (gt.on_mesh(0) + convert_green<gt_result_type>(ta(1)(0, 0))); if (gt.mesh().kind() == full_bins) gt.on_mesh(L) = pm * (gt.on_mesh(0) + convert_green<gt_result_type>(ta(1)(0, 0)));
// set tail // set tail