3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 22:03:43 +01:00

doc : gf, fourier,meshes

This commit is contained in:
Laura Messio 2013-07-19 16:37:01 +02:00 committed by Olivier Parcollet
parent 71c709b0ba
commit 76d74ce0da
2 changed files with 154 additions and 21 deletions

View File

@ -37,10 +37,10 @@ It will be used to calculate the (inverse) Fourier transform, in real/imaginary
The DFT transforms of a sequence of :math:`N` complex numbers :math:`f_0...,f_{N-1}` into a sequence of :math:`N` complex numbers :math:`\tilde f_0...,\tilde f_{N-1}` according to the formula: The DFT transforms of a sequence of :math:`N` complex numbers :math:`f_0...,f_{N-1}` into a sequence of :math:`N` complex numbers :math:`\tilde f_0...,\tilde f_{N-1}` according to the formula:
:label: _DFT :label: _DFT
.. math:: \tilde f_m = \sum_{k=0}^{N-1} f_k e^{-i 2 \pi m k / N}. .. math:: \tilde f_k = \sum_{n=0}^{N-1} f_n e^{-i 2 \pi k n / N}.
The inverse DFT formula is The inverse DFT formula is
:label: _inv_DFT :label: _inv_DFT
.. math:: f_k = \frac{1}{N} \sum_{m=0}^{N-1} \tilde f_m e^{i 2 \pi m k / N}. .. math:: f_n = \frac{1}{N} \sum_{k=0}^{N-1} \tilde f_k e^{i 2 \pi k n / N}.
@ -54,17 +54,15 @@ The times are :math:`t_k=t_{min}+k\delta t` and the frequencies :math:`\omega_m=
By approximating Eq. :ref:`TF_R` by By approximating Eq. :ref:`TF_R` by
.. math:: \tilde G(\omega_m) = \delta t \sum_{k=0}^{N_t} G(t_k) e^{i\omega_m t_k}, .. math:: \tilde G(\omega_m) = \delta t \sum_{k=0}^{N_t} G(t_k) e^{i\omega_m t_k},
we recognize a DFT (Eq. :ref:`DFT`). To calculate it using FFTW, we first need to prepare the input: we recognize an inverse DFT (Eq. :ref:`inv_DFT`). To calculate it using FFTW, we first need to prepare the input :math:`\tilde f_k`, then to do the DFT and finally to modify the output to obtain :math:`\tilde G(\omega_m)` using the two formulas:
.. math:: f_k = G(t_k) e^{i \omega_{min}t_k}, .. math:: \tilde f_k = G(t_k) e^{i \omega_{min}t_k},
then to do the DFT and finally to modify the output to obtain :math:`\tilde G(\omega_m)` as .. math:: \tilde G(\omega_m) = \delta t f_m e^{i t_{min}(\omega_m-\omega_{min})}.
.. math:: \tilde G(\omega_m) = \delta t \tilde f_m e^{i t_{min}(\omega_m-\omega_{min})}.
Similarly, the inverse transformation is obtained by approximating Eq. :ref:`eq_inv_TF_R` by Similarly, the inverse transformation is obtained by approximating Eq. :ref:`eq_inv_TF_R` by
.. math:: G(t_k)=\frac{\delta\omega}{2\pi}\sum_{m=0}^{N_\omega} \tilde G(\omega_m)e^{-i\omega_m t_k}, .. math:: G(t_k)=\frac{\delta\omega}{2\pi}\sum_{m=0}^{N_\omega} \tilde G(\omega_m)e^{-i\omega_m t_k},
we recognize an inverse DFT (Eq. :ref:`inv_DFT`). To calculate it using FFTW, we first need to prepare the input: we recognize a DFT (Eq. :ref:`DFT`). To calculate it using FFTW, we first need to prepare the input :math:`f_m`, then to do the inverse DFT and finally to modify the output to obtain :math:`G(t_k)`:
.. math:: \tilde f_m = \tilde G(\omega_m) e^{-i t_{min}\omega_m}, .. math:: f_m = \tilde G(\omega_m) e^{-i t_{min}\omega_m},
then to do the inverse DFT and finally to modify the output to obtain :math:`G(t_k)` as .. math:: G(t_k) = \frac{1}{N_t \delta t}\tilde f_k e^{-i \omega_{min}(t_k-t_{min})}.
.. math:: G(t_k) = \frac{1}{N_t \delta t}f_k e^{-i \omega_{min}(t_k-t_{min})},
@ -74,24 +72,55 @@ Implementation in imaginary time/frequency using FFTW
The imaginary time mesh parameters are :math:`\beta` and :math:`N_\tau`, plus a tag ``half_bins``, ``full_bins`` or ``without_last``. The imaginary time mesh parameters are :math:`\beta` and :math:`N_\tau`, plus a tag ``half_bins``, ``full_bins`` or ``without_last``.
In the ``full_bins`` case, one point of the time GF has to be removed for the fourier transform. In the ``full_bins`` case, one point of the time GF has to be removed for the fourier transform.
From these parameters, we deduce :math:`\delta\tau=\beta/N_\tau` From these parameters, we deduce :math:`\delta\tau=\beta/N_\tau`.
CHAPTER NOT FINISHED !!!! It seems that only real GF's in time are considered (w_n is always >0)... For the imaginary frequency mesh, the mesh parameters are :math:`\beta`, :math:`n_{min}` and :math:`N_{\omega_n}`.
For the imaginary frequency mesh, they are :math:`n_{min}`, :math:`\beta` and :math:`N_\omega`.
From them, we deduce :math:`\delta\omega=\frac{2\pi}{\beta}`. From them, we deduce :math:`\delta\omega=\frac{2\pi}{\beta}`.
The Fourier transform requires :math:`N_\omega=N_\tau`. The Fourier transform requires :math:`N_\omega=N_\tau`.
The times are :math:`\tau_k=\tau_{min}+k\delta\tau` and the frequencies :math:`\omega_n=\omega_{min}+n\delta \omega`. The times are :math:`\tau_k=\tau_{min}+k\delta\tau` and the frequencies :math:`\omega_n=\omega_{min}+n\delta \omega`.
:math:`\tau_{min}` is either 0 or :math:`\delta\tau/2` depending on the mesh kind. :math:`\tau_{min}` is either 0 or :math:`\delta\tau/2` depending on the mesh kind.
:math:`\omega_{min}` is either :math:`\frac{2\pi(n_{min}+1)}{\beta}` or :math:`\frac{2\pi n_{min}}{\beta}` depending on the statistic. :math:`\omega_{min}` is either :math:`\frac{2\pi(n_{min}+1)}{\beta}` or :math:`\frac{2\pi n_{min}}{\beta}` depending on the statistics.
We approximate the TF and its inverse by We approximate the TF and its inverse by
.. math:: \tilde G(i\omega_n) = \delta\tau \sum_{k=0}^{N_\tau} G(\tau_k)e^{i\omega_n \tau_k} .. math:: \tilde G(i\omega_n) = \delta\tau \sum_{k=0}^{N_\tau} G(\tau_k)e^{i\omega_n \tau_k}
.. math:: G(\tau_k) = \sum_{n=0}^{N_\tau} \frac{1}{\beta} \tilde G(i\omega_n)e^{-i\omega_n \tau_k} .. math:: G(\tau_k) = \sum_{n=n_{min}}^{N_\tau} \frac{1}{\beta} \tilde G(i\omega_n)e^{-i\omega_n \tau_k}
We use for the TF: We use for the TF:
.. math:: f_k = G(\tau_k) e^{i \omega_{min}\tau_k}, .. math:: \tilde f_k = G(\tau_k) e^{i \omega_{min}\tau_k},
.. math:: \tilde G(i\omega_m) = \frac{\beta}{N_\tau} \tilde f_m e^{i \tau_{min}(\omega_m-\omega_{min})}. .. math:: \tilde G(i\omega_n) = \frac{\beta}{N_\tau} f_n e^{i \tau_{min}(\omega_n-\omega_{min})}.
and for the inverse TF:
.. math:: f_m = \frac{1}{\beta}\tilde G(i\omega_n) e^{-i t_{min}\omega_n},
.. math:: G(t_k) = \tilde f_k e^{-i \omega_{min}(\tau_k-\tau_{min})},
Special case of real functions in time for fermions
----------------------------------------------------
In this case, :math:`G(i\omega_n)=conj(G(i\omega_n))` and we only store the values of :math:`G(i\omega_n)` for :math:`\omega_n > 0`.
The Eq. :ref:`inv_DFT_I` becomes:
:label: _inv_TF_I_real_fermion
.. math:: G(\tau)=\sum_{n=0}^\infty \frac{2}{\beta} \tilde G(i\omega_n)\cos(\omega_n \tau)
The inverse TF formulas are in this case
.. math:: f_m = \frac{2}{\beta}\tilde G(i\omega_n) e^{-i t_{min}\omega_n},
.. math:: G(t_k) = \tilde f_k e^{-i \omega_{min}(\tau_k-\tau_{min})},
Special case of real functions in time for bosons
--------------------------------------------------
In this case, :math:`G(i\omega_n)=conj(G(i\omega_n))` and we only store the values of :math:`G(i\omega_n)` for :math:`\omega_n \ge 0`.
The Eq. :ref:`inv_DFT_I` becomes:
:label: _inv_TF_I_real_bosons
.. math:: G(\tau)=\frac{1}{\beta} \tilde G(0)+\sum_{n=1}^\infty \frac{2}{\beta} \tilde G(i\omega_n)\cos(\omega_n \tau)
The inverse TF formulas are in this case
.. math:: f_0 = \frac{1}{\beta}\tilde G(0),
.. math:: f_m = \frac{2}{\beta}\tilde G(i\omega_n) \cos(t_{min}\omega_n),
.. math:: G(t_k) = \tilde f_k e^{-i \omega_{min}(\tau_k-\tau_{min})},
Effect of a TF on the tail Effect of a TF on the tail
=========================== ===========================

View File

@ -25,9 +25,63 @@ Briefly, if we want to describe a function on an interval:
We then have to be careful for example when we fourier transform the function (to not take twice the same point). We then have to be careful for example when we fourier transform the function (to not take twice the same point).
How to access to a mesh point with its index
---------------------------------------------
The four basic meshes .. compileblock::
=====================
#include <triqs/gf/refreq.hpp>
using namespace triqs::gf;
int main() {
//we construct a GF
double wmin = 0.0;
double wmax = 1.0;
int nw = 101;
auto Gw = make_gf<refreq, scalar_valued>(wmin, wmax, nw);
//we print the mesh parameters and print te value of the 10th point
std::cout << "The kind of the mesh is " << Gw.mesh().kind() << std::endl;
std::cout << "The smallest mesh point value is w_min=" << Gw.mesh().x_min() << std::endl;
std::cout << "The largest mesh point value is w_max=" << Gw.mesh().x_max() << std::endl;
std::cout << "The number of mesh points is n=" << Gw.mesh().size() << std::endl;
std::cout << "Between two consecutive mesh points: delta=" << Gw.mesh().delta() << std::endl;
std::cout << "The 10th mesh point is w=" << Gw.mesh()[10] << std::endl;
}
How to access to a mesh point with a value
-------------------------------------------
In this case, we look for the closest mesh point, but can need the distance of the value to the mesh point.
``windowing`` gives all these informations:
.. compileblock::
#include <triqs/gf/refreq.hpp>
using namespace triqs::gf;
int main() {
double wmin = 0.0;
double wmax = 1.0;
int nw=101;
auto Gw= make_gf<refreq, scalar_valued>(wmin, wmax, nw);
double w=0.25156;
size_t index; double wd; bool in;
std::tie(in, index, wd) = windowing ( Gw.mesh(), w);
std::cout << "Is the point w="<< w <<" in the mesh range ? " << in << std::endl;
if(in){
std::cout << "The point before is the " << index << "th" << std::endl;
std::cout << "The position in the intervall is " << wd << std::endl;
}
}
The four basic linear meshes
============================
Real time Real time
@ -60,7 +114,57 @@ Depending on what one needs, we can choose ``full_bins``, ``half_bins`` or ``w
Matsubara frequency Matsubara frequency
-------------------- --------------------
The domain is discrete. The Matsubara frequencies are :math:`\omega_n=\frac{(2n+1)\pi}{beta}` for fermions and :math:`\omega_n=\frac{2n\pi}{beta}` for bosons. The domain is discrete. The Matsubara frequencies are :math:`\omega_n=\frac{(2n+1)\pi}{\beta}` for fermions and :math:`\omega_n=\frac{2n\pi}{\beta}` for bosons.
Products of meshes
===================
We detail the case of a two mesh product, but what follows is true for any number of meshes.
A mesh point can be labelled by a linear index, or by a tuple of indices. Each mesh point correspond to a point of the domain, which is a tuple of points of the subdomains.
We can navigate between these representations, through ``closest_mesh_pt``, ``get_closest_pt``, ``index_to_linear``,...
How to access to the closest mesh point
---------------------------------------
.. compileblock::
#include <triqs/gf/two_real_times.hpp>
using namespace triqs::gf;
int main() {
double tmax = 1.0;
int nt = 101;
auto Gtt = make_gf<two_real_times>(tmax, nt, triqs::arrays::make_shape(1,1));
//does not work for instance
//double t1 = 0.256, t2 = 0.758;
//Gtt(closest_mesh_pt(i1,i2)) = 1.5;
}
How to access to a mesh point with its index
---------------------------------------------
.. compileblock::
#include <triqs/gf/two_real_times.hpp>
using namespace triqs::gf;
int main() {
double tmax = 1.0;
int nt = 101;
auto Gtt = make_gf<two_real_times>(tmax, nt, triqs::arrays::make_shape(1,1));
int i1 = 14, i2 = 86;
Gtt.on_mesh(i1, i2) = 1.8;
std::cout << Gtt.on_mesh(i1, i2)(0,0) << std::endl;
}