# Green’s functions

The gfs class of TRIQS contains objects representing Green functions over real or imaginary times, real or imaginary frequencies… that can be easily manipulated at the C++ level. Here are a couple of simple examples showing the basic use of this class. Learn more in the full reference.

## Matsubara Green’s functions

### Creation of a simple Green’s function $$G(i\omega)$$

In this example, we show how to initialize the following Green’s functions:

$G(i\omega) = \frac{1}{i\omega -3}$
#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;
using nda::clef::placeholder;

int main() {

// Create a Matsubara-frequency mesh
double beta  = 1;   // inverse temperature
int n_iw     = 100; // number of Matsubara frequencies
auto iw_mesh = mesh::imfreq{beta, Fermion, n_iw};

// Create and fill a 1x1 Matsubara Green function
auto g = gf{iw_mesh, {1, 1}};
placeholder<0> iw_;
g[iw_] << 1 / (iw_ - 3);
std::cout << g(0) << std::endl;

// An equivalent way to initialize
g() = 0.0;
for (auto w : g.mesh()) g[w] = 1 / (w - 3);
std::cout << g(0) << std::endl;

//an incorrect way : throws exception as expected
//g(w) returns a const_view: () are to be used for interpolation, see bottom of the page
//for (auto w : g.mesh())  g(w) = 1/(w-3);
}


### Two-frequency Green’s function $$G(i\omega,i\nu)$$

In this example, we show how to initialize the following Green’s functions:

$G(i\omega, i\nu) = \frac{1}{i\omega + i\nu -4}$
#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;
using nda::clef::placeholder;

int main() {

// Create a Matsubara-frequency mesh
double beta  = 1;   // inverse temperature
int n_iw     = 100; // number of Matsubara frequencies
auto iw_mesh = mesh::imfreq{beta, Fermion, n_iw};

// Create and fill a 1x1 Matsubara Green function on the product mesh
auto g2 = gf{iw_mesh * iw_mesh, {1, 1}};

//the shortest way to fill a gf
placeholder<0> iw_;
placeholder<1> inu_;
g2[iw_, inu_] << 1 / (iw_ + inu_ - 4);
std::cout << g2(0, 0) << std::endl;

// An equivalent way to initialize
g2() = 0.0;
for (auto [w, nu] : g2.mesh()) g2[w, nu] = 1 / (w + nu - 4);
std::cout << g2(0, 0) << std::endl;
}


## Imaginary-time Green’s functions $$G(\tau)$$

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Create a imaginary-time mesh
double beta   = 1;
int n_times   = 101; // number of time-points
auto tau_mesh = mesh::imtime{beta, Fermion, n_times};

// Create a scalar-valued Green function g[tau] on the tau_mesh
auto g = gf<imtime, scalar_valued>{tau_mesh};
}


## Real-time Green’s functions $$G(t)$$

Here we create a GF defined on the time interval from tmin to tmax. If we want the value of the GF at any time to be a scalar, we use:

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Create a real-time mesh
double tmin = 0, tmax = 10; // the time interval
int n_times = 101;          // number of time-points
auto t_mesh = mesh::retime{tmin, tmax, n_times};

// Create a scalar-valued Green function on the t_mesh
auto g = gf<retime, scalar_valued>{t_mesh};
}


If we need a matrix of size n by m, we use:

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Create a real-time mesh on interval [tmin, tmax]
double tmin = 0, tmax = 10;
int n_times = 101; // number of time-points
auto t_mesh = mesh::retime{tmin, tmax, n_times};

// Create a scalar-valued Green function on the t_mesh
auto g = gf<retime, scalar_valued>{t_mesh};

// Create a nxm matrix-valued Green function on the t_mesh
const int n = 2, m = 2;
auto gm = gf<retime, matrix_valued>{t_mesh, {n, m}};
}


Or a tensor!

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Number of time-points to be used
int n_times = 101;

// Create a real-time mesh on interval [tmin, tmax]
double tmin = 0, tmax = 10;
auto t_mesh = mesh::retime{tmin, tmax, n_times};

// Create a imaginary-time mesh
double beta   = 1;
auto tau_mesh = mesh::imtime{beta, Fermion, n_times};

// Create Green function g[t,tau] on product-mesh with values of shape (2,2,2)
auto g = gf<prod<retime, imtime>, tensor_valued<3>>{t_mesh * tau_mesh, {2, 2, 2}};
}


### Creation of a two real time GF $$G(t,t')$$

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Create a real-time mesh on the interval [tmin, tmax]
double tmin = 0, tmax = 10;
int n_times = 101; // number of time-points
auto t_mesh = mesh::retime{tmin, tmax, n_times};

// Create a scalar-valued Green function g[t1,t2] on the product-mesh and initialize
auto g = gf<prod<retime, retime>, scalar_valued>{t_mesh * t_mesh};
}


### How to fill a GF with placeholders

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Create a real-time mesh on the interval [tmin, tmax]
double tmin = 0, tmax = 10;
int n_times = 101; // number of time-points
auto t_mesh = mesh::retime{tmin, tmax, n_times};

// Create a scalar-valued Green function g[t1,t2] on the product-mesh and initialize
auto g = gf<prod<retime, retime>, scalar_valued>{t_mesh * t_mesh};
nda::clef::placeholder<0> t1_;
nda::clef::placeholder<1> t2_;
g[t1_, t2_] << 2 * t1_;
}


### How to interpolate the GF value at a point of the domain

You simply have to call the GF with the coordinates of the point:

#include <triqs/gfs.hpp>
#include <triqs/mesh.hpp>
using namespace triqs;
using namespace triqs::gfs;

int main() {
// Create a real-time mesh on the interval [tmin, tmax]
double tmin = 0, tmax = 10;
int n_times = 101; // number of time-points
auto t_mesh = mesh::retime{tmin, tmax, n_times};

// Create a scalar-valued Green function g[t1,t2] on the product-mesh and initialize
auto g = gf<prod<retime, retime>, scalar_valued>{t_mesh * t_mesh};
nda::clef::placeholder<0> t1_;
nda::clef::placeholder<1> t2_;
g[t1_, t2_] << 2 * t1_;

// Interpolate to obtain value in the domain
std::cout << g(0.24, 0.36) << std::endl;
}