mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 13:53:40 +01:00
doc : gf, fourier,meshes
This commit is contained in:
parent
71c709b0ba
commit
76d74ce0da
@ -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
|
||||||
===========================
|
===========================
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user