# 9. Green’s function¶

Green’s function methods were used briefly in the Fields and effects and Defects and strain sections. As with the eigensolvers, there is one common Greens interface while the underlying algorithm may be implemented in various ways. At this time, kpm() is the only one that comes with the package.

Download this page as a Jupyter notebook

## 9.1. KPM¶

The kpm() implementation is a very efficient way of calculating Green’s function, especially for large sparse Hamiltonian matrices. Based on the kernel polynomial method, the approach approximates the Green’s function by expanding it into a series of Chebyshev polynomials. For more information, see the references linked here and here.

A great advantage of this method is that memory usage and computation time scale linearly with problem dimension. In addition, computation time can be tuned based on the required accuracy which is conveniently expressed as a Lorentzian broadening width. Finally, each spatial site can be computed separately which means local properties can be calculated efficiently at a fraction of the time required for the entire system.

## 9.2. Greens interface¶

The interface is quite simple. A Greens function is created with the desired implementation:

model = pb.Model(graphene.monolayer())
greens = pb.greens.kpm(model)


It can then be used to calculate the Green’s function corresponding to Hamiltonian matrix element i,j for the desired energy range and broadening:

g_ij = greens(i, j, energy=np.linspace(-9, 9, 100), broadening=0.1)


The result is the raw Green’s function data for the given matrix element. However, there is also a convenient Greens.calc_ldos() method which makes it very easy to calculate the local density of states (LDOS). In the next example we’ll use a large square sheet of pristine graphene:

from pybinding.repository import graphene

model = pb.Model(
graphene.monolayer(),
pb.rectangle(60)
)
greens = pb.greens.kpm(model)
ldos = greens.calc_ldos(energy=np.linspace(-9, 9, 200), broadening=0.05, position=[0, 0])
ldos.plot()


The LDOS is calculated for energies between -9 and 9 eV with a Lorentzian broadening of 50 meV. Since this is the local density of states, position is also a required argument. We target the center of our square system where we expect to see the well-known LDOS shape of pristine graphene. Indeed, that is what the resulting LDOS object shows after invoking its plot() method.

Tight-binding systems have lattice sites at discrete positions, which in principle means that we cannot freely choose just any position for LDOS calculations. However, as a convenience the Greens.calc_ldos() method will automatically find a valid site closest to the given target position. We can optionally also choose a specific sublattice:

ldos = greens.calc_ldos(energy=np.linspace(-9, 9, 200), broadening=0.05,
position=[0, 0], sublattice='B')


In this case we would calculate the LDOS at a site of sublattice B closest to the center of the system. We can try that on a graphene system with a mass term:

model = pb.Model(
graphene.monolayer(),
graphene.mass_term(1),
pb.rectangle(60)
)
greens = pb.greens.kpm(model)

for sub_name in ['A', 'B']:
ldos = greens.calc_ldos(energy=np.linspace(-9, 9, 500), broadening=0.05,
position=[0, 0], sublattice=sub_name)
ldos.plot(label=sub_name)
pb.pltutils.legend()


Multiple plots compose nicely here. A large band gap is visible at zero energy due to the inclusion of graphene.mass_term(). It places an onsite potential with the opposite sign in each sublattice. This is also why the LDOS lines for A and B sublattices are antisymmetric around zero energy with respect to one another.

For an additional examples see the Magnetic field subsection of Fields and effects as well as the Strain modifier subsection of Defects and strain. The reference page for the greens submodule contains more information.