TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
legendre_matsubara.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2013-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You may obtain a copy of the License at
16// https://www.gnu.org/licenses/gpl-3.0.txt
17//
18// Authors: Michel Ferrero, Olivier Parcollet, Nils Wentzell
19
24
25#pragma once
26
27#include "../gf/gf.hpp"
29#include "../gf/gf_view.hpp"
32#include "../../mesh/imfreq.hpp"
33#include "../../mesh/imtime.hpp"
36
37#include <cmath>
38
39namespace triqs::gfs {
40
41 // FIXME REMOVE TAG AND gf_keeper
42 // Tag identifying a deferred Legendre <-> Matsubara transformation carried by a gf_keeper.
43 namespace tags {
44 struct legendre {};
45 } // namespace tags
46
51
52 // ----------------------------
53
66 template <typename G1, typename G2>
68 void legendre_matsubara_direct(G1 &&gw, G2 const &gl) {
69
70 static_assert(is_gf_v<G2, mesh::legendre>, "Second argument to legendre_matsubara_direct needs to be a Legendre Green function");
71 static_assert(std::is_same_v<typename std::decay_t<G1>::target_t, typename std::decay_t<G2>::target_t>,
72 "Arguments to legendre_matsubara_direct require same target_t");
73
74 gw() = 0.0;
75
76 // Use the transformation matrix
77 for (auto om : gw.mesh()) {
78 for (auto l : gl.mesh()) { gw[om] += triqs::utility::legendre_T(om.index(), l.index()) * gl[l]; }
79 }
80 }
81
82 // ----------------------------
83
85 template <typename G1, typename G2>
87 void legendre_matsubara_direct(G1 &&gt, G2 const &gl) {
88
89 static_assert(is_gf_v<G2, mesh::legendre>, "Second argument to legendre_matsubara_direct needs to be a Legendre Green function");
90 static_assert(std::is_same_v<typename std::decay_t<G1>::target_t, typename std::decay_t<G2>::target_t>,
91 "Arguments to legendre_matsubara_direct require same target_t");
92
93 gt() = 0.0;
95
96 for (auto t : gt.mesh()) {
97 L.reset(2 * t / gt.mesh().beta() - 1);
98 for (auto l : gl.mesh()) { gt[t] += std::sqrt(2 * l.index() + 1) / gt.mesh().beta() * gl[l] * L.next(); }
99 }
100 }
101
102 // ----------------------------
103
117 template <typename G1, typename G2>
119 void legendre_matsubara_inverse(G1 &&gl, G2 const &gw) {
120
121 static_assert(is_gf_v<G1, mesh::legendre>, "First argument to legendre_matsubara_inverse needs to be a Legendre Green function");
122 static_assert(std::is_same_v<typename std::decay_t<G1>::target_t, typename std::decay_t<G2>::target_t>,
123 "Arguments to legendre_matsubara_inverse require same target_t");
124
125 gl() = 0.0;
126
127 // Construct a temporary imaginary-time Green's function gt
128 // I set Nt time bins. This is ugly, one day we must code the direct
129 // transformation without going through imaginary time
130 long Nt = 50000;
131 auto gt =
132 gf<mesh::imtime, typename std::decay_t<G1>::target_t>{{gw.mesh().beta(), gw.mesh().statistic(), Nt}, stdutil::front_pop(gw.data().shape())};
133
134 // We first transform to imaginary time because it's been coded with the knowledge of the tails
135 gt() = fourier(gw);
137 }
138
139 // ----------------------------
140
142 template <typename G1, typename G2>
144 void legendre_matsubara_inverse(G1 &&gl, G2 const &gt) {
145
146 static_assert(is_gf_v<G1, mesh::legendre>, "First argument to legendre_matsubara_inverse needs to be a Legendre Green function");
147 static_assert(std::is_same_v<typename std::decay_t<G1>::target_t, typename std::decay_t<G2>::target_t>,
148 "Arguments to legendre_matsubara_inverse require same target_t");
149
150 gl() = 0.0;
152 auto N = gt.mesh().size() - 1;
153 double coef{};
154
155 // Do the integral over imaginary time
156 for (auto t : gt.mesh()) {
157 if (t.index() == 0 || t.index() == N)
158 coef = 0.5;
159 else
160 coef = 1.0;
161 L.reset(2 * t / gt.mesh().beta() - 1);
162 for (auto l : gl.mesh()) { gl[l] += coef * std::sqrt(2 * l.index() + 1) * L.next() * gt[t]; }
163 }
164 gl.data() *= gt.mesh().delta();
165 }
166
167 // ----------------------------
168
169 // Lightweight handle pairing a const view of a source Green's function with a transformation tag,
170 // so that `g_dst() = legendre_to_imfreq(g_src)` can dispatch through triqs_gf_view_assign_delegation.
171 template <typename Tag, typename D, typename Target> struct gf_keeper {
172 gf_const_view<D, Target> g;
173 };
174
185 template <typename G> inline gf_keeper<tags::legendre, mesh::legendre, typename G::target_t> legendre_to_imfreq(G const &gl) {
186 static_assert(is_gf_v<G, mesh::legendre>, "legendre_to_imfreq takes a Legendre Green function");
187 return {make_const_view(gl)};
188 }
189
200 template <typename G> inline gf_keeper<tags::legendre, mesh::legendre, typename G::target_t> legendre_to_imtime(G const &gl) {
201 static_assert(is_gf_v<G, mesh::legendre>, "legendre_to_imtime takes a Legendre Green function");
202 return {make_const_view(gl)};
203 }
204
215 template <typename G> inline gf_keeper<tags::legendre, mesh::imfreq, typename G::target_t> imfreq_to_legendre(G const &gw) {
216 static_assert(is_gf_v<G, mesh::imfreq>, "imfreq_to_legendre takes a Matsubara Green function");
217 return {make_const_view(gw)};
218 }
219
230 template <typename G> inline gf_keeper<tags::legendre, mesh::imtime, typename G::target_t> imtime_to_legendre(G const &gt) {
231 static_assert(is_gf_v<G, mesh::imtime>, "imtime_to_legendre takes an imaginary time Green function");
232 return {make_const_view(gt)};
233 }
234
236
237 // ----------------------------
238
239 // Assignment delegation: realise a Legendre-to-imfreq transform when a gf_keeper is assigned to a gf_view.
240 template <typename T> void triqs_gf_view_assign_delegation(gf_view<mesh::imfreq, T> gw, gf_keeper<tags::legendre, mesh::legendre, T> const &L) {
242 }
243
244 // Assignment delegation: realise a Legendre-to-imtime transform when a gf_keeper is assigned to a gf_view.
245 template <typename T> void triqs_gf_view_assign_delegation(gf_view<mesh::imtime, T> gt, gf_keeper<tags::legendre, mesh::legendre, T> const &L) {
247 }
248
249 // Assignment delegation: realise an imfreq-to-Legendre transform when a gf_keeper is assigned to a gf_view.
250 template <typename T> void triqs_gf_view_assign_delegation(gf_view<mesh::legendre, T> gl, gf_keeper<tags::legendre, mesh::imfreq, T> const &L) {
252 }
253
254 // Assignment delegation: realise an imtime-to-Legendre transform when a gf_keeper is assigned to a gf_view.
255 template <typename T> void triqs_gf_view_assign_delegation(gf_view<mesh::legendre, T> gl, gf_keeper<tags::legendre, mesh::imtime, T> const &L) {
257 }
258
259} // namespace triqs::gfs
A mutable, non-owning view of a Green's function.
Definition gf_view.hpp:48
The owning Green's function container.
Definition gf.hpp:194
Recursive generation of Legendre polynomials .
Definition legendre.hpp:87
void reset(double x)
Reset the generator to 0th order and with a new value.
Definition legendre.hpp:117
double next()
Increase the degree of the polynomial from to using .
Definition legendre.hpp:101
Provides the Fourier transform factories and the lazy fourier(...) assignment for Green's functions.
Provides tail fitting, slicing, inversion, reality and matrix-multiplication functions for Green's fu...
Provides the triqs::gfs::gf_const_view container, a read-only non-owning view of a Green's function.
Provides a mutable non-owning view of a Green's function.
Provides the Green's function class.
void legendre_matsubara_direct(G1 &&gw, G2 const &gl)
Fill a Matsubara Green's function from a Legendre Green's function.
void legendre_matsubara_inverse(G1 &&gl, G2 const &gw)
Fill a Legendre Green's function from a Matsubara Green's function.
gf_keeper< tags::legendre, mesh::legendre, typename G::target_t > legendre_to_imtime(G const &gl)
Tag a Legendre Green's function for assignment to an imaginary-time Green's function.
gf_keeper< tags::legendre, mesh::legendre, typename G::target_t > legendre_to_imfreq(G const &gl)
Tag a Legendre Green's function for assignment to a Matsubara Green's function.
gf_keeper< tags::legendre, mesh::imtime, typename G::target_t > imtime_to_legendre(G const &gt)
Tag an imaginary-time Green's function for assignment to a Legendre Green's function.
gf_keeper< tags::legendre, mesh::imfreq, typename G::target_t > imfreq_to_legendre(G const &gw)
Tag a Matsubara Green's function for assignment to a Legendre Green's function.
auto fourier(block_gf< V, T, L, A > const &g)
Lazily apply the Fourier transform block by block to a block Green's function.
Definition functions.hpp:44
auto make_const_view(Gf const &g)
Make a const view of a Green's function.
constexpr bool is_gf_v
Trait to check whether a type models the Green's function concept.
Definition gf.hpp:101
std::complex< double > legendre_T(int n, int l)
Get the quantity from Eq.(E2) in the paper https://doi.org/10.1103/PhysRevB.84.075145.
Definition legendre.cpp:37
Provides a mesh type on the imaginary frequency axis.
Provides a mesh type on the imaginary time axis.
Provides a mesh type for Legendre polynomials as basis functions.
Provides Legendre polynomials and related functions.